DISK: Add RT11 file system disk size detection

This commit is contained in:
John Forecast 2019-05-09 16:16:31 -07:00 committed by Mark Pizzolato
parent 39f36f273b
commit e47a7e9ef7
2 changed files with 205 additions and 0 deletions

View file

@ -225,6 +225,8 @@ Host platforms which have libSDL available can leverage this functionality.
#### Disk Extensions
RAW Disk Access (including CDROM)
Virtual Disk Container files, including differencing disks
File System type detection to accurately autosize disks.
Recognized file systems are: DEC ODS1, DEC ODS2, DEC RT11, Ultrix Partitions
#### Tape Extensions
AWS format tape support

View file

@ -1304,6 +1304,204 @@ uptr->capac = saved_capac;
return ret_val;
}
#pragma pack(push,1)
typedef struct _RT11_HomeBlock {
uint8 hb_b_bbtable[130];
uint8 hb_b_unused1[2];
uint8 hb_b_initrestore[38];
uint8 hb_b_bup[18];
uint8 hb_b_unused2[260];
uint16 hb_w_reserved1;
uint16 hb_w_reserved2;
uint8 hb_b_unused3[14];
uint16 hb_w_clustersize;
uint16 hb_w_firstdir;
uint16 hb_w_sysver;
#define HB_C_SYSVER_V3A 36521
#define HB_C_SYSVER_V04 36434
#define HB_C_SYSVER_V05 36435
uint8 hb_b_volid[12];
uint8 hb_b_owner[12];
uint8 hb_b_sysid[12];
#define HB_C_SYSID "DECRT11A "
uint8 hb_b_unused4[2];
uint16 hb_w_checksum;
} RT11_HomeBlock;
typedef struct _RT11_DirHeader {
uint16 dh_w_count;
uint16 dh_w_next;
uint16 dh_w_highest;
#define DH_C_MAXSEG 31
uint16 dh_w_extra;
uint16 dh_w_start;
} RT11_DirHeader;
typedef struct _RT11_DirEntry {
uint16 de_w_status;
#define DE_C_PRE 0000020
#define DE_C_TENT 0000400
#define DE_C_EMPTY 0001000
#define DE_C_PERM 0002000
#define DE_C_EOS 0004000
#define DE_C_READ 0040000
#define DE_C_PROT 0100000
uint16 de_w_fname1;
uint16 de_w_fname2;
uint16 de_w_ftype;
uint16 de_w_length;
uint16 de_w_jobchannel;
uint16 de_w_creationdate;
} RT11_DirEntry;
#pragma pack(pop)
#define RT11_MAXPARTITIONS 256 /* Max partitions supported */
#define RT11_HOME 1 /* Home block # */
#define RT11_NOPART 0
#define RT11_SINGLEPART 1
#define RT11_MULTIPART 2
static int rt11_get_partition_type(RT11_HomeBlock *home, int part)
{
if (strncmp((char *)&home->hb_b_sysid, HB_C_SYSID, strlen(HB_C_SYSID)) == 0) {
uint16 type = home->hb_w_sysver;
if (part == 0) {
if ((type == HB_C_SYSVER_V3A) || (type == HB_C_SYSVER_V04))
return RT11_SINGLEPART;
}
if (type == HB_C_SYSVER_V05)
return RT11_MULTIPART;
}
return RT11_NOPART;
}
static t_offset get_rt11_filesystem_size (UNIT *uptr)
{
DEVICE *dptr;
t_addr saved_capac;
struct disk_context *ctx = (struct disk_context *)uptr->disk_ctx;
t_offset temp_capac = 512 * (t_offset)0xFFFFFFFFu;
uint32 capac_factor;
uint8 sector_buf[1024];
RT11_HomeBlock Home;
RT11_DirHeader *dir_hdr = (RT11_DirHeader *)sector_buf;
int partitions = 0;
int part;
uint32 base;
uint32 dir_sec;
uint16 dir_seg;
uint16 version;
t_offset ret_val = (t_offset)-1;
if ((dptr = find_dev_from_unit (uptr)) == NULL)
return ret_val;
capac_factor = ((dptr->dwidth / dptr->aincr) == 16) ? 2 : 1;
saved_capac = uptr->capac;
uptr->capac = (t_addr)(temp_capac / (capac_factor * ((dptr->flags & DEV_SECTORS) ? 512 : 1)));
for (part = 0; part < RT11_MAXPARTITIONS; part++) {
uint16 seg_highest;
int type;
base = part << 16;
if (sim_disk_rdsect(uptr, (base + RT11_HOME) * (512 / ctx->sector_size), (uint8 *)&Home, NULL, 512 / ctx->sector_size))
goto Return_Cleanup;
type = rt11_get_partition_type(&Home, part);
if (type != RT11_NOPART) {
uint16 highest = 0;
uint8 seg_seen[DH_C_MAXSEG + 1];
memset(seg_seen, 0, sizeof(seg_seen));
partitions++;
dir_seg = 1;
do {
int offset = sizeof(RT11_DirHeader);
int dir_size = sizeof(RT11_DirEntry);
uint16 cur_blk;
if (seg_seen[dir_seg]++ != 0)
goto Next_Partition;
dir_sec = Home.hb_w_firstdir + ((dir_seg - 1) * 2);
if (sim_disk_rdsect(uptr, (base + dir_sec) * (512 / ctx->sector_size), sector_buf, NULL, 1024 / ctx->sector_size))
goto Return_Cleanup;
if (dir_seg == 1) {
seg_highest = dir_hdr->dh_w_highest;
if (seg_highest > DH_C_MAXSEG)
goto Next_Partition;
}
dir_size += dir_hdr->dh_w_extra;
cur_blk = dir_hdr->dh_w_start;
while ((1024 - offset) >= dir_size) {
RT11_DirEntry *dir_entry = (RT11_DirEntry *)&sector_buf[offset];
if (dir_entry->de_w_status & DE_C_EOS)
break;
/*
* Within each directory segment the bas address should never
* decrease.
*/
if (((cur_blk + dir_entry->de_w_length) & 0xFFFF) < cur_blk)
goto Next_Partition;
cur_blk += dir_entry->de_w_length;
offset += dir_size;
}
if (cur_blk > highest)
highest = cur_blk;
dir_seg = dir_hdr->dh_w_next;
if (dir_seg > seg_highest)
goto Next_Partition;
} while (dir_seg != 0);
ret_val = (t_offset)((base + highest) * 512);
version = Home.hb_w_sysver;
if (type == RT11_SINGLEPART)
break;
}
Next_Partition:
}
Return_Cleanup:
if (partitions) {
if (!sim_quiet) {
char *parttype = "???";
switch (version) {
case HB_C_SYSVER_V3A:
parttype = "V3A";
break;
case HB_C_SYSVER_V04:
parttype = "V04";
break;
case HB_C_SYSVER_V05:
parttype = "V05";
break;
}
sim_printf ("%s%d: '%s' Contains RT11 partitions\n", sim_dname (dptr), (int)(uptr-dptr->units), uptr->filename);
sim_printf ("%d valid partition%s, Type: %s, Sectors On Disk: %u\n", partitions, partitions == 1 ? "" : "s", parttype, (uint32)(ret_val / 512));
}
}
uptr->capac = saved_capac;
return ret_val;
};
typedef t_offset (*FILESYSTEM_CHECK)(UNIT *uptr);
static t_offset get_filesystem_size (UNIT *uptr)
@ -1312,6 +1510,11 @@ static FILESYSTEM_CHECK checks[] = {
&get_ods2_filesystem_size,
&get_ods1_filesystem_size,
&get_ultrix_filesystem_size,
&get_rt11_filesystem_size, /* This should be the last entry
in the table to reduce the
possibility of matching an RT-11
container file stored in another
filesystem */
NULL
};
t_offset ret_val;