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
This commit is contained in:
@@ -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 ;
|
||||
|
||||
@@ -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 <partitioning_system>amiga_rdb : userland partitioning_systems :
|
||||
amiga_rdb.cpp
|
||||
;
|
||||
|
||||
LinkSharedOSLibs <partitioning_system>amiga_rdb :
|
||||
libkernelland_emu.so
|
||||
libdisk_device_manager.so
|
||||
;
|
||||
@@ -0,0 +1,202 @@
|
||||
/*
|
||||
** Copyright 2003, Axel Dörfler, [email protected]. All rights reserved.
|
||||
** Distributed under the terms of the OpenBeOS License.
|
||||
*/
|
||||
|
||||
|
||||
#include "amiga_rdb.h"
|
||||
#include <ByteOrder.h>
|
||||
#include <ddm_modules.h>
|
||||
#include <DiskDeviceTypes.h>
|
||||
#include <KernelExport.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
#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
|
||||
};
|
||||
|
||||
@@ -0,0 +1,175 @@
|
||||
/*
|
||||
** Copyright 2003, Axel Dörfler, [email protected]. 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 */
|
||||
|
||||
Reference in New Issue
Block a user