3b2: Support for additional hard disk geometries

This commit adds support for the following emulated hard disks:

   HD30       30 MB CDC Wren 94155-36
   HD72       73 MB CDC Wren II 94156-86
   HD72C      72 MB Fujitsu M2243AS
   HD135     161 MB Maxtor XT1190
This commit is contained in:
Seth Morabito 2017-12-13 16:30:37 -08:00
parent 5a19a6b12c
commit 2fdf6bd1d7
2 changed files with 114 additions and 47 deletions

View file

@ -29,30 +29,17 @@
*/
/*
* The larger of the two hard drive options shipped with the AT&T 3B2
* was a 72MB Wren II ST-506 MFM hard disk. That's what we emulate
* here, as a start.
* This file contains the code for the Integrated Disk (ID) controller
* (based on the uPD7261) and up to two winchester hard disks.
*
* Formatted Capacity: 76,723,200 Bytes
*
* Cylinders: 925
* Sectors/Track: 18
* Heads: 9
* Bytes/Sector: 512
* Avg. seek: 28 ms
* Seek/track: 5 ms
*
* Drive Information from the 3B2 FAQ:
*
* Drive type drv id cyls trk/cyl sec/trk byte/cyl abbrev
* --------------- ------ ---- ------- ------- -------- ------
* Wren II 30MB 3 697 5 18 512 HD30
* Wren II 72MB 5 925 9 18 512 HD72
* Fujitsu M2243AS 8 754 11 18 512 HD72C
* Micropolis 1325 5 1024 8 18 512 HD72
* Maxtor 1140 4* 918= 15 18 512 HD120
* Maxtor 1190 11 1224+ 15 18 512 HD135
* Supported winchester drives are:
*
* SIMH Name ID Cyl Head Sec Byte/Sec Note
* --------- -- ---- ---- --- -------- ----------------------
* HD30 3 697 5 18 512 CDC Wren 94155-36
* HD72 5 925 9 18 512 CDC Wren II 94156-86
* HD72C 8 754 11 18 512 Fujitsu M2243AS
* HD135 11 1224 15 18 512 Maxtor XT1190
*/
#include <assert.h>
@ -80,11 +67,6 @@
/* The catch-all command wait time is about 140 us */
#define ID_CMD_WAIT 140 /* us */
/* State. The DP7261 supports four MFM (winchester) disks connected
simultaneously. There is only one set of registers, however, so
commands must be completed for one unit before they can begin on
another unit. */
/* Data FIFO pointer - Read */
uint8 id_dpr = 0;
/* Data FIFO pointer - Write */
@ -139,10 +121,25 @@ uint8 id_idfield_ptr = 0;
uint8 id_seek_state[ID_NUM_UNITS] = {ID_SEEK_NONE};
struct id_dtype {
uint8 hd; /* Number of heads */
uint32 capac; /* Capacity (in sectors) */
};
static struct id_dtype id_dtab[] = {
ID_DRV(HD30),
ID_DRV(HD72),
ID_DRV(HD72C),
ID_DRV(HD135),
{ 0 }
};
UNIT id_unit[] = {
{ UDATA (&id_unit_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_BINK, ID_DSK_SIZE), 0, ID0, 0 },
{ UDATA (&id_unit_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_BINK, ID_DSK_SIZE), 0, ID1, 0 },
{ UDATA (&id_ctlr_svc, UNIT_FIX+UNIT_BINK, 0) },
{ UDATA (&id_unit_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_BINK+
(ID_HD72_DTYPE << ID_V_DTYPE), ID_DSK_SIZE(HD72)), 0, ID0, 0 },
{ UDATA (&id_unit_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_BINK+
(ID_HD72_DTYPE << ID_V_DTYPE), ID_DSK_SIZE(HD72)), 0, ID1, 0 },
{ UDATA (&id_ctlr_svc, 0, 0) },
{ NULL }
};
@ -158,8 +155,20 @@ REG id_reg[] = {
{ NULL }
};
MTAB id_mod[] = {
{ MTAB_XTD|MTAB_VUN, ID_HD30_DTYPE, NULL, "HD30",
&id_set_type, NULL, NULL, "Set HD30 Disk Type" },
{ MTAB_XTD|MTAB_VUN, ID_HD72_DTYPE, NULL, "HD72",
&id_set_type, NULL, NULL, "Set HD72 Disk Type" },
{ MTAB_XTD|MTAB_VUN, ID_HD72C_DTYPE, NULL, "HD72C",
&id_set_type, NULL, NULL, "Set HD72C Disk Type" },
{ MTAB_XTD|MTAB_VUN, ID_HD135_DTYPE, NULL, "HD135",
&id_set_type, NULL, NULL, "Set HD135 Disk Type" },
{ 0 }
};
DEVICE id_dev = {
"ID", id_unit, id_reg, NULL,
"ID", id_unit, id_reg, id_mod,
ID_NUM_UNITS, 16, 32, 1, 16, 8,
NULL, NULL, &id_reset,
NULL, &id_attach, &id_detach, NULL,
@ -332,6 +341,24 @@ t_stat id_unit_svc(UNIT *uptr)
return SCPE_OK;
}
t_stat id_set_type(UNIT *uptr, int32 val, CONST char *cptr, void *desc)
{
t_stat r;
if (val < 0 || val > ID_MAX_DTYPE) {
return SCPE_ARG;
}
if (uptr->flags & UNIT_ATT) {
return SCPE_ALATT;
}
uptr->flags = (uptr->flags & ~ID_DTYPE) | (val << ID_V_DTYPE);
uptr->capac = (t_addr)id_dtab[val].capac;
return SCPE_OK;
}
t_stat id_reset(DEVICE *dptr)
{
id_clear_fifo();
@ -349,9 +376,13 @@ t_stat id_detach(UNIT *uptr)
}
/* Return the logical block address of the given sector */
static SIM_INLINE t_lba id_lba(uint16 cyl, uint8 head, uint8 sec)
static t_lba id_lba(uint16 cyl, uint8 head, uint8 sec)
{
return((ID_SEC_CNT * ID_HEADS * cyl) +
uint8 dtype;
dtype = ID_GET_DTYPE(id_sel_unit->flags);
return((ID_SEC_CNT * id_dtab[dtype].hd * cyl) +
(ID_SEC_CNT * head) +
sec);
}
@ -911,14 +942,22 @@ void id_drq_handled()
CONST char *id_description(DEVICE *dptr)
{
return "72MB MFM Hard Disk";
return "MFM Hard Disk Controller";
}
t_stat id_help(FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr)
{
fprintf(st, "72MB MFM Integrated Hard Disk (ID)\n\n");
fprintf(st,
"The ID controller implements the integrated MFM hard disk controller\n"
"of the 3B2/400. Up to two drives are supported on a single controller.\n");
fprintf(st, "Integrated Hard Disk (ID)\n\n");
fprintf(st, "The ID device implements the integrated MFM hard disk controller\n");
fprintf(st, "of the 3B2/400. Up to two drives are supported on a single controller.\n\n");
fprintf(st, "Supported device types are:\n\n");
fprintf(st, " Name Size ID Cyl Head Sec Byte/Sec Description\n");
fprintf(st, " ---- -------- -- ---- ---- --- -------- ----------------------\n");
fprintf(st, " HD30 30.6 MB 3 697 5 18 512 CDC Wren 94155-36\n");
fprintf(st, " HD72 73.2 MB 5 925 9 18 512 CDC Wren II 94156-86\n");
fprintf(st, " HD72C 72.9 MB 8 754 11 18 512 Fujitsu M2243AS\n");
fprintf(st, " HD135 161.0 MB 11 1224 15 18 512 Maxtor XT1190\n\n");
fprintf(st, "The drive ID and geometry values are used when low-level formatting a\n");
fprintf(st, "drive using the AT&T 'idtools' utility.\n");
return SCPE_OK;
}

View file

@ -102,13 +102,43 @@
#define ID_SEEK_0 0
#define ID_SEEK_1 1
/* Geometry */
/* Drive Geometries */
#define ID_CYL 925
#define ID_SEC_SIZE 512 /* Bytes per sector */
#define ID_SEC_CNT 18 /* Sectors per track */
#define ID_HEADS 9
#define ID_CYL_SIZE ID_SEC_SIZE * ID_SEC_CNT
/* Common across all drive types */
#define ID_SEC_SIZE 512
#define ID_SEC_CNT 18
#define ID_CYL_SIZE ID_SEC_SIZE * ID_SEC_CNT
/* Specific to each drive type */
#define ID_MAX_DTYPE 3
#define ID_HD30_DTYPE 0
#define ID_HD30_CYL 697
#define ID_HD30_HEADS 5
#define ID_HD30_LBN 62730
#define ID_HD72_DTYPE 1
#define ID_HD72_CYL 925
#define ID_HD72_HEADS 9
#define ID_HD72_LBN 149850
#define ID_HD72C_DTYPE 2
#define ID_HD72C_CYL 754
#define ID_HD72C_HEADS 11
#define ID_HD72C_LBN 149292
#define ID_HD135_DTYPE 3
#define ID_HD135_CYL 1224
#define ID_HD135_HEADS 15
#define ID_HD135_LBN 330480
#define ID_V_DTYPE (DKUF_V_UF + 0)
#define ID_M_DTYPE 3
#define ID_DTYPE (ID_M_DTYPE << ID_V_DTYPE)
#define ID_GET_DTYPE(x) (((x) >> ID_V_DTYPE) & ID_M_DTYPE)
#define ID_DRV(d) { ID_##d##_HEADS, ID_##d##_LBN }
#define ID_DSK_SIZE(d) ID_##d##_LBN
/* Unit, Register, Device descriptions */
@ -125,9 +155,6 @@ extern t_bool id_int();
#define IDBASE 0x4a000
#define IDSIZE 0x2
/* Total disk size, in sectors */
#define ID_DSK_SIZE ID_CYL * ID_SEC_CNT * ID_HEADS
#define CMD_NUM ((id_cmd >> 4) & 0xf)
/* Function prototypes */
@ -136,6 +163,7 @@ t_bool id_int();
t_stat id_ctlr_svc(UNIT *uptr);
t_stat id_unit_svc(UNIT *uptr);
t_stat id_reset(DEVICE *dptr);
t_stat id_set_type(UNIT *uptr, int32 val, CONST char *cptr, void *desc);
t_stat id_attach(UNIT *uptr, CONST char *cptr);
t_stat id_detach(UNIT *uptr);
uint32 id_read(uint32 pa, size_t size);