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 #### Disk Extensions
RAW Disk Access (including CDROM) RAW Disk Access (including CDROM)
Virtual Disk Container files, including differencing disks 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 #### Tape Extensions
AWS format tape support AWS format tape support

View file

@ -1304,6 +1304,204 @@ uptr->capac = saved_capac;
return ret_val; 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); typedef t_offset (*FILESYSTEM_CHECK)(UNIT *uptr);
static t_offset get_filesystem_size (UNIT *uptr) static t_offset get_filesystem_size (UNIT *uptr)
@ -1312,6 +1510,11 @@ static FILESYSTEM_CHECK checks[] = {
&get_ods2_filesystem_size, &get_ods2_filesystem_size,
&get_ods1_filesystem_size, &get_ods1_filesystem_size,
&get_ultrix_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 NULL
}; };
t_offset ret_val; t_offset ret_val;