diff options
Diffstat (limited to 'isys')
-rw-r--r-- | isys/pdc.c | 157 |
1 files changed, 157 insertions, 0 deletions
diff --git a/isys/pdc.c b/isys/pdc.c new file mode 100644 index 000000000..92b968ed4 --- /dev/null +++ b/isys/pdc.c @@ -0,0 +1,157 @@ +/* + pdc: Promise Fake Raid reader + Copyright (C) 2001 + +*/ + +#include <unistd.h> +#include <sys/ioctl.h> +#include <stdio.h> +#include <fcntl.h> +#include <linux/hdreg.h> +#include <linux/fs.h> +#include <string.h> + +typedef unsigned int uint32_t; + +struct promise_raid_conf { + char promise_id[24]; +#define PR_MAGIC "Promise Technology, Inc." + + int32_t dummy_0; + int32_t magic_0; + int32_t dummy_1; + int32_t magic_1; + int16_t dummy_2; + int8_t filler1[470]; + struct { + int32_t flags; /* 0x200 */ +#define PR_F_CONFED 0x00000080 + + int8_t dummy_0; + int8_t disk_number; + int8_t channel; + int8_t device; + int32_t magic_0; + int32_t dummy_1; + int32_t dummy_2; /* 0x210 */ + int32_t disk_secs; + int32_t dummy_3; + int16_t dummy_4; + int8_t status; +#define PR_S_DEFINED 0x01 +#define PR_S_ONLINE 0x02 +#define PR_S_OFFLINE 0x10 + + int8_t type; +#define PR_T_STRIPE 0x00 +#define PR_T_MIRROR 0x01 +#define PR_T_STRIPE_MIRROR 0x04 +#define PR_T_SPAN 0x08 + + u_int8_t total_disks; /* 0x220 */ + u_int8_t raid0_shift; + u_int8_t raid0_disks; + u_int8_t array_number; + u_int32_t total_secs; + u_int16_t cylinders; + u_int8_t heads; + u_int8_t sectors; + int32_t magic_1; + int32_t dummy_5; /* 0x230 */ + struct { + int16_t dummy_0; + int8_t channel; + int8_t device; + int32_t magic_0; + int32_t disk_number; + } disk[8]; + } raid; + int32_t filler2[346]; + uint32_t checksum; +}; + + +long long lseek64(int fd, long long offset, int whence); + +static unsigned long calc_pdcblock_offset (int fd) { + unsigned long lba = 0; + struct hd_big_geometry g; + long sectors; + int sector_size = 1; + + if (ioctl(fd, HDIO_GETGEO_BIG_RAW, &g)) + return -1; + + if (ioctl(fd, BLKGETSIZE, §ors)) + return -1; + + if (ioctl(fd, BLKSSZGET, §or_size)) + return -1; + + sector_size /= 512; + g.cylinders = (sectors / (g.heads * g.sectors)) / sector_size; + + lba = g.cylinders * (g.heads*g.sectors); + lba = lba - g.sectors; + + return lba; +} + + +static int read_disk_sb (int fd, unsigned char *buffer,int bufsize) +{ + int ret = -1; + char bh[4096]; + unsigned long long sb_offset; + + /* + * Calculate the position of the superblock, + * it's at first sector of the last cylinder + */ + sb_offset = calc_pdcblock_offset(fd) * 512; + if (sb_offset == -1) + return -1; + + lseek64(fd, sb_offset, SEEK_SET); + read (fd, buffer, bufsize); + + ret = 0; + + return ret; +} + +static unsigned int calc_sb_csum (unsigned int* ptr) +{ + unsigned int sum; + int count; + + sum = 0; + for (count=0;count<511;count++) + sum += *ptr++; + + return sum; +} + +static int check_disk_sb (void) +{ + return 0; +} + +int pdc_dev_running_raid(int fd) +{ + int i; + struct promise_raid_conf *prom; + unsigned char block[4096]; + + if (read_disk_sb(fd,(unsigned char*)&block,sizeof(block))) + return -1; + + prom = (struct promise_raid_conf*)&block[0]; + + if (!strcmp(prom->promise_id, "Promise Technology, Inc.") && + (prom->checksum == calc_sb_csum((unsigned int*)prom))) + return 1; + + return 0; +} |