From 91b482987276c2d880d320a3bbc1087291735253 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Axel=20D=C3=B6rfler?= Date: Tue, 2 Sep 2003 00:59:45 +0000 Subject: [PATCH] Initial Amiga RDB read-only support. Code itself is tested, but not yet in this "shell" (the new DiskDeviceManager module API). Hope for the best :-) git-svn-id: file:///srv/svn/repos/haiku/trunk/current@4440 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- .../kernel/partitioning_systems/Jamfile | 1 + .../kernel/partitioning_systems/amiga/Jamfile | 14 ++ .../partitioning_systems/amiga/amiga_rdb.cpp | 202 ++++++++++++++++++ .../partitioning_systems/amiga/amiga_rdb.h | 175 +++++++++++++++ 4 files changed, 392 insertions(+) create mode 100644 src/add-ons/kernel/partitioning_systems/amiga/Jamfile create mode 100644 src/add-ons/kernel/partitioning_systems/amiga/amiga_rdb.cpp create mode 100644 src/add-ons/kernel/partitioning_systems/amiga/amiga_rdb.h diff --git a/src/add-ons/kernel/partitioning_systems/Jamfile b/src/add-ons/kernel/partitioning_systems/Jamfile index ba4834c3a6..5cfae65158 100644 --- a/src/add-ons/kernel/partitioning_systems/Jamfile +++ b/src/add-ons/kernel/partitioning_systems/Jamfile @@ -1,3 +1,4 @@ SubDir OBOS_TOP src add-ons kernel partitioning_systems ; SubInclude OBOS_TOP src add-ons kernel partitioning_systems intel ; +SubInclude OBOS_TOP src add-ons kernel partitioning_systems amiga ; diff --git a/src/add-ons/kernel/partitioning_systems/amiga/Jamfile b/src/add-ons/kernel/partitioning_systems/amiga/Jamfile new file mode 100644 index 0000000000..01a51dd0fd --- /dev/null +++ b/src/add-ons/kernel/partitioning_systems/amiga/Jamfile @@ -0,0 +1,14 @@ +SubDir OBOS_TOP src add-ons kernel partitioning_systems amiga ; + +UsePrivateHeaders [ FDirName kernel disk_device_manager ] ; +UsePrivateHeaders [ FDirName storage ] ; + +# For now build a userland version only. +Addon amiga_rdb : userland partitioning_systems : + amiga_rdb.cpp + ; + +LinkSharedOSLibs amiga_rdb : + libkernelland_emu.so + libdisk_device_manager.so + ; diff --git a/src/add-ons/kernel/partitioning_systems/amiga/amiga_rdb.cpp b/src/add-ons/kernel/partitioning_systems/amiga/amiga_rdb.cpp new file mode 100644 index 0000000000..fa20ff6095 --- /dev/null +++ b/src/add-ons/kernel/partitioning_systems/amiga/amiga_rdb.cpp @@ -0,0 +1,202 @@ +/* +** Copyright 2003, Axel Dörfler, axeld@pinc-software.de. All rights reserved. +** Distributed under the terms of the OpenBeOS License. +*/ + + +#include "amiga_rdb.h" +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#define TRACE_AMIGA_RDB 1 +#if TRACE_AMIGA_RDB +# define TRACE(x) printf x +#else +# define TRACE(x) ; +#endif + + +static const char *kPartitionModuleName = "partitioning_systems/amiga/rdb/v1"; + +#if TRACE_AMIGA_RDB +static char * +get_tupel(uint32 id) +{ + static unsigned char tupel[5]; + + tupel[0] = 0xff & (id >> 24); + tupel[1] = 0xff & (id >> 16); + tupel[2] = 0xff & (id >> 8); + tupel[3] = 0xff & (id); + tupel[4] = 0; + for (int16 i = 0;i < 4;i++) { + if (tupel[i] < ' ' || tupel[i] > 128) + tupel[i] = '.'; + } + + return (char *)tupel; +} +#endif + + +status_t +get_next_partition(int fd, rigid_disk_block &rdb, uint32 &cookie, partition_block &partition) +{ + if (cookie == 0) { + // first entry + cookie = rdb.partition_list; + } else if (cookie == 0xffffffff) { + // last entry + return B_ENTRY_NOT_FOUND; + } + + ssize_t bytesRead = read_pos(fd, (off_t)cookie * rdb.block_size, (void *)&partition, + sizeof(partition_block)); + if (bytesRead < (ssize_t)sizeof(partition_block)) + return B_ERROR; + + cookie = partition.next; + return B_OK; +} + + +bool +search_rdb(int fd, rigid_disk_block *_rdb) +{ + rigid_disk_block *rdb; + uint8 buffer[512]; + + for (int32 sector = 0; sector < RDB_LOCATION_LIMIT; sector++) { + ssize_t bytesRead = read(fd, buffer, sizeof(buffer)); + if (bytesRead < (ssize_t)sizeof(buffer)) + return false; + + rdb = (rigid_disk_block *)buffer; + if (rdb->id == RDB_DISK_ID && rdb->summed_longs == sizeof(rigid_disk_block) / sizeof(uint32)) { + // check checksum + uint32 *longs = (uint32 *)buffer; + uint32 sum = 0; + for (uint32 i = 0; i < rdb->summed_longs; i++) + sum += longs[i]; + + if (sum != 0) { + TRACE(("amiga_rdb: check sum is incorrect!\n")); + return false; + } + + *_rdb = *rdb; + return true; + } + } + + return false; +} + + +// #pragma mark - +// AmigaRDB public module interface + + +static status_t +amiga_rdb_std_ops(int32 op, ...) +{ + switch (op) { + case B_MODULE_INIT: + case B_MODULE_UNINIT: + return B_OK; + } + + return B_ERROR; +} + + +static float +amiga_rdb_identify_partition(int fd, partition_data *partition, void **_cookie) +{ + rigid_disk_block *rdb = new rigid_disk_block(); + if (!search_rdb(fd, rdb)) { + delete rdb; + return B_ERROR; + } + + *_cookie = (void *)rdb; + return 0.5f; +} + + +static status_t +amiga_rdb_scan_partition(int fd, partition_data *partition, void *_cookie) +{ + rigid_disk_block &rdb = *(rigid_disk_block *)_cookie; + + partition->status = B_PARTITION_VALID; + partition->flags |= B_PARTITION_PARTITIONING_SYSTEM + | B_PARTITION_READ_ONLY; + partition->content_size = partition->size; + + // scan all children + + partition_block partitionBlock; + uint32 index = 0, cookie = 0; + status_t status; + + while ((status = get_next_partition(fd, rdb, cookie, partitionBlock)) == B_OK) { + disk_environment &environment = *(disk_environment *)&partitionBlock.environment[0]; + TRACE(("amiga_rdb: file system: %s\n", get_tupel(environment.dos_type))); + + partition_data *child = create_child_partition(partition->id, index++, -1); + if (child == NULL) { + TRACE(("Creating child at index %ld failed\n", index - 1)); + return B_ERROR; + } + + child->offset = partition->offset + environment.Start(); + child->size = environment.Size(); + child->block_size = partition->block_size; + } + + if (status == B_ENTRY_NOT_FOUND) + return B_OK; + + return status; +} + + +static void +amiga_rdb_free_identify_partition_cookie(partition_data *partition, void *_cookie) +{ + delete (rigid_disk_block *)_cookie; +} + + +static partition_module_info amiga_rdb_partition_module = { + { + kPartitionModuleName, + 0, + amiga_rdb_std_ops + }, + kPartitionTypeAmiga, // pretty_name + 0, // flags + + // scanning + amiga_rdb_identify_partition, // identify_partition + amiga_rdb_scan_partition, // scan_partition + amiga_rdb_free_identify_partition_cookie, // free_identify_partition_cookie + NULL, +// amiga_rdb_free_partition_cookie, // free_partition_cookie +// amiga_rdb_free_partition_content_cookie, // free_partition_content_cookie +}; + +partition_module_info *modules[] = { + &amiga_rdb_partition_module, + NULL +}; + diff --git a/src/add-ons/kernel/partitioning_systems/amiga/amiga_rdb.h b/src/add-ons/kernel/partitioning_systems/amiga/amiga_rdb.h new file mode 100644 index 0000000000..5b83f8c648 --- /dev/null +++ b/src/add-ons/kernel/partitioning_systems/amiga/amiga_rdb.h @@ -0,0 +1,175 @@ +/* +** Copyright 2003, Axel Dörfler, axeld@pinc-software.de. All rights reserved. +** Distributed under the terms of the OpenBeOS License. +*/ +#ifndef AMIGA_RDB_H +#define AMIGA_RDB_H + + +#include "SupportDefs.h" +#include "ByteOrder.h" + + +struct rigid_disk_block { + uint32 id; + uint32 summed_longs; + int32 check_sum; + uint32 host_id; + uint32 block_size; + uint32 flags; + + /* block list heads */ + + uint32 bad_block_list; + uint32 partition_list; + uint32 fs_header_list; + uint32 drive_init; + + uint32 __reserved1[6]; + + /* physical drive characteristics */ + + uint32 cylinders; + uint32 sectors; + uint32 heads; + uint32 interleave; + uint32 park; + uint32 __reserved2[3]; + uint32 write_precompensation; + uint32 reduced_write; + uint32 step_rate; + uint32 __reserved3[5]; + + /* logical drive characteristics */ + + uint32 rdb_blocks_low; + uint32 rdb_blocks_high; + uint32 low_cylinder; + uint32 high_cylinder; + uint32 cylinder_blocks; + uint32 auto_park_seconds; + + uint32 __reserved4[2]; + + /* drive identification */ + + char disk_vendor[8]; + char disk_product[16]; + char disk_revision[4]; + char controller_vendor[8]; + char controller_product[16]; + char controller_revision[4]; + + uint32 __reserved5[10]; +}; + +#define RDB_DISK_ID 'RDSK' + +#define RDB_LOCATION_LIMIT 16 + +enum rdb_flags { + RDB_LAST = 0x01, + RDB_LAST_LUN = 0x02, + RDB_LAST_TID = 0x04, + RDB_NO_RESELECT = 0x08, + RDB_HAS_DISK_ID = 0x10, + RDB_HAS_CONTROLLER_ID = 0x20, + RDB_SUPPORTS_SYNCHRONOUS = 0x40, +}; + + +/************* bad blocks *************/ + +struct bad_block_entry { +}; + +struct bad_block_block { +}; + +#define RDB_BAD_BLOCK_ID 'BADB' + + +/************* partition block *************/ + +struct partition_block { + uint32 id; + uint32 summed_longs; + int32 check_sum; + uint32 host_id; + uint32 next; + uint32 flags; + uint32 __reserved1[2]; + uint32 open_device_flags; + uint8 drive_name[32]; // BSTR form (Pascal like string) + + uint32 __reserved2[15]; + uint32 environment[17]; + uint32 __reserved3[15]; +}; + +#define RDB_PARTITION_ID 'PART' + +enum rdb_partition_flags { + RDB_PARTITION_BOOTABLE = 0x01, + RDB_PARTITION_NO_MOUNT = 0x02, +}; + + +/************* disk environment *************/ + +struct disk_environment { + uint32 table_size; // size of this environment + uint32 long_block_size; // block size in longs (128 == 512 byte) + uint32 sec_org; // always 0 + uint32 surfaces; + uint32 sectors_per_block; + uint32 blocks_per_track; + uint32 reserved_blocks_at_start; + uint32 reserved_blocks_at_end; + uint32 interleave; + uint32 first_cylinder; + uint32 last_cylinder; + uint32 num_buffers; + uint32 buffer_mem_type; + uint32 max_transfer; + uint32 dma_mask; + int32 boot_priority; + uint32 dos_type; + uint32 baud_rate; + uint32 control; + uint32 boot_blocks; + + uint32 FirstCylinder() { return B_BENDIAN_TO_HOST_INT32(first_cylinder); } + uint32 LastCylinder() { return B_BENDIAN_TO_HOST_INT32(last_cylinder); } + uint32 Surfaces() { return B_BENDIAN_TO_HOST_INT32(surfaces); } + uint32 BlocksPerTrack() { return B_BENDIAN_TO_HOST_INT32(blocks_per_track); } + uint32 LongBlockSize() { return B_BENDIAN_TO_HOST_INT32(long_block_size); } + + uint64 Start() + { + return uint64(FirstCylinder()) * BlocksPerTrack() * Surfaces() + * LongBlockSize() * sizeof(long); + } + + uint64 Size() + { + return uint64(LastCylinder() + 1 - FirstCylinder()) * BlocksPerTrack() * Surfaces() + * LongBlockSize() * sizeof(long); + } +}; + + +/************* file system header block *************/ + +struct fs_header_block { +}; + +#define RDB_FS_HEADER_ID 'FSHD' + +struct load_seg_block { +}; + +#define RDB_LOAD_SEG_ID 'LSEG' + +#endif /* AMIGA_RDB_H */ +