AltairZ80: New iCOM device, PTP port command, code cleanup
This commit is contained in:
parent
26f9c7a748
commit
5211c1134a
13 changed files with 2021 additions and 483 deletions
|
@ -2084,14 +2084,31 @@ static t_stat sim_instr_mmu (void) {
|
||||||
register uint32 cbits;
|
register uint32 cbits;
|
||||||
register uint32 op;
|
register uint32 op;
|
||||||
register uint32 adr;
|
register uint32 adr;
|
||||||
/* tStates contains the number of t-states executed. One t-state is executed
|
|
||||||
in one microsecond on a 1MHz CPU. tStates is used for real-time simulations. */
|
/* The clock frequency simulation works as follows:
|
||||||
register uint32 tStates;
|
For each 8080 or Z80 instruction one can determine the number of t-states
|
||||||
uint32 tStatesInSlice; /* number of t-states in 10 mSec time-slice */
|
needed for its execution. One t-state is executed in one microsecond on a
|
||||||
|
1MHz CPU. The variable sliceLength defines a time interval of typically
|
||||||
|
10 ms. When the clock frequency (clockFrequency) is known one can compute
|
||||||
|
the number of t-states which need to be completed in this slice:
|
||||||
|
tStatesInSlice = sliceLength * clockFrequency. The variable tStates counts
|
||||||
|
how many t-states have already been completed. startTime is initialized
|
||||||
|
with the current time when tStates is 0 at the beginning.
|
||||||
|
|
||||||
|
Periodically there is a check whether tStates >= tStatesInSlice.
|
||||||
|
If this is true case three things happen:
|
||||||
|
|
||||||
|
1. startTime is incremented by sliceLength giving the new expected current time.
|
||||||
|
2. tStates is decremented by tStatesInSlice.
|
||||||
|
3. In case startTime is in the future there is a sleep until startTime
|
||||||
|
is equal to the current time.
|
||||||
|
*/
|
||||||
|
register uint32 tStates; /* number of t-states executed in the current time-slice */
|
||||||
|
uint32 tStatesInSlice; /* number of t-states in a 10 mSec time-slice */
|
||||||
uint32 startTime, now;
|
uint32 startTime, now;
|
||||||
int32 tStateModifier = FALSE;
|
int32 tStateModifier = FALSE;
|
||||||
|
|
||||||
switch_cpu_now = TRUE; /* hharte */
|
switch_cpu_now = TRUE;
|
||||||
|
|
||||||
AF = AF_S;
|
AF = AF_S;
|
||||||
BC = BC_S;
|
BC = BC_S;
|
||||||
|
@ -2127,11 +2144,13 @@ static t_stat sim_instr_mmu (void) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (specialProcessing) { /* quick check for special processing */
|
if (specialProcessing) { /* quick check for special processing */
|
||||||
|
|
||||||
|
/* check for CPU clock frequency simulation + enough t-states executed */
|
||||||
if (clockFrequency && (tStates >= tStatesInSlice)) {
|
if (clockFrequency && (tStates >= tStatesInSlice)) {
|
||||||
/* clockFrequency != 0 implies that real time clock is available */
|
/* clockFrequency != 0 implies that real time clock is available */
|
||||||
startTime += sliceLength;
|
startTime += sliceLength; /* advance start time to new expected current time */
|
||||||
tStates -= tStatesInSlice;
|
tStates -= tStatesInSlice; /* reduce by t-states executed in a slice */
|
||||||
if (startTime > (now = sim_os_msec()))
|
if (startTime > (now = sim_os_msec())) /* if expected time is in the future, sleep */
|
||||||
sim_os_ms_sleep(startTime - now);
|
sim_os_ms_sleep(startTime - now);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -145,7 +145,7 @@
|
||||||
#define UNIT_DSK_WLK (1 << UNIT_V_DSK_WLK)
|
#define UNIT_DSK_WLK (1 << UNIT_V_DSK_WLK)
|
||||||
#define DSK_SECTSIZE 137 /* size of sector */
|
#define DSK_SECTSIZE 137 /* size of sector */
|
||||||
#define DSK_SECT 32 /* sectors per track */
|
#define DSK_SECT 32 /* sectors per track */
|
||||||
#define MAX_TRACKS 254 /* number of tracks,
|
#define MAX_TRACKS 2048 /* number of tracks,
|
||||||
original Altair has 77 tracks only */
|
original Altair has 77 tracks only */
|
||||||
#define DSK_TRACSIZE (DSK_SECTSIZE * DSK_SECT)
|
#define DSK_TRACSIZE (DSK_SECTSIZE * DSK_SECT)
|
||||||
#define MAX_DSK_SIZE (DSK_TRACSIZE * MAX_TRACKS)
|
#define MAX_DSK_SIZE (DSK_TRACSIZE * MAX_TRACKS)
|
||||||
|
|
|
@ -187,6 +187,102 @@ static int32 mits[SPT32] = { 0, 17, 2, 19, 4, 21, 6, 23,
|
||||||
measured in CP/M sectors of size 128 bytes. Standard format "HDSK" must be
|
measured in CP/M sectors of size 128 bytes. Standard format "HDSK" must be
|
||||||
first as index 0 is used as default in some cases.
|
first as index 0 is used as default in some cases.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
The structure of a Disk Parameter Block in CP/M is as follows:
|
||||||
|
|
||||||
|
+---+---+---+---+---+---+---+---+---+---+
|
||||||
|
|SPT|BSH|BLM|EXM|DSM|DRM|AL0|AL1|CKS|OFF|
|
||||||
|
+---+---+---+---+---+---+---+---+---+---+
|
||||||
|
16B 8B 8B 8B 16B 16B 8B 8B 16B 16B
|
||||||
|
|
||||||
|
where each is a byte or word value, as shown by the 8b or 16b indicator
|
||||||
|
below the field.
|
||||||
|
|
||||||
|
The following field abbreviations are used in the figure above:
|
||||||
|
SPT is the total number of sectors per track.
|
||||||
|
BSH is the data allocation block shift factor, determined by
|
||||||
|
the data block allocation size.
|
||||||
|
BLM is the data allocation block mask (2[BSH-1]).
|
||||||
|
EXM is the extent mask, determined by the data block
|
||||||
|
allocation size and the number of disk blocks.
|
||||||
|
DSM determines the total storage capacity of the disk drive.
|
||||||
|
DRM determines the total number of directory entries that
|
||||||
|
can be stored on this drive.
|
||||||
|
AL0, AL1 determine reserved directory blocks.
|
||||||
|
CKS is the size of the directory check vector.
|
||||||
|
|
||||||
|
OFF is the number of reserved tracks at the beginning of the
|
||||||
|
(logical) disk.
|
||||||
|
|
||||||
|
The values of BSH and BLM determine the data allocation size BLS, which is
|
||||||
|
not an entry in the DPB. Given that the designer has selected a value for
|
||||||
|
BLS, the values of BSH and BLM are shown in the following table.
|
||||||
|
|
||||||
|
BLS BSH BLM
|
||||||
|
1,024 3 7
|
||||||
|
2,048 4 15
|
||||||
|
4,096 5 31
|
||||||
|
8,192 6 63
|
||||||
|
16,384 7 127
|
||||||
|
|
||||||
|
where all values are in decimal. The value of EXM depends upon both the BLS
|
||||||
|
and whether the DSM value is less than 256 or greater than 255, as shown in
|
||||||
|
the table below.
|
||||||
|
|
||||||
|
EXM values
|
||||||
|
BLS DSM<256 DSM>255
|
||||||
|
1,024 0 N/A
|
||||||
|
2,048 1 0
|
||||||
|
4,096 3 1
|
||||||
|
8,192 7 3
|
||||||
|
16,384 15 7
|
||||||
|
|
||||||
|
The value of DSM is the maximum data block number supported by this
|
||||||
|
particular drive, measured in BLS units. The product (DSM + 1) is the total
|
||||||
|
number of bytes held by the drive and must be within the capacity of the
|
||||||
|
physical disk, not counting the reserved operating system tracks.
|
||||||
|
|
||||||
|
The DRM entry is the one less than the total number of directory entries
|
||||||
|
that can take on a 16-bit value. The values of AL0 and AL1, however, are
|
||||||
|
determined by DRM. The values AL0 and AL1 can together be considered a
|
||||||
|
string of 16-bits, as shown below.
|
||||||
|
|
||||||
|
|--------- AL0 ---------|-------- AL1 ----------|
|
||||||
|
00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15
|
||||||
|
|
||||||
|
Position 00 corresponds to the high-order bit of the byte labeled AL0 and
|
||||||
|
15 corresponds to the low-order bit of the byte labeled AL1. Each bit
|
||||||
|
position reserves a data block for number of directory entries, thus
|
||||||
|
allowing a total of 16 data blocks to be assigned for directory entries
|
||||||
|
(bits are assigned starting at 00 and filled to the right until position
|
||||||
|
15). Each directory entry occupies 32 bytes, resulting in the following
|
||||||
|
tabulation:
|
||||||
|
|
||||||
|
BLS Directory Entries
|
||||||
|
1,024 32 times # bits
|
||||||
|
2,048 64 times # bits
|
||||||
|
4,096 128 times # bits
|
||||||
|
8,192 256 times # bits
|
||||||
|
16,384 512 times # bits
|
||||||
|
|
||||||
|
Thus, if DRM = 127 (128 directory entries) and BLS = 1024, there are 32
|
||||||
|
directory entries per block, requiring 4 reserved blocks. In this case, the
|
||||||
|
4 high-order bits of AL0 are set, resulting in the values AL0 = 0F0H and
|
||||||
|
AL1 = 00H.
|
||||||
|
|
||||||
|
The CKS value is determined as follows: if the disk drive media is
|
||||||
|
removable, then CKS = (DRM + 1)/4, where DRM is the last directory entry
|
||||||
|
number. If the media are fixed, then set CKS = 0 (no directory records are
|
||||||
|
checked in this case).
|
||||||
|
|
||||||
|
Finally, the OFF field determines the number of tracks that are skipped at
|
||||||
|
the beginning of the physical disk. This value is automatically added
|
||||||
|
whenever SETTRK is called and can be used as a mechanism for skipping
|
||||||
|
reserved operating system tracks or for partitioning a large disk into
|
||||||
|
smaller segmented sections.
|
||||||
|
|
||||||
|
*/
|
||||||
static DPB dpb[] = {
|
static DPB dpb[] = {
|
||||||
/* name capac spt bsh blm exm dsm drm
|
/* name capac spt bsh blm exm dsm drm
|
||||||
al0 al1 cks off psh phm ss off skew */
|
al0 al1 cks off psh phm ss off skew */
|
||||||
|
@ -241,7 +337,10 @@ static DPB dpb[] = {
|
||||||
{ "SSDD8S", 512512, SPT52, 0x04, 0x0F, 0x01, 242, 0x007F,
|
{ "SSDD8S", 512512, SPT52, 0x04, 0x0F, 0x01, 242, 0x007F,
|
||||||
0xC0, 0x00, 0x0000, 0x0002, 0x01, 0x01, 0, 0, standard8 }, /* Standard 8" SS DD with skew */
|
0xC0, 0x00, 0x0000, 0x0002, 0x01, 0x01, 0, 0, standard8 }, /* Standard 8" SS DD with skew */
|
||||||
|
|
||||||
{ "DSDD8", 1025024, SPT52, 0x04, 0x0F, 0x00, 493, 0x007F,
|
{ "DSSD8S", 512512, SPT26, 0x03, 0x07, 0x00, 487, 0x007F,
|
||||||
|
0xF0, 0x00, 0x0000, 0x0004, 0x00, 0x00, 0, 0, standard8 }, /* Standard 8" DS SD with skew */
|
||||||
|
|
||||||
|
{ "DSDD8", 1025024, SPT52, 0x04, 0x0F, 0x00, 493, 0x007F, // psco test
|
||||||
0xC0, 0x00, 0x0000, 0x0002, 0x01, 0x01, 0, 0, NULL }, /* Standard 8" DS DD */
|
0xC0, 0x00, 0x0000, 0x0002, 0x01, 0x01, 0, 0, NULL }, /* Standard 8" DS DD */
|
||||||
|
|
||||||
{ "DSDD8S", 1025024, SPT52, 0x04, 0x0F, 0x00, 493, 0x007F,
|
{ "DSDD8S", 1025024, SPT52, 0x04, 0x0F, 0x00, 493, 0x007F,
|
||||||
|
|
|
@ -138,6 +138,8 @@ static const char* sio_description(DEVICE *dptr);
|
||||||
static const char* simh_description(DEVICE *dptr);
|
static const char* simh_description(DEVICE *dptr);
|
||||||
static const char* ptr_description(DEVICE *dptr);
|
static const char* ptr_description(DEVICE *dptr);
|
||||||
static const char* ptp_description(DEVICE *dptr);
|
static const char* ptp_description(DEVICE *dptr);
|
||||||
|
static t_stat ptpptr_dev_set_port(UNIT *uptr, int32 value, CONST char *cptr, void *desc);
|
||||||
|
static t_stat ptpptr_dev_show_port(FILE *st, UNIT *uptr, int32 val, CONST void *desc);
|
||||||
static void mapAltairPorts(void);
|
static void mapAltairPorts(void);
|
||||||
int32 nulldev (const int32 port, const int32 io, const int32 data);
|
int32 nulldev (const int32 port, const int32 io, const int32 data);
|
||||||
int32 sr_dev (const int32 port, const int32 io, const int32 data);
|
int32 sr_dev (const int32 port, const int32 io, const int32 data);
|
||||||
|
@ -288,6 +290,10 @@ static int32 warnUnassignedPort = 0; /* display a warning message if
|
||||||
int32 keyboardInterrupt = FALSE; /* keyboard interrupt pending */
|
int32 keyboardInterrupt = FALSE; /* keyboard interrupt pending */
|
||||||
uint32 keyboardInterruptHandler = 0x0038;/* address of keyboard interrupt handler */
|
uint32 keyboardInterruptHandler = 0x0038;/* address of keyboard interrupt handler */
|
||||||
|
|
||||||
|
/* PTR/PTP port assignments (read only) */
|
||||||
|
static int32 ptpptrStatusPort = 0x12; /* default status port for PTP/PTR device */
|
||||||
|
static int32 ptpptrDataPort = 0x13; /* default data port for PTP/PTR device */
|
||||||
|
|
||||||
static TMLN TerminalLines[TERMINALS] = { /* four terminals */
|
static TMLN TerminalLines[TERMINALS] = { /* four terminals */
|
||||||
{ 0 }
|
{ 0 }
|
||||||
};
|
};
|
||||||
|
@ -320,7 +326,7 @@ static REG sio_reg[] = {
|
||||||
"BOOL to determine whether terminal input is attached to a file"), REG_RO },
|
"BOOL to determine whether terminal input is attached to a file"), REG_RO },
|
||||||
/* TRUE iff terminal input is attached to a file */
|
/* TRUE iff terminal input is attached to a file */
|
||||||
{ HRDATAD (TSTATUS, sio_unit.u3, 8,
|
{ HRDATAD (TSTATUS, sio_unit.u3, 8,
|
||||||
"BOOL to determine whethere a character is available") },
|
"BOOL to determine whether a character is available") },
|
||||||
/* TRUE iff a character available in sio_unit.buf */
|
/* TRUE iff a character available in sio_unit.buf */
|
||||||
{ DRDATAD (TBUFFER, sio_unit.buf, 8,
|
{ DRDATAD (TBUFFER, sio_unit.buf, 8,
|
||||||
"Input buffer register") },
|
"Input buffer register") },
|
||||||
|
@ -388,6 +394,9 @@ DEVICE sio_dev = {
|
||||||
};
|
};
|
||||||
|
|
||||||
static MTAB ptpptr_mod[] = {
|
static MTAB ptpptr_mod[] = {
|
||||||
|
{ MTAB_XTD|MTAB_VDV, 0, "PORT", "PORT",
|
||||||
|
&ptpptr_dev_set_port, &ptpptr_dev_show_port, NULL,
|
||||||
|
"Set status and data port for PTP/PTR device" },
|
||||||
{ 0 }
|
{ 0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -396,7 +405,9 @@ static UNIT ptr_unit = {
|
||||||
};
|
};
|
||||||
|
|
||||||
static REG ptr_reg[] = {
|
static REG ptr_reg[] = {
|
||||||
{ HRDATAD (STAT, ptr_unit.u3, 8, "Status register") },
|
{ HRDATAD (PTRSTATUSPORT, ptpptrStatusPort, 8, "PTR status port (shared with PTP)"), REG_RO },
|
||||||
|
{ HRDATAD (PTRDATAPORT, ptpptrDataPort, 8, "PTR data port (shared with PTP)"), REG_RO },
|
||||||
|
{ HRDATAD (PTRSTATUS, ptr_unit.u3, 8, "PTR Status register") },
|
||||||
{ NULL }
|
{ NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -417,12 +428,18 @@ static UNIT ptp_unit = {
|
||||||
UDATA (NULL, UNIT_ATTABLE, 0)
|
UDATA (NULL, UNIT_ATTABLE, 0)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static REG ptp_reg[] = {
|
||||||
|
{ HRDATAD (PTPSTATUSPORT, ptpptrStatusPort, 8, "PTP status port (shared with PTR)"), REG_RO },
|
||||||
|
{ HRDATAD (PTPDATAPORT, ptpptrDataPort, 8, "PTP data port (shared with PTR)"), REG_RO },
|
||||||
|
{ NULL }
|
||||||
|
};
|
||||||
|
|
||||||
static const char* ptp_description(DEVICE *dptr) {
|
static const char* ptp_description(DEVICE *dptr) {
|
||||||
return "Paper Tape Puncher";
|
return "Paper Tape Puncher";
|
||||||
}
|
}
|
||||||
|
|
||||||
DEVICE ptp_dev = {
|
DEVICE ptp_dev = {
|
||||||
"PTP", &ptp_unit, NULL, ptpptr_mod,
|
"PTP", &ptp_unit, ptp_reg, ptpptr_mod,
|
||||||
1, 10, 31, 1, 8, 8,
|
1, 10, 31, 1, 8, 8,
|
||||||
NULL, NULL, &ptp_reset,
|
NULL, NULL, &ptp_reset,
|
||||||
NULL, NULL, NULL,
|
NULL, NULL, NULL,
|
||||||
|
@ -992,6 +1009,33 @@ static uint32 equalSIP(SIO_PORT_INFO x, SIO_PORT_INFO y) {
|
||||||
(x.sio_reset == y.sio_reset) && (x.hasOUT == y.hasOUT);
|
(x.sio_reset == y.sio_reset) && (x.hasOUT == y.hasOUT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static t_stat ptpptr_dev_set_port(UNIT *uptr, int32 value, CONST char *cptr, void *desc) {
|
||||||
|
int32 result, n, statusPort, dataPort;
|
||||||
|
if (cptr == NULL)
|
||||||
|
return SCPE_ARG;
|
||||||
|
result = sscanf(cptr, "%x/%x%n", &statusPort, &dataPort, &n);
|
||||||
|
if ((result != 2) || (result == EOF) || (cptr[n] != 0))
|
||||||
|
return SCPE_ARG;
|
||||||
|
if (statusPort != (statusPort & 0xff)) {
|
||||||
|
sim_printf("Truncating status port 0x%x to 0x%02x.\n", statusPort, statusPort & 0xff);
|
||||||
|
statusPort &= 0xff;
|
||||||
|
}
|
||||||
|
if (dataPort != (dataPort & 0xff)) {
|
||||||
|
sim_printf("Truncating data port 0x%x to 0x%02x.\n", dataPort, dataPort & 0xff);
|
||||||
|
dataPort &= 0xff;
|
||||||
|
}
|
||||||
|
sim_map_resource(statusPort, 1, RESOURCE_TYPE_IO, &sio1s, "sio1s", ptp_dev.flags & ptr_dev.flags & DEV_DIS);
|
||||||
|
ptpptrStatusPort = statusPort;
|
||||||
|
sim_map_resource(dataPort, 1, RESOURCE_TYPE_IO, &sio1d, "sio1d", ptp_dev.flags & ptr_dev.flags & DEV_DIS);
|
||||||
|
ptpptrDataPort = dataPort;
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static t_stat ptpptr_dev_show_port(FILE *st, UNIT *uptr, int32 val, CONST void *desc) {
|
||||||
|
fprintf(st, "\n\tStatus port = 0x%02x\n\t Data port = 0x%02x\n", ptpptrStatusPort, ptpptrDataPort);
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
static t_stat sio_dev_set_port(UNIT *uptr, int32 value, CONST char *cptr, void *desc) {
|
static t_stat sio_dev_set_port(UNIT *uptr, int32 value, CONST char *cptr, void *desc) {
|
||||||
int32 result, n, position, isDataPort;
|
int32 result, n, position, isDataPort;
|
||||||
SIO_PORT_INFO sip = { 0 }, old;
|
SIO_PORT_INFO sip = { 0 }, old;
|
||||||
|
|
|
@ -68,6 +68,7 @@ extern DEVICE hdc1001_dev;
|
||||||
|
|
||||||
extern DEVICE jade_dev;
|
extern DEVICE jade_dev;
|
||||||
extern DEVICE tarbell_dev;
|
extern DEVICE tarbell_dev;
|
||||||
|
extern DEVICE icom_dev;
|
||||||
extern DEVICE m2sio0_dev;
|
extern DEVICE m2sio0_dev;
|
||||||
extern DEVICE m2sio1_dev;
|
extern DEVICE m2sio1_dev;
|
||||||
extern DEVICE pmmi_dev;
|
extern DEVICE pmmi_dev;
|
||||||
|
@ -127,6 +128,8 @@ DEVICE *sim_devices[] = {
|
||||||
&jade_dev,
|
&jade_dev,
|
||||||
/* Tarbell Devices */
|
/* Tarbell Devices */
|
||||||
&tarbell_dev,
|
&tarbell_dev,
|
||||||
|
/* iCOM Devices */
|
||||||
|
&icom_dev,
|
||||||
/* MITS 88-2SIO */
|
/* MITS 88-2SIO */
|
||||||
&m2sio0_dev,
|
&m2sio0_dev,
|
||||||
&m2sio1_dev,
|
&m2sio1_dev,
|
||||||
|
|
|
@ -365,7 +365,7 @@ static t_stat m2sio_reset(DEVICE *dptr, int32 (*routine)(const int32, const int3
|
||||||
M2SIO_CTX *xptr;
|
M2SIO_CTX *xptr;
|
||||||
int32 c;
|
int32 c;
|
||||||
|
|
||||||
xptr = dptr->ctxt;
|
xptr = (M2SIO_CTX *) dptr->ctxt;
|
||||||
|
|
||||||
/* Connect/Disconnect I/O Ports at base address */
|
/* Connect/Disconnect I/O Ports at base address */
|
||||||
if (sim_map_resource(xptr->pnp.io_base, xptr->pnp.io_size, RESOURCE_TYPE_IO, routine, dptr->name, dptr->flags & DEV_DIS) != 0) {
|
if (sim_map_resource(xptr->pnp.io_base, xptr->pnp.io_size, RESOURCE_TYPE_IO, routine, dptr->name, dptr->flags & DEV_DIS) != 0) {
|
||||||
|
@ -402,7 +402,7 @@ static t_stat m2sio_svc(UNIT *uptr)
|
||||||
int32 c,s,stb;
|
int32 c,s,stb;
|
||||||
t_stat r;
|
t_stat r;
|
||||||
|
|
||||||
xptr = uptr->dptr->ctxt;
|
xptr = (M2SIO_CTX *) uptr->dptr->ctxt;
|
||||||
|
|
||||||
/* Check for new incoming connection */
|
/* Check for new incoming connection */
|
||||||
if (uptr->flags & UNIT_ATT) {
|
if (uptr->flags & UNIT_ATT) {
|
||||||
|
@ -500,7 +500,7 @@ static t_stat m2sio_attach(UNIT *uptr, CONST char *cptr)
|
||||||
M2SIO_CTX *xptr;
|
M2SIO_CTX *xptr;
|
||||||
t_stat r;
|
t_stat r;
|
||||||
|
|
||||||
xptr = uptr->dptr->ctxt;
|
xptr = (M2SIO_CTX *) uptr->dptr->ctxt;
|
||||||
|
|
||||||
sim_debug(VERBOSE_MSG, uptr->dptr, "attach (%s).\n", cptr);
|
sim_debug(VERBOSE_MSG, uptr->dptr, "attach (%s).\n", cptr);
|
||||||
|
|
||||||
|
@ -525,7 +525,7 @@ static t_stat m2sio_detach(UNIT *uptr)
|
||||||
sim_debug(VERBOSE_MSG, uptr->dptr, "detach.\n");
|
sim_debug(VERBOSE_MSG, uptr->dptr, "detach.\n");
|
||||||
|
|
||||||
if (uptr->flags & UNIT_ATT) {
|
if (uptr->flags & UNIT_ATT) {
|
||||||
xptr = uptr->dptr->ctxt;
|
xptr = (M2SIO_CTX *) uptr->dptr->ctxt;
|
||||||
|
|
||||||
sim_cancel(uptr);
|
sim_cancel(uptr);
|
||||||
|
|
||||||
|
@ -541,7 +541,7 @@ static t_stat m2sio_set_baud(UNIT *uptr, int32 value, const char *cptr, void *de
|
||||||
int32 baud;
|
int32 baud;
|
||||||
t_stat r = SCPE_ARG;
|
t_stat r = SCPE_ARG;
|
||||||
|
|
||||||
xptr = uptr->dptr->ctxt;
|
xptr = (M2SIO_CTX *) uptr->dptr->ctxt;
|
||||||
|
|
||||||
if (!(uptr->flags & UNIT_ATT)) {
|
if (!(uptr->flags & UNIT_ATT)) {
|
||||||
return SCPE_UNATT;
|
return SCPE_UNATT;
|
||||||
|
@ -576,7 +576,7 @@ static t_stat m2sio_show_baud(FILE *st, UNIT *uptr, int32 value, const void *des
|
||||||
{
|
{
|
||||||
M2SIO_CTX *xptr;
|
M2SIO_CTX *xptr;
|
||||||
|
|
||||||
xptr = uptr->dptr->ctxt;
|
xptr = (M2SIO_CTX *) uptr->dptr->ctxt;
|
||||||
|
|
||||||
if (uptr->flags & UNIT_ATT) {
|
if (uptr->flags & UNIT_ATT) {
|
||||||
fprintf(st, "Baud rate: %d", xptr->baud);
|
fprintf(st, "Baud rate: %d", xptr->baud);
|
||||||
|
@ -589,10 +589,10 @@ static t_stat m2sio_config_line(UNIT *uptr)
|
||||||
{
|
{
|
||||||
M2SIO_CTX *xptr;
|
M2SIO_CTX *xptr;
|
||||||
char config[20];
|
char config[20];
|
||||||
char *fmt;
|
const char *fmt;
|
||||||
t_stat r = SCPE_IERR;
|
t_stat r = SCPE_IERR;
|
||||||
|
|
||||||
xptr = uptr->dptr->ctxt;
|
xptr = (M2SIO_CTX *) uptr->dptr->ctxt;
|
||||||
|
|
||||||
if (xptr != NULL) {
|
if (xptr != NULL) {
|
||||||
switch (xptr->ctb & M2SIO_FMTMSK) {
|
switch (xptr->ctb & M2SIO_FMTMSK) {
|
||||||
|
@ -687,7 +687,7 @@ static int32 m2sio_stat(DEVICE *dptr, int32 io, int32 data)
|
||||||
M2SIO_CTX *xptr;
|
M2SIO_CTX *xptr;
|
||||||
int32 r,s;
|
int32 r,s;
|
||||||
|
|
||||||
xptr = dptr->ctxt;
|
xptr = (M2SIO_CTX *) dptr->ctxt;
|
||||||
|
|
||||||
if (io == IO_RD) {
|
if (io == IO_RD) {
|
||||||
r = xptr->stb;
|
r = xptr->stb;
|
||||||
|
@ -748,7 +748,7 @@ static int32 m2sio_data(DEVICE *dptr, int32 io, int32 data)
|
||||||
M2SIO_CTX *xptr;
|
M2SIO_CTX *xptr;
|
||||||
int32 r;
|
int32 r;
|
||||||
|
|
||||||
xptr = dptr->ctxt;
|
xptr = (M2SIO_CTX *) dptr->ctxt;
|
||||||
|
|
||||||
if (io == IO_RD) {
|
if (io == IO_RD) {
|
||||||
r = xptr->rxb;
|
r = xptr->rxb;
|
||||||
|
|
|
@ -236,13 +236,9 @@ static const char* hayes_description(DEVICE *dptr)
|
||||||
|
|
||||||
static t_stat hayes_reset(DEVICE *dptr)
|
static t_stat hayes_reset(DEVICE *dptr)
|
||||||
{
|
{
|
||||||
HAYES_CTX *xptr;
|
|
||||||
|
|
||||||
xptr = dptr->ctxt;
|
|
||||||
|
|
||||||
/* Connect/Disconnect I/O Ports at base address */
|
/* Connect/Disconnect I/O Ports at base address */
|
||||||
if(sim_map_resource(xptr->pnp.io_base, xptr->pnp.io_size, RESOURCE_TYPE_IO, &hayes_io, dptr->name, dptr->flags & DEV_DIS) != 0) {
|
if (sim_map_resource(hayes_ctx.pnp.io_base, hayes_ctx.pnp.io_size, RESOURCE_TYPE_IO, &hayes_io, dptr->name, dptr->flags & DEV_DIS) != 0) {
|
||||||
sim_debug(ERROR_MSG, dptr, "error mapping I/O resource at 0x%02x.\n", xptr->pnp.io_base);
|
sim_debug(ERROR_MSG, dptr, "error mapping I/O resource at 0x%02x.\n", hayes_ctx.pnp.io_base);
|
||||||
return SCPE_ARG;
|
return SCPE_ARG;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -250,19 +246,19 @@ static t_stat hayes_reset(DEVICE *dptr)
|
||||||
dptr->units[0].dptr = dptr;
|
dptr->units[0].dptr = dptr;
|
||||||
|
|
||||||
/* Enable TMXR modem control passthru */
|
/* Enable TMXR modem control passthru */
|
||||||
tmxr_set_modem_control_passthru(xptr->tmxr);
|
tmxr_set_modem_control_passthru(hayes_ctx.tmxr);
|
||||||
|
|
||||||
/* Reset status registers */
|
/* Reset status registers */
|
||||||
xptr->ireg0 = 0;
|
hayes_ctx.ireg0 = 0;
|
||||||
xptr->ireg1 = HAYES_RI;
|
hayes_ctx.ireg1 = HAYES_RI;
|
||||||
xptr->oreg1 = HAYES_8BIT | HAYES_PI;
|
hayes_ctx.oreg1 = HAYES_8BIT | HAYES_PI;
|
||||||
xptr->oreg2 = 0;
|
hayes_ctx.oreg2 = 0;
|
||||||
xptr->oreg3 = 0;
|
hayes_ctx.oreg3 = 0;
|
||||||
xptr->txp = 0;
|
hayes_ctx.txp = 0;
|
||||||
xptr->dtr = 0;
|
hayes_ctx.dtr = 0;
|
||||||
xptr->intmsk = 0;
|
hayes_ctx.intmsk = 0;
|
||||||
xptr->timer = 0;
|
hayes_ctx.timer = 0;
|
||||||
xptr->baud = HAYES_BAUD;
|
hayes_ctx.baud = HAYES_BAUD;
|
||||||
|
|
||||||
if (!(dptr->flags & DEV_DIS)) {
|
if (!(dptr->flags & DEV_DIS)) {
|
||||||
sim_activate(&dptr->units[0], dptr->units[0].wait);
|
sim_activate(&dptr->units[0], dptr->units[0].wait);
|
||||||
|
@ -277,32 +273,29 @@ static t_stat hayes_reset(DEVICE *dptr)
|
||||||
|
|
||||||
static t_stat hayes_svc(UNIT *uptr)
|
static t_stat hayes_svc(UNIT *uptr)
|
||||||
{
|
{
|
||||||
HAYES_CTX *xptr;
|
|
||||||
int32 c,s,ireg1;
|
int32 c,s,ireg1;
|
||||||
t_stat r;
|
t_stat r;
|
||||||
uint32 ms;
|
uint32 ms;
|
||||||
|
|
||||||
xptr = uptr->dptr->ctxt;
|
|
||||||
|
|
||||||
/* Check for new incoming connection */
|
/* Check for new incoming connection */
|
||||||
if (uptr->flags & UNIT_ATT) {
|
if (uptr->flags & UNIT_ATT) {
|
||||||
if (tmxr_poll_conn(xptr->tmxr) >= 0) { /* poll connection */
|
if (tmxr_poll_conn(hayes_ctx.tmxr) >= 0) { /* poll connection */
|
||||||
sim_debug(STATUS_MSG, uptr->dptr, "new connection.\n");
|
sim_debug(STATUS_MSG, uptr->dptr, "new connection.\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Update incoming modem status bits */
|
/* Update incoming modem status bits */
|
||||||
if (uptr->flags & UNIT_ATT) {
|
if (uptr->flags & UNIT_ATT) {
|
||||||
tmxr_set_get_modem_bits(xptr->tmln, 0, 0, &s);
|
tmxr_set_get_modem_bits(hayes_ctx.tmln, 0, 0, &s);
|
||||||
|
|
||||||
ireg1 = xptr->ireg1;
|
ireg1 = hayes_ctx.ireg1;
|
||||||
|
|
||||||
xptr->ireg1 &= ~HAYES_RI;
|
hayes_ctx.ireg1 &= ~HAYES_RI;
|
||||||
xptr->ireg1 |= (s & TMXR_MDM_RNG) ? 0 : HAYES_RI; /* Active Low */
|
hayes_ctx.ireg1 |= (s & TMXR_MDM_RNG) ? 0 : HAYES_RI; /* Active Low */
|
||||||
|
|
||||||
/* RI status changed */
|
/* RI status changed */
|
||||||
if ((ireg1 ^ xptr->ireg1) & HAYES_RI) {
|
if ((ireg1 ^ hayes_ctx.ireg1) & HAYES_RI) {
|
||||||
sim_debug(STATUS_MSG, uptr->dptr, "RI state changed to %s.\n", (xptr->ireg1 & HAYES_RI) ? "LOW" : "HIGH");
|
sim_debug(STATUS_MSG, uptr->dptr, "RI state changed to %s.\n", (hayes_ctx.ireg1 & HAYES_RI) ? "LOW" : "HIGH");
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** The Hayes does not have DTR or RTS control signals.
|
** The Hayes does not have DTR or RTS control signals.
|
||||||
|
@ -310,17 +303,17 @@ static t_stat hayes_svc(UNIT *uptr)
|
||||||
** is active and there is no way to tell TMXR to ignore
|
** is active and there is no way to tell TMXR to ignore
|
||||||
** them, so we raise DTR here on RI.
|
** them, so we raise DTR here on RI.
|
||||||
*/
|
*/
|
||||||
if (!(xptr->ireg1 & HAYES_RI)) { /* RI is active low */
|
if (!(hayes_ctx.ireg1 & HAYES_RI)) { /* RI is active low */
|
||||||
hayes_set_dtr(uptr, 1);
|
hayes_set_dtr(uptr, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
xptr->ireg1 &= ~HAYES_CD;
|
hayes_ctx.ireg1 &= ~HAYES_CD;
|
||||||
xptr->ireg1 |= (s & TMXR_MDM_DCD) ? HAYES_CD : 0; /* Active High */
|
hayes_ctx.ireg1 |= (s & TMXR_MDM_DCD) ? HAYES_CD : 0; /* Active High */
|
||||||
|
|
||||||
/* CD status changed */
|
/* CD status changed */
|
||||||
if ((ireg1 ^ xptr->ireg1) & HAYES_CD) {
|
if ((ireg1 ^ hayes_ctx.ireg1) & HAYES_CD) {
|
||||||
sim_debug(STATUS_MSG, uptr->dptr, "CD state changed to %s.\n", (xptr->ireg1 & HAYES_CD) ? "HIGH" : "LOW");
|
sim_debug(STATUS_MSG, uptr->dptr, "CD state changed to %s.\n", (hayes_ctx.ireg1 & HAYES_CD) ? "HIGH" : "LOW");
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** The Hayes does not have DTR or RTS control signals.
|
** The Hayes does not have DTR or RTS control signals.
|
||||||
|
@ -328,21 +321,21 @@ static t_stat hayes_svc(UNIT *uptr)
|
||||||
** is active and there is no way to tell TMXR to
|
** is active and there is no way to tell TMXR to
|
||||||
** ignore them, so we drop DTR here on loss of CD.
|
** ignore them, so we drop DTR here on loss of CD.
|
||||||
*/
|
*/
|
||||||
if (!(xptr->ireg1 & HAYES_CD)) {
|
if (!(hayes_ctx.ireg1 & HAYES_CD)) {
|
||||||
hayes_set_dtr(uptr, 0);
|
hayes_set_dtr(uptr, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* TX data */
|
/* TX data */
|
||||||
if (xptr->txp && xptr->oreg2 & HAYES_TXE) {
|
if (hayes_ctx.txp && hayes_ctx.oreg2 & HAYES_TXE) {
|
||||||
if (uptr->flags & UNIT_ATT) {
|
if (uptr->flags & UNIT_ATT) {
|
||||||
r = tmxr_putc_ln(xptr->tmln, xptr->oreg0);
|
r = tmxr_putc_ln(hayes_ctx.tmln, hayes_ctx.oreg0);
|
||||||
} else {
|
} else {
|
||||||
r = sim_putchar(xptr->oreg0);
|
r = sim_putchar(hayes_ctx.oreg0);
|
||||||
}
|
}
|
||||||
|
|
||||||
xptr->txp = 0; /* Reset TX Pending */
|
hayes_ctx.txp = 0; /* Reset TX Pending */
|
||||||
|
|
||||||
if (r == SCPE_LOST) {
|
if (r == SCPE_LOST) {
|
||||||
sim_debug(STATUS_MSG, uptr->dptr, "lost connection.\n");
|
sim_debug(STATUS_MSG, uptr->dptr, "lost connection.\n");
|
||||||
|
@ -350,41 +343,41 @@ static t_stat hayes_svc(UNIT *uptr)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Update TRE if not set and no character pending */
|
/* Update TRE if not set and no character pending */
|
||||||
if (!xptr->txp && !(xptr->ireg1 & HAYES_TRE)) {
|
if (!hayes_ctx.txp && !(hayes_ctx.ireg1 & HAYES_TRE)) {
|
||||||
if (uptr->flags & UNIT_ATT) {
|
if (uptr->flags & UNIT_ATT) {
|
||||||
tmxr_poll_tx(xptr->tmxr);
|
tmxr_poll_tx(hayes_ctx.tmxr);
|
||||||
xptr->ireg1 |= (tmxr_txdone_ln(xptr->tmln)) ? HAYES_TRE : 0;
|
hayes_ctx.ireg1 |= (tmxr_txdone_ln(hayes_ctx.tmln)) ? HAYES_TRE : 0;
|
||||||
} else {
|
} else {
|
||||||
xptr->ireg1 |= HAYES_TRE;
|
hayes_ctx.ireg1 |= HAYES_TRE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check for Data if RX buffer empty */
|
/* Check for Data if RX buffer empty */
|
||||||
if (!(xptr->ireg1 & HAYES_RRF)) {
|
if (!(hayes_ctx.ireg1 & HAYES_RRF)) {
|
||||||
if (uptr->flags & UNIT_ATT) {
|
if (uptr->flags & UNIT_ATT) {
|
||||||
tmxr_poll_rx(xptr->tmxr);
|
tmxr_poll_rx(hayes_ctx.tmxr);
|
||||||
|
|
||||||
c = tmxr_getc_ln(xptr->tmln);
|
c = tmxr_getc_ln(hayes_ctx.tmln);
|
||||||
} else {
|
} else {
|
||||||
c = sim_poll_kbd();
|
c = sim_poll_kbd();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (c & (TMXR_VALID | SCPE_KFLAG)) {
|
if (c & (TMXR_VALID | SCPE_KFLAG)) {
|
||||||
xptr->ireg0 = c & 0xff;
|
hayes_ctx.ireg0 = c & 0xff;
|
||||||
xptr->ireg1 |= HAYES_RRF;
|
hayes_ctx.ireg1 |= HAYES_RRF;
|
||||||
xptr->ireg1 &= ~(HAYES_FE | HAYES_OE | HAYES_PE);
|
hayes_ctx.ireg1 &= ~(HAYES_FE | HAYES_OE | HAYES_PE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Timer */
|
/* Timer */
|
||||||
ms = sim_os_msec();
|
ms = sim_os_msec();
|
||||||
|
|
||||||
if (xptr->timer && ms > xptr->timer) {
|
if (hayes_ctx.timer && ms > hayes_ctx.timer) {
|
||||||
if (!(xptr->ireg1 & HAYES_TMR)) {
|
if (!(hayes_ctx.ireg1 & HAYES_TMR)) {
|
||||||
sim_debug(VERBOSE_MSG, uptr->dptr, "50ms timer triggered.\n");
|
sim_debug(VERBOSE_MSG, uptr->dptr, "50ms timer triggered.\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
xptr->ireg1 |= HAYES_TMR;
|
hayes_ctx.ireg1 |= HAYES_TMR;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Don't let TMXR clobber our wait time */
|
/* Don't let TMXR clobber our wait time */
|
||||||
|
@ -399,18 +392,15 @@ static t_stat hayes_svc(UNIT *uptr)
|
||||||
/* Attach routine */
|
/* Attach routine */
|
||||||
static t_stat hayes_attach(UNIT *uptr, CONST char *cptr)
|
static t_stat hayes_attach(UNIT *uptr, CONST char *cptr)
|
||||||
{
|
{
|
||||||
HAYES_CTX *xptr;
|
|
||||||
t_stat r;
|
t_stat r;
|
||||||
|
|
||||||
xptr = uptr->dptr->ctxt;
|
|
||||||
|
|
||||||
sim_debug(VERBOSE_MSG, uptr->dptr, "attach (%s).\n", cptr);
|
sim_debug(VERBOSE_MSG, uptr->dptr, "attach (%s).\n", cptr);
|
||||||
|
|
||||||
if ((r = tmxr_attach(xptr->tmxr, uptr, cptr)) == SCPE_OK) {
|
if ((r = tmxr_attach(hayes_ctx.tmxr, uptr, cptr)) == SCPE_OK) {
|
||||||
|
|
||||||
xptr->flags = uptr->flags; /* Save Flags */
|
hayes_ctx.flags = uptr->flags; /* Save Flags */
|
||||||
|
|
||||||
xptr->tmln->rcve = 1;
|
hayes_ctx.tmln->rcve = 1;
|
||||||
|
|
||||||
hayes_config_line(uptr);
|
hayes_config_line(uptr);
|
||||||
|
|
||||||
|
@ -419,8 +409,8 @@ static t_stat hayes_attach(UNIT *uptr, CONST char *cptr)
|
||||||
** We raise RTS here for use to provide DCD/RI signals.
|
** We raise RTS here for use to provide DCD/RI signals.
|
||||||
** We drop DTR as that is tied to the other functions.
|
** We drop DTR as that is tied to the other functions.
|
||||||
*/
|
*/
|
||||||
tmxr_set_get_modem_bits(xptr->tmln, TMXR_MDM_RTS, TMXR_MDM_DTR, NULL);
|
tmxr_set_get_modem_bits(hayes_ctx.tmln, TMXR_MDM_RTS, TMXR_MDM_DTR, NULL);
|
||||||
xptr->dtr = 0;
|
hayes_ctx.dtr = 0;
|
||||||
sim_debug(STATUS_MSG, uptr->dptr, "Raising RTS. Dropping DTR.\n");
|
sim_debug(STATUS_MSG, uptr->dptr, "Raising RTS. Dropping DTR.\n");
|
||||||
|
|
||||||
sim_activate(uptr, uptr->wait);
|
sim_activate(uptr, uptr->wait);
|
||||||
|
@ -435,18 +425,14 @@ static t_stat hayes_attach(UNIT *uptr, CONST char *cptr)
|
||||||
/* Detach routine */
|
/* Detach routine */
|
||||||
static t_stat hayes_detach(UNIT *uptr)
|
static t_stat hayes_detach(UNIT *uptr)
|
||||||
{
|
{
|
||||||
HAYES_CTX *xptr;
|
|
||||||
|
|
||||||
sim_debug(VERBOSE_MSG, uptr->dptr, "detach.\n");
|
sim_debug(VERBOSE_MSG, uptr->dptr, "detach.\n");
|
||||||
|
|
||||||
if (uptr->flags & UNIT_ATT) {
|
if (uptr->flags & UNIT_ATT) {
|
||||||
xptr = uptr->dptr->ctxt;
|
uptr->flags = hayes_ctx.flags; /* Restore Flags */
|
||||||
|
|
||||||
uptr->flags = xptr->flags; /* Restore Flags */
|
|
||||||
|
|
||||||
sim_cancel(uptr);
|
sim_cancel(uptr);
|
||||||
|
|
||||||
return (tmxr_detach(xptr->tmxr, uptr));
|
return (tmxr_detach(hayes_ctx.tmxr, uptr));
|
||||||
}
|
}
|
||||||
|
|
||||||
return SCPE_UNATT;
|
return SCPE_UNATT;
|
||||||
|
@ -454,15 +440,11 @@ static t_stat hayes_detach(UNIT *uptr)
|
||||||
|
|
||||||
static t_stat hayes_config_line(UNIT *uptr)
|
static t_stat hayes_config_line(UNIT *uptr)
|
||||||
{
|
{
|
||||||
HAYES_CTX *xptr;
|
|
||||||
char config[20];
|
char config[20];
|
||||||
char b,p,s;
|
char b,p,s;
|
||||||
t_stat r = SCPE_IERR;
|
t_stat r = SCPE_IERR;
|
||||||
|
|
||||||
xptr = uptr->dptr->ctxt;
|
switch (hayes_ctx.oreg1 & HAYES_BMSK) {
|
||||||
|
|
||||||
if (xptr != NULL) {
|
|
||||||
switch (xptr->oreg1 & HAYES_BMSK) {
|
|
||||||
case HAYES_5BIT:
|
case HAYES_5BIT:
|
||||||
b = '5';
|
b = '5';
|
||||||
break;
|
break;
|
||||||
|
@ -481,7 +463,7 @@ static t_stat hayes_config_line(UNIT *uptr)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (xptr->oreg1 & HAYES_PMSK) {
|
switch (hayes_ctx.oreg1 & HAYES_PMSK) {
|
||||||
case HAYES_OPAR:
|
case HAYES_OPAR:
|
||||||
p = 'O';
|
p = 'O';
|
||||||
break;
|
break;
|
||||||
|
@ -495,7 +477,7 @@ static t_stat hayes_config_line(UNIT *uptr)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (xptr->oreg1 & HAYES_SMSK) {
|
switch (hayes_ctx.oreg1 & HAYES_SMSK) {
|
||||||
case HAYES_2SB:
|
case HAYES_2SB:
|
||||||
s = '2';
|
s = '2';
|
||||||
break;
|
break;
|
||||||
|
@ -506,9 +488,9 @@ static t_stat hayes_config_line(UNIT *uptr)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
sprintf(config, "%d-%c%c%c", xptr->baud, b,p,s);
|
sprintf(config, "%d-%c%c%c", hayes_ctx.baud, b,p,s);
|
||||||
|
|
||||||
r = tmxr_set_config_line(xptr->tmln, config);
|
r = tmxr_set_config_line(hayes_ctx.tmln, config);
|
||||||
|
|
||||||
if (r) {
|
if (r) {
|
||||||
sim_debug(ERROR_MSG, uptr->dptr, "error %d setting port configuration to '%s'.\n", r, config);
|
sim_debug(ERROR_MSG, uptr->dptr, "error %d setting port configuration to '%s'.\n", r, config);
|
||||||
|
@ -531,35 +513,29 @@ static t_stat hayes_config_line(UNIT *uptr)
|
||||||
** Serial ports are self-limiting and sockets will run
|
** Serial ports are self-limiting and sockets will run
|
||||||
** at the clocked CPU speed.
|
** at the clocked CPU speed.
|
||||||
*/
|
*/
|
||||||
xptr->tmln->txbps = 0; /* Get TMXR's rate-limiting out of our way */
|
hayes_ctx.tmln->txbps = 0; /* Get TMXR's rate-limiting out of our way */
|
||||||
xptr->tmln->rxbps = 0; /* Get TMXR's rate-limiting out of our way */
|
hayes_ctx.tmln->rxbps = 0; /* Get TMXR's rate-limiting out of our way */
|
||||||
}
|
|
||||||
|
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
static t_stat hayes_set_dtr(UNIT *uptr, int32 flag)
|
static t_stat hayes_set_dtr(UNIT *uptr, int32 flag)
|
||||||
{
|
{
|
||||||
HAYES_CTX *xptr;
|
|
||||||
t_stat r = SCPE_IERR;
|
t_stat r = SCPE_IERR;
|
||||||
|
|
||||||
xptr = uptr->dptr->ctxt;
|
if (hayes_ctx.dtr && !flag) {
|
||||||
|
r = tmxr_set_get_modem_bits(hayes_ctx.tmln, 0, TMXR_MDM_DTR, NULL);
|
||||||
if (xptr != NULL) {
|
|
||||||
if (xptr->dtr && !flag) {
|
|
||||||
r = tmxr_set_get_modem_bits(xptr->tmln, 0, TMXR_MDM_DTR, NULL);
|
|
||||||
sim_debug(STATUS_MSG, uptr->dptr, "Dropping DTR.\n");
|
sim_debug(STATUS_MSG, uptr->dptr, "Dropping DTR.\n");
|
||||||
} else if (!xptr->dtr && flag) {
|
} else if (!hayes_ctx.dtr && flag) {
|
||||||
r = tmxr_set_get_modem_bits(xptr->tmln, TMXR_MDM_DTR, 0, NULL);
|
r = tmxr_set_get_modem_bits(hayes_ctx.tmln, TMXR_MDM_DTR, 0, NULL);
|
||||||
sim_debug(STATUS_MSG, uptr->dptr, "Raising DTR.\n");
|
sim_debug(STATUS_MSG, uptr->dptr, "Raising DTR.\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
xptr->dtr = flag;
|
hayes_ctx.dtr = flag;
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int32 hayes_io(int32 addr, int32 io, int32 data)
|
static int32 hayes_io(int32 addr, int32 io, int32 data)
|
||||||
{
|
{
|
||||||
int32 r;
|
int32 r;
|
||||||
|
@ -602,18 +578,15 @@ static int32 hayes_io(int32 addr, int32 io, int32 data)
|
||||||
*/
|
*/
|
||||||
static int32 hayes_reg0(int32 io, int32 data)
|
static int32 hayes_reg0(int32 io, int32 data)
|
||||||
{
|
{
|
||||||
HAYES_CTX *xptr;
|
|
||||||
int32 r;
|
int32 r;
|
||||||
|
|
||||||
xptr = hayes_dev.ctxt;
|
|
||||||
|
|
||||||
if (io == IO_RD) {
|
if (io == IO_RD) {
|
||||||
r = xptr->ireg0;
|
r = hayes_ctx.ireg0;
|
||||||
xptr->ireg1 &= ~(HAYES_RRF);
|
hayes_ctx.ireg1 &= ~(HAYES_RRF);
|
||||||
} else {
|
} else {
|
||||||
xptr->oreg0 = data;
|
hayes_ctx.oreg0 = data;
|
||||||
xptr->ireg1 &= ~(HAYES_TRE);
|
hayes_ctx.ireg1 &= ~(HAYES_TRE);
|
||||||
xptr->txp = 1;
|
hayes_ctx.txp = 1;
|
||||||
|
|
||||||
r = 0x00;
|
r = 0x00;
|
||||||
}
|
}
|
||||||
|
@ -629,16 +602,13 @@ static int32 hayes_reg0(int32 io, int32 data)
|
||||||
*/
|
*/
|
||||||
static int32 hayes_reg1(int32 io, int32 data)
|
static int32 hayes_reg1(int32 io, int32 data)
|
||||||
{
|
{
|
||||||
HAYES_CTX *xptr;
|
|
||||||
int32 r;
|
int32 r;
|
||||||
|
|
||||||
xptr = hayes_dev.ctxt;
|
|
||||||
|
|
||||||
if (io == IO_RD) {
|
if (io == IO_RD) {
|
||||||
r = xptr->ireg1;
|
r = hayes_ctx.ireg1;
|
||||||
xptr->ireg1 &= ~(HAYES_FE | HAYES_OE | HAYES_PE);
|
hayes_ctx.ireg1 &= ~(HAYES_FE | HAYES_OE | HAYES_PE);
|
||||||
} else {
|
} else {
|
||||||
xptr->oreg1 = data; /* Set UART configuration */
|
hayes_ctx.oreg1 = data; /* Set UART configuration */
|
||||||
|
|
||||||
hayes_config_line(&hayes_dev.units[0]);
|
hayes_config_line(&hayes_dev.units[0]);
|
||||||
|
|
||||||
|
@ -656,14 +626,11 @@ static int32 hayes_reg1(int32 io, int32 data)
|
||||||
*/
|
*/
|
||||||
static int32 hayes_reg2(int32 io, int32 data)
|
static int32 hayes_reg2(int32 io, int32 data)
|
||||||
{
|
{
|
||||||
HAYES_CTX *xptr;
|
|
||||||
int32 oreg2;
|
int32 oreg2;
|
||||||
|
|
||||||
xptr = hayes_dev.ctxt;
|
|
||||||
|
|
||||||
if (io == IO_WR) {
|
if (io == IO_WR) {
|
||||||
oreg2 = xptr->oreg2; /* Save previous value */
|
oreg2 = hayes_ctx.oreg2; /* Save previous value */
|
||||||
xptr->oreg2 = data; /* Set new value */
|
hayes_ctx.oreg2 = data; /* Set new value */
|
||||||
|
|
||||||
sim_debug(DEBUG_MSG, &hayes_dev, "oreg2 %02X -> %02X\n", oreg2, data);
|
sim_debug(DEBUG_MSG, &hayes_dev, "oreg2 %02X -> %02X\n", oreg2, data);
|
||||||
|
|
||||||
|
@ -685,7 +652,7 @@ static int32 hayes_reg2(int32 io, int32 data)
|
||||||
|
|
||||||
/* Did the line configuration change? */
|
/* Did the line configuration change? */
|
||||||
if ((oreg2 & HAYES_LMSK) != (data & HAYES_LMSK)) {
|
if ((oreg2 & HAYES_LMSK) != (data & HAYES_LMSK)) {
|
||||||
xptr->baud = (data & HAYES_BRS) ? 300 : 110;
|
hayes_ctx.baud = (data & HAYES_BRS) ? 300 : 110;
|
||||||
|
|
||||||
hayes_config_line(&hayes_dev.units[0]);
|
hayes_config_line(&hayes_dev.units[0]);
|
||||||
}
|
}
|
||||||
|
@ -702,13 +669,9 @@ static int32 hayes_reg2(int32 io, int32 data)
|
||||||
*/
|
*/
|
||||||
static int32 hayes_reg3(int32 io, int32 data)
|
static int32 hayes_reg3(int32 io, int32 data)
|
||||||
{
|
{
|
||||||
HAYES_CTX *xptr;
|
|
||||||
|
|
||||||
xptr = hayes_dev.ctxt;
|
|
||||||
|
|
||||||
if (io == IO_WR) {
|
if (io == IO_WR) {
|
||||||
xptr->timer = sim_os_msec() + 50; /* Set timeout to 50ms */
|
hayes_ctx.timer = sim_os_msec() + 50; /* Set timeout to 50ms */
|
||||||
xptr->ireg1 &= ~(HAYES_TMR); /* Clear timer status */
|
hayes_ctx.ireg1 &= ~(HAYES_TMR); /* Clear timer status */
|
||||||
}
|
}
|
||||||
|
|
||||||
return(0x00);
|
return(0x00);
|
||||||
|
|
1462
AltairZ80/s100_icom.c
Normal file
1462
AltairZ80/s100_icom.c
Normal file
File diff suppressed because it is too large
Load diff
|
@ -259,13 +259,9 @@ static const char* pmmi_description(DEVICE *dptr)
|
||||||
|
|
||||||
static t_stat pmmi_reset(DEVICE *dptr)
|
static t_stat pmmi_reset(DEVICE *dptr)
|
||||||
{
|
{
|
||||||
PMMI_CTX *xptr;
|
|
||||||
|
|
||||||
xptr = dptr->ctxt;
|
|
||||||
|
|
||||||
/* Connect/Disconnect I/O Ports at base address */
|
/* Connect/Disconnect I/O Ports at base address */
|
||||||
if(sim_map_resource(xptr->pnp.io_base, xptr->pnp.io_size, RESOURCE_TYPE_IO, &pmmi_io, dptr->name, dptr->flags & DEV_DIS) != 0) {
|
if (sim_map_resource(pmmi_ctx.pnp.io_base, pmmi_ctx.pnp.io_size, RESOURCE_TYPE_IO, &pmmi_io, dptr->name, dptr->flags & DEV_DIS) != 0) {
|
||||||
sim_debug(ERROR_MSG, dptr, "error mapping I/O resource at 0x%02x.\n", xptr->pnp.io_base);
|
sim_debug(ERROR_MSG, dptr, "error mapping I/O resource at 0x%02x.\n", pmmi_ctx.pnp.io_base);
|
||||||
return SCPE_ARG;
|
return SCPE_ARG;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -273,21 +269,21 @@ static t_stat pmmi_reset(DEVICE *dptr)
|
||||||
dptr->units[0].dptr = dptr;
|
dptr->units[0].dptr = dptr;
|
||||||
|
|
||||||
/* Enable TMXR modem control passthru */
|
/* Enable TMXR modem control passthru */
|
||||||
tmxr_set_modem_control_passthru(xptr->tmxr);
|
tmxr_set_modem_control_passthru(pmmi_ctx.tmxr);
|
||||||
|
|
||||||
/* Reset status registers */
|
/* Reset status registers */
|
||||||
xptr->ireg0 = 0;
|
pmmi_ctx.ireg0 = 0;
|
||||||
xptr->ireg1 = 0;
|
pmmi_ctx.ireg1 = 0;
|
||||||
xptr->ireg2 = PMMI_RNG | PMMI_CTS | PMMI_DT | PMMI_AP;
|
pmmi_ctx.ireg2 = PMMI_RNG | PMMI_CTS | PMMI_DT | PMMI_AP;
|
||||||
xptr->ireg3 = 0;
|
pmmi_ctx.ireg3 = 0;
|
||||||
xptr->oreg0 = 0;
|
pmmi_ctx.oreg0 = 0;
|
||||||
xptr->oreg1 = 0;
|
pmmi_ctx.oreg1 = 0;
|
||||||
xptr->oreg2 = 0;
|
pmmi_ctx.oreg2 = 0;
|
||||||
xptr->oreg3 = 0;
|
pmmi_ctx.oreg3 = 0;
|
||||||
xptr->txp = 0;
|
pmmi_ctx.txp = 0;
|
||||||
xptr->intmsk = 0;
|
pmmi_ctx.intmsk = 0;
|
||||||
xptr->ptimer = sim_os_msec() + 40;
|
pmmi_ctx.ptimer = sim_os_msec() + 40;
|
||||||
xptr->dtimer = 0;
|
pmmi_ctx.dtimer = 0;
|
||||||
|
|
||||||
if (!(dptr->flags & DEV_DIS)) {
|
if (!(dptr->flags & DEV_DIS)) {
|
||||||
sim_activate(&dptr->units[0], dptr->units[0].wait);
|
sim_activate(&dptr->units[0], dptr->units[0].wait);
|
||||||
|
@ -302,25 +298,22 @@ static t_stat pmmi_reset(DEVICE *dptr)
|
||||||
|
|
||||||
static t_stat pmmi_svc(UNIT *uptr)
|
static t_stat pmmi_svc(UNIT *uptr)
|
||||||
{
|
{
|
||||||
PMMI_CTX *xptr;
|
|
||||||
int32 c,s,ireg2;
|
int32 c,s,ireg2;
|
||||||
t_stat r;
|
t_stat r;
|
||||||
uint32 ms;
|
uint32 ms;
|
||||||
|
|
||||||
xptr = uptr->dptr->ctxt;
|
|
||||||
|
|
||||||
/* Check for new incoming connection */
|
/* Check for new incoming connection */
|
||||||
if (uptr->flags & UNIT_ATT) {
|
if (uptr->flags & UNIT_ATT) {
|
||||||
if (tmxr_poll_conn(xptr->tmxr) >= 0) { /* poll connection */
|
if (tmxr_poll_conn(pmmi_ctx.tmxr) >= 0) { /* poll connection */
|
||||||
|
|
||||||
/* Clear DTR and RTS if serial port */
|
/* Clear DTR and RTS if serial port */
|
||||||
if (xptr->tmln->serport) {
|
if (pmmi_ctx.tmln->serport) {
|
||||||
s = TMXR_MDM_DTR | ((pmmi_dev.units[0].flags & UNIT_PMMI_RTS) ? TMXR_MDM_RTS : 0);
|
s = TMXR_MDM_DTR | ((pmmi_dev.units[0].flags & UNIT_PMMI_RTS) ? TMXR_MDM_RTS : 0);
|
||||||
tmxr_set_get_modem_bits(xptr->tmln, 0, s, NULL);
|
tmxr_set_get_modem_bits(pmmi_ctx.tmln, 0, s, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
xptr->tmln->rcve = 1; /* Enable receiver */
|
pmmi_ctx.tmln->rcve = 1; /* Enable receiver */
|
||||||
xptr->conn = 1; /* set connected */
|
pmmi_ctx.conn = 1; /* set connected */
|
||||||
|
|
||||||
sim_debug(STATUS_MSG, uptr->dptr, "new connection.\n");
|
sim_debug(STATUS_MSG, uptr->dptr, "new connection.\n");
|
||||||
}
|
}
|
||||||
|
@ -328,104 +321,104 @@ static t_stat pmmi_svc(UNIT *uptr)
|
||||||
|
|
||||||
/* Update incoming modem status bits */
|
/* Update incoming modem status bits */
|
||||||
if (uptr->flags & UNIT_ATT) {
|
if (uptr->flags & UNIT_ATT) {
|
||||||
tmxr_set_get_modem_bits(xptr->tmln, 0, 0, &s);
|
tmxr_set_get_modem_bits(pmmi_ctx.tmln, 0, 0, &s);
|
||||||
|
|
||||||
ireg2 = xptr->ireg2;
|
ireg2 = pmmi_ctx.ireg2;
|
||||||
xptr->ireg2 &= ~PMMI_CTS;
|
pmmi_ctx.ireg2 &= ~PMMI_CTS;
|
||||||
xptr->ireg2 |= (s & TMXR_MDM_CTS) ? 0 : PMMI_CTS; /* Active Low */
|
pmmi_ctx.ireg2 |= (s & TMXR_MDM_CTS) ? 0 : PMMI_CTS; /* Active Low */
|
||||||
|
|
||||||
/* CTS status changed */
|
/* CTS status changed */
|
||||||
if ((ireg2 ^ xptr->ireg2) & PMMI_CTS) {
|
if ((ireg2 ^ pmmi_ctx.ireg2) & PMMI_CTS) {
|
||||||
if (xptr->ireg2 & PMMI_CTS) { /* If no CTS, set AP bit */
|
if (pmmi_ctx.ireg2 & PMMI_CTS) { /* If no CTS, set AP bit */
|
||||||
xptr->ireg2 |= PMMI_AP; /* Answer Phone Bit (active low) */
|
pmmi_ctx.ireg2 |= PMMI_AP; /* Answer Phone Bit (active low) */
|
||||||
}
|
}
|
||||||
sim_debug(STATUS_MSG, uptr->dptr, "CTS state changed to %s.\n", (xptr->ireg2 & PMMI_CTS) ? "LOW" : "HIGH");
|
sim_debug(STATUS_MSG, uptr->dptr, "CTS state changed to %s.\n", (pmmi_ctx.ireg2 & PMMI_CTS) ? "LOW" : "HIGH");
|
||||||
}
|
}
|
||||||
|
|
||||||
xptr->ireg2 &= ~PMMI_RNG;
|
pmmi_ctx.ireg2 &= ~PMMI_RNG;
|
||||||
xptr->ireg2 |= (s & TMXR_MDM_RNG) ? 0 : PMMI_RNG; /* Active Low */
|
pmmi_ctx.ireg2 |= (s & TMXR_MDM_RNG) ? 0 : PMMI_RNG; /* Active Low */
|
||||||
|
|
||||||
/* RNG status changed */
|
/* RNG status changed */
|
||||||
if ((ireg2 ^ xptr->ireg2) & PMMI_RNG) {
|
if ((ireg2 ^ pmmi_ctx.ireg2) & PMMI_RNG) {
|
||||||
/* Answer Phone Bit on RI */
|
/* Answer Phone Bit on RI */
|
||||||
if (!(xptr->ireg2 & PMMI_RNG)) {
|
if (!(pmmi_ctx.ireg2 & PMMI_RNG)) {
|
||||||
xptr->ireg2 &= ~PMMI_AP; /* Answer Phone Bit (active low) */
|
pmmi_ctx.ireg2 &= ~PMMI_AP; /* Answer Phone Bit (active low) */
|
||||||
}
|
}
|
||||||
|
|
||||||
sim_debug(STATUS_MSG, uptr->dptr, "RNG state changed to %s.\n", (xptr->ireg2 & PMMI_RNG) ? "LOW" : "HIGH");
|
sim_debug(STATUS_MSG, uptr->dptr, "RNG state changed to %s.\n", (pmmi_ctx.ireg2 & PMMI_RNG) ? "LOW" : "HIGH");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Enable receiver if CTS is active low */
|
/* Enable receiver if CTS is active low */
|
||||||
xptr->tmln->rcve = !(xptr->ireg2 & PMMI_CTS);
|
pmmi_ctx.tmln->rcve = !(pmmi_ctx.ireg2 & PMMI_CTS);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* TX data */
|
/* TX data */
|
||||||
if (xptr->txp) {
|
if (pmmi_ctx.txp) {
|
||||||
if (uptr->flags & UNIT_ATT) {
|
if (uptr->flags & UNIT_ATT) {
|
||||||
if (!(xptr->ireg2 & PMMI_CTS)) { /* Active low */
|
if (!(pmmi_ctx.ireg2 & PMMI_CTS)) { /* Active low */
|
||||||
r = tmxr_putc_ln(xptr->tmln, xptr->oreg1);
|
r = tmxr_putc_ln(pmmi_ctx.tmln, pmmi_ctx.oreg1);
|
||||||
xptr->txp = 0; /* Reset TX Pending */
|
pmmi_ctx.txp = 0; /* Reset TX Pending */
|
||||||
} else {
|
} else {
|
||||||
r = SCPE_STALL;
|
r = SCPE_STALL;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
r = sim_putchar(xptr->oreg1);
|
r = sim_putchar(pmmi_ctx.oreg1);
|
||||||
xptr->txp = 0; /* Reset TX Pending */
|
pmmi_ctx.txp = 0; /* Reset TX Pending */
|
||||||
}
|
}
|
||||||
|
|
||||||
if (r == SCPE_LOST) {
|
if (r == SCPE_LOST) {
|
||||||
xptr->conn = 0; /* Connection was lost */
|
pmmi_ctx.conn = 0; /* Connection was lost */
|
||||||
sim_debug(STATUS_MSG, uptr->dptr, "lost connection.\n");
|
sim_debug(STATUS_MSG, uptr->dptr, "lost connection.\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Update TBMT if not set and no character pending */
|
/* Update TBMT if not set and no character pending */
|
||||||
if (!xptr->txp && !(xptr->ireg0 & PMMI_TBMT)) {
|
if (!pmmi_ctx.txp && !(pmmi_ctx.ireg0 & PMMI_TBMT)) {
|
||||||
if (uptr->flags & UNIT_ATT) {
|
if (uptr->flags & UNIT_ATT) {
|
||||||
tmxr_poll_tx(xptr->tmxr);
|
tmxr_poll_tx(pmmi_ctx.tmxr);
|
||||||
xptr->ireg0 |= (tmxr_txdone_ln(xptr->tmln) && xptr->conn) ? (PMMI_TBMT | PMMI_TEOC) : 0;
|
pmmi_ctx.ireg0 |= (tmxr_txdone_ln(pmmi_ctx.tmln) && pmmi_ctx.conn) ? (PMMI_TBMT | PMMI_TEOC) : 0;
|
||||||
} else {
|
} else {
|
||||||
xptr->ireg0 |= (PMMI_TBMT | PMMI_TEOC);
|
pmmi_ctx.ireg0 |= (PMMI_TBMT | PMMI_TEOC);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check for Data if RX buffer empty */
|
/* Check for Data if RX buffer empty */
|
||||||
if (!(xptr->ireg0 & PMMI_DAV)) {
|
if (!(pmmi_ctx.ireg0 & PMMI_DAV)) {
|
||||||
if (uptr->flags & UNIT_ATT) {
|
if (uptr->flags & UNIT_ATT) {
|
||||||
tmxr_poll_rx(xptr->tmxr);
|
tmxr_poll_rx(pmmi_ctx.tmxr);
|
||||||
|
|
||||||
c = tmxr_getc_ln(xptr->tmln);
|
c = tmxr_getc_ln(pmmi_ctx.tmln);
|
||||||
} else {
|
} else {
|
||||||
c = sim_poll_kbd();
|
c = sim_poll_kbd();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (c & (TMXR_VALID | SCPE_KFLAG)) {
|
if (c & (TMXR_VALID | SCPE_KFLAG)) {
|
||||||
xptr->ireg1 = c & 0xff;
|
pmmi_ctx.ireg1 = c & 0xff;
|
||||||
xptr->ireg0 |= PMMI_DAV;
|
pmmi_ctx.ireg0 |= PMMI_DAV;
|
||||||
xptr->ireg0 &= ~(PMMI_FE | PMMI_OR | PMMI_RPE);
|
pmmi_ctx.ireg0 &= ~(PMMI_FE | PMMI_OR | PMMI_RPE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Timer Pulses */
|
/* Timer Pulses */
|
||||||
ms = sim_os_msec();
|
ms = sim_os_msec();
|
||||||
|
|
||||||
if (ms > xptr->ptimer) {
|
if (ms > pmmi_ctx.ptimer) {
|
||||||
if (xptr->oreg2) {
|
if (pmmi_ctx.oreg2) {
|
||||||
if (xptr->ireg2 & PMMI_TMR) {
|
if (pmmi_ctx.ireg2 & PMMI_TMR) {
|
||||||
xptr->ireg2 &= ~PMMI_TMR;
|
pmmi_ctx.ireg2 &= ~PMMI_TMR;
|
||||||
xptr->ptimer = sim_os_msec() + 600 / (PMMI_CLOCK / xptr->oreg2); /* 60% off */
|
pmmi_ctx.ptimer = sim_os_msec() + 600 / (PMMI_CLOCK / pmmi_ctx.oreg2); /* 60% off */
|
||||||
} else {
|
} else {
|
||||||
xptr->ireg2 |= PMMI_TMR;
|
pmmi_ctx.ireg2 |= PMMI_TMR;
|
||||||
xptr->ptimer = sim_os_msec() + 400 / (PMMI_CLOCK / xptr->oreg2); /* 40% on */
|
pmmi_ctx.ptimer = sim_os_msec() + 400 / (PMMI_CLOCK / pmmi_ctx.oreg2); /* 40% on */
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
xptr->ptimer = sim_os_msec() + 100; /* default to 100ms if timer rate is 0 */
|
pmmi_ctx.ptimer = sim_os_msec() + 100; /* default to 100ms if timer rate is 0 */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Emulate dial tone */
|
/* Emulate dial tone */
|
||||||
if ((ms > xptr->dtimer) && (xptr->oreg0 & PMMI_SH) && (xptr->ireg2 & PMMI_DT)) {
|
if ((ms > pmmi_ctx.dtimer) && (pmmi_ctx.oreg0 & PMMI_SH) && (pmmi_ctx.ireg2 & PMMI_DT)) {
|
||||||
xptr->ireg2 &= ~PMMI_DT;
|
pmmi_ctx.ireg2 &= ~PMMI_DT;
|
||||||
sim_debug(STATUS_MSG, uptr->dptr, "dial tone active.\n");
|
sim_debug(STATUS_MSG, uptr->dptr, "dial tone active.\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -441,22 +434,19 @@ static t_stat pmmi_svc(UNIT *uptr)
|
||||||
/* Attach routine */
|
/* Attach routine */
|
||||||
static t_stat pmmi_attach(UNIT *uptr, CONST char *cptr)
|
static t_stat pmmi_attach(UNIT *uptr, CONST char *cptr)
|
||||||
{
|
{
|
||||||
PMMI_CTX *xptr;
|
|
||||||
t_stat r;
|
t_stat r;
|
||||||
|
|
||||||
xptr = uptr->dptr->ctxt;
|
|
||||||
|
|
||||||
sim_debug(VERBOSE_MSG, uptr->dptr, "attach (%s).\n", cptr);
|
sim_debug(VERBOSE_MSG, uptr->dptr, "attach (%s).\n", cptr);
|
||||||
|
|
||||||
if ((r = tmxr_attach(xptr->tmxr, uptr, cptr)) == SCPE_OK) {
|
if ((r = tmxr_attach(pmmi_ctx.tmxr, uptr, cptr)) == SCPE_OK) {
|
||||||
|
|
||||||
xptr->flags = uptr->flags; /* Save Flags */
|
pmmi_ctx.flags = uptr->flags; /* Save Flags */
|
||||||
|
|
||||||
if (!xptr->tmln->serport) {
|
if (!pmmi_ctx.tmln->serport) {
|
||||||
uptr->flags |= UNIT_PMMI_RTS; /* Force following DTR on sockets */
|
uptr->flags |= UNIT_PMMI_RTS; /* Force following DTR on sockets */
|
||||||
}
|
}
|
||||||
|
|
||||||
xptr->tmln->rcve = 1;
|
pmmi_ctx.tmln->rcve = 1;
|
||||||
|
|
||||||
sim_activate(uptr, uptr->wait);
|
sim_activate(uptr, uptr->wait);
|
||||||
|
|
||||||
|
@ -466,22 +456,17 @@ static t_stat pmmi_attach(UNIT *uptr, CONST char *cptr)
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Detach routine */
|
/* Detach routine */
|
||||||
static t_stat pmmi_detach(UNIT *uptr)
|
static t_stat pmmi_detach(UNIT *uptr)
|
||||||
{
|
{
|
||||||
PMMI_CTX *xptr;
|
|
||||||
|
|
||||||
sim_debug(VERBOSE_MSG, uptr->dptr, "detach.\n");
|
sim_debug(VERBOSE_MSG, uptr->dptr, "detach.\n");
|
||||||
|
|
||||||
if (uptr->flags & UNIT_ATT) {
|
if (uptr->flags & UNIT_ATT) {
|
||||||
xptr = uptr->dptr->ctxt;
|
uptr->flags = pmmi_ctx.flags; /* Restore Flags */
|
||||||
|
|
||||||
uptr->flags = xptr->flags; /* Restore Flags */
|
|
||||||
|
|
||||||
sim_cancel(uptr);
|
sim_cancel(uptr);
|
||||||
|
|
||||||
return (tmxr_detach(xptr->tmxr, uptr));
|
return (tmxr_detach(pmmi_ctx.tmxr, uptr));
|
||||||
}
|
}
|
||||||
|
|
||||||
return SCPE_UNATT;
|
return SCPE_UNATT;
|
||||||
|
@ -489,12 +474,9 @@ static t_stat pmmi_detach(UNIT *uptr)
|
||||||
|
|
||||||
static t_stat pmmi_set_baud(UNIT *uptr, int32 value, const char *cptr, void *desc)
|
static t_stat pmmi_set_baud(UNIT *uptr, int32 value, const char *cptr, void *desc)
|
||||||
{
|
{
|
||||||
PMMI_CTX *xptr;
|
|
||||||
int32 baud;
|
int32 baud;
|
||||||
t_stat r = SCPE_ARG;
|
t_stat r = SCPE_ARG;
|
||||||
|
|
||||||
xptr = uptr->dptr->ctxt;
|
|
||||||
|
|
||||||
if (!(uptr->flags & UNIT_ATT)) {
|
if (!(uptr->flags & UNIT_ATT)) {
|
||||||
return SCPE_UNATT;
|
return SCPE_UNATT;
|
||||||
}
|
}
|
||||||
|
@ -502,7 +484,7 @@ static t_stat pmmi_set_baud(UNIT *uptr, int32 value, const char *cptr, void *des
|
||||||
if (cptr != NULL) {
|
if (cptr != NULL) {
|
||||||
if (sscanf(cptr, "%d", &baud)) {
|
if (sscanf(cptr, "%d", &baud)) {
|
||||||
if (baud >= 61 && baud <=600) {
|
if (baud >= 61 && baud <=600) {
|
||||||
xptr->baud = baud;
|
pmmi_ctx.baud = baud;
|
||||||
r = pmmi_config_line(uptr);
|
r = pmmi_config_line(uptr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -513,12 +495,8 @@ static t_stat pmmi_set_baud(UNIT *uptr, int32 value, const char *cptr, void *des
|
||||||
|
|
||||||
static t_stat pmmi_show_baud(FILE *st, UNIT *uptr, int32 value, const void *desc)
|
static t_stat pmmi_show_baud(FILE *st, UNIT *uptr, int32 value, const void *desc)
|
||||||
{
|
{
|
||||||
PMMI_CTX *xptr;
|
|
||||||
|
|
||||||
xptr = uptr->dptr->ctxt;
|
|
||||||
|
|
||||||
if (uptr->flags & UNIT_ATT) {
|
if (uptr->flags & UNIT_ATT) {
|
||||||
fprintf(st, "Baud rate: %d", xptr->baud);
|
fprintf(st, "Baud rate: %d", pmmi_ctx.baud);
|
||||||
}
|
}
|
||||||
|
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
|
@ -526,15 +504,11 @@ static t_stat pmmi_show_baud(FILE *st, UNIT *uptr, int32 value, const void *desc
|
||||||
|
|
||||||
static t_stat pmmi_config_line(UNIT *uptr)
|
static t_stat pmmi_config_line(UNIT *uptr)
|
||||||
{
|
{
|
||||||
PMMI_CTX *xptr;
|
|
||||||
char config[20];
|
char config[20];
|
||||||
char b,p,s;
|
char b,p,s;
|
||||||
t_stat r = SCPE_IERR;
|
t_stat r = SCPE_IERR;
|
||||||
|
|
||||||
xptr = uptr->dptr->ctxt;
|
switch (pmmi_ctx.oreg0 & PMMI_BMSK) {
|
||||||
|
|
||||||
if (xptr != NULL) {
|
|
||||||
switch (xptr->oreg0 & PMMI_BMSK) {
|
|
||||||
case PMMI_5BIT:
|
case PMMI_5BIT:
|
||||||
b = '5';
|
b = '5';
|
||||||
break;
|
break;
|
||||||
|
@ -553,7 +527,7 @@ static t_stat pmmi_config_line(UNIT *uptr)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (xptr->oreg0 & PMMI_PMSK) {
|
switch (pmmi_ctx.oreg0 & PMMI_PMSK) {
|
||||||
case PMMI_OPAR:
|
case PMMI_OPAR:
|
||||||
p = 'O';
|
p = 'O';
|
||||||
break;
|
break;
|
||||||
|
@ -568,7 +542,7 @@ static t_stat pmmi_config_line(UNIT *uptr)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (xptr->oreg0 & PMMI_SMSK) {
|
switch (pmmi_ctx.oreg0 & PMMI_SMSK) {
|
||||||
case PMMI_2SB:
|
case PMMI_2SB:
|
||||||
s = '2';
|
s = '2';
|
||||||
break;
|
break;
|
||||||
|
@ -579,9 +553,9 @@ static t_stat pmmi_config_line(UNIT *uptr)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
sprintf(config, "%d-%c%c%c", xptr->baud, b,p,s);
|
sprintf(config, "%d-%c%c%c", pmmi_ctx.baud, b,p,s);
|
||||||
|
|
||||||
r = tmxr_set_config_line(xptr->tmln, config);
|
r = tmxr_set_config_line(pmmi_ctx.tmln, config);
|
||||||
|
|
||||||
sim_debug(STATUS_MSG, uptr->dptr, "port configuration set to '%s'.\n", config);
|
sim_debug(STATUS_MSG, uptr->dptr, "port configuration set to '%s'.\n", config);
|
||||||
|
|
||||||
|
@ -600,9 +574,8 @@ static t_stat pmmi_config_line(UNIT *uptr)
|
||||||
** Serial ports are self-limiting and sockets will run
|
** Serial ports are self-limiting and sockets will run
|
||||||
** at the clocked CPU speed.
|
** at the clocked CPU speed.
|
||||||
*/
|
*/
|
||||||
xptr->tmln->txbps = 0; /* Get TMXR's rate-limiting out of our way */
|
pmmi_ctx.tmln->txbps = 0; /* Get TMXR's rate-limiting out of our way */
|
||||||
xptr->tmln->rxbps = 0; /* Get TMXR's rate-limiting out of our way */
|
pmmi_ctx.tmln->rxbps = 0; /* Get TMXR's rate-limiting out of our way */
|
||||||
}
|
|
||||||
|
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
@ -643,29 +616,26 @@ static int32 pmmi_io(int32 addr, int32 io, int32 data)
|
||||||
|
|
||||||
static int32 pmmi_reg0(int32 io, int32 data)
|
static int32 pmmi_reg0(int32 io, int32 data)
|
||||||
{
|
{
|
||||||
PMMI_CTX *xptr;
|
|
||||||
int32 r;
|
int32 r;
|
||||||
|
|
||||||
xptr = pmmi_dev.ctxt;
|
|
||||||
|
|
||||||
if (io == IO_RD) {
|
if (io == IO_RD) {
|
||||||
r = xptr->ireg0;
|
r = pmmi_ctx.ireg0;
|
||||||
} else { xptr->oreg0 = data; /* Set UART configuration */
|
} else { pmmi_ctx.oreg0 = data; /* Set UART configuration */
|
||||||
pmmi_config_line(&pmmi_dev.units[0]);
|
pmmi_config_line(&pmmi_dev.units[0]);
|
||||||
|
|
||||||
if (data & PMMI_SH) { /* If off-hook, clear dialtone bit (active low) */
|
if (data & PMMI_SH) { /* If off-hook, clear dialtone bit (active low) */
|
||||||
xptr->dtimer = sim_os_msec() + 500; /* Dialtone in 500ms */
|
pmmi_ctx.dtimer = sim_os_msec() + 500; /* Dialtone in 500ms */
|
||||||
if (xptr->oreg0 & PMMI_SH) {
|
if (pmmi_ctx.oreg0 & PMMI_SH) {
|
||||||
xptr->ireg2 &= ~PMMI_AP; /* Answer Phone Bit (active low) */
|
pmmi_ctx.ireg2 &= ~PMMI_AP; /* Answer Phone Bit (active low) */
|
||||||
}
|
}
|
||||||
} else if (!(xptr->ireg2 & PMMI_DT)) {
|
} else if (!(pmmi_ctx.ireg2 & PMMI_DT)) {
|
||||||
xptr->dtimer = 0;
|
pmmi_ctx.dtimer = 0;
|
||||||
xptr->ireg2 |= PMMI_DT;
|
pmmi_ctx.ireg2 |= PMMI_DT;
|
||||||
sim_debug(STATUS_MSG, &pmmi_dev, "dial tone inactive.\n");
|
sim_debug(STATUS_MSG, &pmmi_dev, "dial tone inactive.\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data & PMMI_RI) { /* Go off-hook in answer mode */
|
if (data & PMMI_RI) { /* Go off-hook in answer mode */
|
||||||
xptr->ireg2 &= ~PMMI_AP; /* Answer Phone Bit (active low) */
|
pmmi_ctx.ireg2 &= ~PMMI_AP; /* Answer Phone Bit (active low) */
|
||||||
}
|
}
|
||||||
|
|
||||||
r = 0x00;
|
r = 0x00;
|
||||||
|
@ -676,18 +646,15 @@ static int32 pmmi_reg0(int32 io, int32 data)
|
||||||
|
|
||||||
static int32 pmmi_reg1(int32 io, int32 data)
|
static int32 pmmi_reg1(int32 io, int32 data)
|
||||||
{
|
{
|
||||||
PMMI_CTX *xptr;
|
|
||||||
int32 r;
|
int32 r;
|
||||||
|
|
||||||
xptr = pmmi_dev.ctxt;
|
|
||||||
|
|
||||||
if (io == IO_RD) {
|
if (io == IO_RD) {
|
||||||
r = xptr->ireg1;
|
r = pmmi_ctx.ireg1;
|
||||||
xptr->ireg0 &= ~(PMMI_DAV | PMMI_FE | PMMI_OR | PMMI_RPE);
|
pmmi_ctx.ireg0 &= ~(PMMI_DAV | PMMI_FE | PMMI_OR | PMMI_RPE);
|
||||||
} else {
|
} else {
|
||||||
xptr->oreg1 = data;
|
pmmi_ctx.oreg1 = data;
|
||||||
xptr->ireg0 &= ~(PMMI_TBMT | PMMI_TEOC);
|
pmmi_ctx.ireg0 &= ~(PMMI_TBMT | PMMI_TEOC);
|
||||||
xptr->txp = 1;
|
pmmi_ctx.txp = 1;
|
||||||
|
|
||||||
r = 0x00;
|
r = 0x00;
|
||||||
}
|
}
|
||||||
|
@ -697,15 +664,12 @@ static int32 pmmi_reg1(int32 io, int32 data)
|
||||||
|
|
||||||
static int32 pmmi_reg2(int32 io, int32 data)
|
static int32 pmmi_reg2(int32 io, int32 data)
|
||||||
{
|
{
|
||||||
PMMI_CTX *xptr;
|
|
||||||
int32 r;
|
int32 r;
|
||||||
|
|
||||||
xptr = pmmi_dev.ctxt;
|
|
||||||
|
|
||||||
if (io == IO_RD) {
|
if (io == IO_RD) {
|
||||||
r = xptr->ireg2;
|
r = pmmi_ctx.ireg2;
|
||||||
} else {
|
} else {
|
||||||
xptr->oreg2 = data;
|
pmmi_ctx.oreg2 = data;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** The actual baud rate is determined by the following:
|
** The actual baud rate is determined by the following:
|
||||||
|
@ -713,7 +677,7 @@ static int32 pmmi_reg2(int32 io, int32 data)
|
||||||
** value loaded into the rate generator.
|
** value loaded into the rate generator.
|
||||||
*/
|
*/
|
||||||
if (data) {
|
if (data) {
|
||||||
xptr->baud = 250000/(data * 16);
|
pmmi_ctx.baud = 250000/(data * 16);
|
||||||
|
|
||||||
pmmi_config_line(&pmmi_dev.units[0]);
|
pmmi_config_line(&pmmi_dev.units[0]);
|
||||||
}
|
}
|
||||||
|
@ -726,24 +690,23 @@ static int32 pmmi_reg2(int32 io, int32 data)
|
||||||
|
|
||||||
static int32 pmmi_reg3(int32 io, int32 data)
|
static int32 pmmi_reg3(int32 io, int32 data)
|
||||||
{
|
{
|
||||||
PMMI_CTX *xptr;
|
|
||||||
int32 s;
|
int32 s;
|
||||||
xptr = pmmi_dev.ctxt;
|
|
||||||
if (io == IO_RD) {
|
if (io == IO_RD) {
|
||||||
xptr->intmsk = xptr->oreg2; /* Load int mask from rate generator */
|
pmmi_ctx.intmsk = pmmi_ctx.oreg2; /* Load int mask from rate generator */
|
||||||
} else {
|
} else {
|
||||||
xptr->oreg3 = data;
|
pmmi_ctx.oreg3 = data;
|
||||||
/* Set/Clear DTR */
|
/* Set/Clear DTR */
|
||||||
s = TMXR_MDM_DTR | ((pmmi_dev.units[0].flags & UNIT_PMMI_RTS) ? TMXR_MDM_RTS : 0);
|
s = TMXR_MDM_DTR | ((pmmi_dev.units[0].flags & UNIT_PMMI_RTS) ? TMXR_MDM_RTS : 0);
|
||||||
if (data & PMMI_DTR) {
|
if (data & PMMI_DTR) {
|
||||||
tmxr_set_get_modem_bits(xptr->tmln, s, 0, NULL);
|
tmxr_set_get_modem_bits(pmmi_ctx.tmln, s, 0, NULL);
|
||||||
if (xptr->oreg0 & PMMI_SH) {
|
if (pmmi_ctx.oreg0 & PMMI_SH) {
|
||||||
xptr->ireg2 &= ~PMMI_AP; /* Answer Phone Bit (active low) */
|
pmmi_ctx.ireg2 &= ~PMMI_AP; /* Answer Phone Bit (active low) */
|
||||||
}
|
}
|
||||||
sim_debug(STATUS_MSG, &pmmi_dev, "set DTR HIGH.\n");
|
sim_debug(STATUS_MSG, &pmmi_dev, "set DTR HIGH.\n");
|
||||||
} else {
|
} else {
|
||||||
tmxr_set_get_modem_bits(xptr->tmln, 0, s, NULL);
|
tmxr_set_get_modem_bits(pmmi_ctx.tmln, 0, s, NULL);
|
||||||
xptr->ireg2 |= PMMI_AP;
|
pmmi_ctx.ireg2 |= PMMI_AP;
|
||||||
sim_debug(STATUS_MSG, &pmmi_dev, "set DTR LOW.\n");
|
sim_debug(STATUS_MSG, &pmmi_dev, "set DTR LOW.\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -707,10 +707,7 @@ static uint32 bytes_per_track(uint8 track)
|
||||||
static uint32 calculate_tarbell_sec_offset(uint8 track, uint8 sector)
|
static uint32 calculate_tarbell_sec_offset(uint8 track, uint8 sector)
|
||||||
{
|
{
|
||||||
uint32 offset;
|
uint32 offset;
|
||||||
uint8 dd,ds;
|
uint8 ds = tarbell_info->side[tarbell_info->currentDrive];
|
||||||
|
|
||||||
dd = tarbell_info->doubleDensity[tarbell_info->currentDrive];
|
|
||||||
ds = tarbell_info->side[tarbell_info->currentDrive];
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Side 0: tracks 0-76
|
** Side 0: tracks 0-76
|
||||||
|
@ -725,8 +722,7 @@ static uint32 calculate_tarbell_sec_offset(uint8 track, uint8 sector)
|
||||||
*/
|
*/
|
||||||
if (track==0) {
|
if (track==0) {
|
||||||
offset=0;
|
offset=0;
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
offset=TARBELL_SPT_SD * TARBELL_SECTOR_LEN; /* Track 0 / Side 0 always SD */
|
offset=TARBELL_SPT_SD * TARBELL_SECTOR_LEN; /* Track 0 / Side 0 always SD */
|
||||||
offset+=(track-1) * secs_per_track(track) * TARBELL_SECTOR_LEN; /* Track 1-153 */
|
offset+=(track-1) * secs_per_track(track) * TARBELL_SECTOR_LEN; /* Track 1-153 */
|
||||||
}
|
}
|
||||||
|
@ -736,7 +732,7 @@ static uint32 calculate_tarbell_sec_offset(uint8 track, uint8 sector)
|
||||||
*/
|
*/
|
||||||
offset += (sector-1)*TARBELL_SECTOR_LEN;
|
offset += (sector-1)*TARBELL_SECTOR_LEN;
|
||||||
|
|
||||||
DBG_PRINT(("TARBELL: OFFSET drive=%d side=%d den=%d track=%03d sector=%03d\n", tarbell_info->currentDrive, ds, dd, track, sector));
|
DBG_PRINT(("TARBELL: OFFSET drive=%d side=%d den=%d track=%03d sector=%03d\n", tarbell_info->currentDrive, ds, tarbell_info->doubleDensity[tarbell_info->currentDrive], track, sector));
|
||||||
|
|
||||||
return (offset);
|
return (offset);
|
||||||
}
|
}
|
||||||
|
@ -773,7 +769,6 @@ static uint8 TARBELL_Read(uint32 Addr)
|
||||||
FD17XX_REG *pFD17XX;
|
FD17XX_REG *pFD17XX;
|
||||||
UNIT *uptr;
|
UNIT *uptr;
|
||||||
|
|
||||||
cData = 0;
|
|
||||||
driveNum = tarbell_info->currentDrive;
|
driveNum = tarbell_info->currentDrive;
|
||||||
uptr = tarbell_info->uptr[driveNum];
|
uptr = tarbell_info->uptr[driveNum];
|
||||||
pFD17XX = &tarbell_info->FD17XX;
|
pFD17XX = &tarbell_info->FD17XX;
|
||||||
|
@ -801,29 +796,25 @@ static uint8 TARBELL_Read(uint32 Addr)
|
||||||
pFD17XX->dataCount = 0;
|
pFD17XX->dataCount = 0;
|
||||||
pFD17XX->status = 0x00;
|
pFD17XX->status = 0x00;
|
||||||
pFD17XX->intrq = TRUE;
|
pFD17XX->intrq = TRUE;
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
pFD17XX->status |= FD17XX_STAT_DRQ; /* Another byte is ready */
|
pFD17XX->status |= FD17XX_STAT_DRQ; /* Another byte is ready */
|
||||||
}
|
}
|
||||||
|
|
||||||
TARBELL_HeadLoad(uptr, pFD17XX, TRUE);
|
TARBELL_HeadLoad(uptr, pFD17XX, TRUE);
|
||||||
}
|
} else if (pFD17XX->readTrkActive) {
|
||||||
else if (pFD17XX->readTrkActive) {
|
|
||||||
/* If we reached the end of the track data, terminate command and set INTRQ */
|
/* If we reached the end of the track data, terminate command and set INTRQ */
|
||||||
if (pFD17XX->trkCount == bytes_per_track(pFD17XX->track)) {
|
if (pFD17XX->trkCount == bytes_per_track(pFD17XX->track)) {
|
||||||
pFD17XX->readTrkActive = FALSE;
|
pFD17XX->readTrkActive = FALSE;
|
||||||
pFD17XX->status = 0x00;
|
pFD17XX->status = 0x00;
|
||||||
pFD17XX->intrq = TRUE;
|
pFD17XX->intrq = TRUE;
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
pFD17XX->trkCount++;
|
pFD17XX->trkCount++;
|
||||||
|
|
||||||
pFD17XX->status |= FD17XX_STAT_DRQ; /* Another byte is ready */
|
pFD17XX->status |= FD17XX_STAT_DRQ; /* Another byte is ready */
|
||||||
}
|
}
|
||||||
|
|
||||||
TARBELL_HeadLoad(uptr, pFD17XX, TRUE);
|
TARBELL_HeadLoad(uptr, pFD17XX, TRUE);
|
||||||
}
|
} else if (pFD17XX->addrActive) {
|
||||||
else if (pFD17XX->addrActive) {
|
|
||||||
/* Store byte in DATA register */
|
/* Store byte in DATA register */
|
||||||
pFD17XX->data = sdata[pFD17XX->dataCount++];
|
pFD17XX->data = sdata[pFD17XX->dataCount++];
|
||||||
|
|
||||||
|
@ -834,8 +825,7 @@ static uint8 TARBELL_Read(uint32 Addr)
|
||||||
pFD17XX->addrActive = FALSE;
|
pFD17XX->addrActive = FALSE;
|
||||||
pFD17XX->status = 0x00;
|
pFD17XX->status = 0x00;
|
||||||
pFD17XX->intrq = TRUE;
|
pFD17XX->intrq = TRUE;
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
pFD17XX->status |= FD17XX_STAT_DRQ; /* Another byte is ready */
|
pFD17XX->status |= FD17XX_STAT_DRQ; /* Another byte is ready */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -912,14 +902,12 @@ static uint8 TARBELL_Write(uint32 Addr, int32 Data)
|
||||||
pFD17XX->writeActive = FALSE;
|
pFD17XX->writeActive = FALSE;
|
||||||
pFD17XX->dataCount = 0;
|
pFD17XX->dataCount = 0;
|
||||||
pFD17XX->intrq = TRUE;
|
pFD17XX->intrq = TRUE;
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
pFD17XX->status |= FD17XX_STAT_DRQ; /* Ready for another byte */
|
pFD17XX->status |= FD17XX_STAT_DRQ; /* Ready for another byte */
|
||||||
}
|
}
|
||||||
|
|
||||||
TARBELL_HeadLoad(uptr, pFD17XX, TRUE);
|
TARBELL_HeadLoad(uptr, pFD17XX, TRUE);
|
||||||
}
|
} else if (pFD17XX->writeTrkActive) {
|
||||||
else if (pFD17XX->writeTrkActive) {
|
|
||||||
|
|
||||||
if (pFD17XX->dataAddrMrk) {
|
if (pFD17XX->dataAddrMrk) {
|
||||||
/* Store DATA register in Sector Buffer */
|
/* Store DATA register in Sector Buffer */
|
||||||
|
@ -957,8 +945,7 @@ static uint8 TARBELL_Write(uint32 Addr, int32 Data)
|
||||||
|
|
||||||
if (pFD17XX->trkCount < bytes_per_track(pFD17XX->track)) {
|
if (pFD17XX->trkCount < bytes_per_track(pFD17XX->track)) {
|
||||||
pFD17XX->status |= FD17XX_STAT_DRQ; /* Ready for another byte */
|
pFD17XX->status |= FD17XX_STAT_DRQ; /* Ready for another byte */
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
pFD17XX->status = 0x00; /* Clear Status Bits */
|
pFD17XX->status = 0x00; /* Clear Status Bits */
|
||||||
pFD17XX->intrq = TRUE;
|
pFD17XX->intrq = TRUE;
|
||||||
pFD17XX->status &= ~FD17XX_STAT_BUSY; /* Clear BUSY Bit */
|
pFD17XX->status &= ~FD17XX_STAT_BUSY; /* Clear BUSY Bit */
|
||||||
|
@ -1140,8 +1127,7 @@ static uint8 TARBELL_Command(UNIT *uptr, FD17XX_REG *pFD17XX, int32 Data)
|
||||||
TARBELL_HeadLoad(uptr, pFD17XX, (Data & TARBELL_FLAG_H) ? TRUE : FALSE);
|
TARBELL_HeadLoad(uptr, pFD17XX, (Data & TARBELL_FLAG_H) ? TRUE : FALSE);
|
||||||
|
|
||||||
sim_debug(SEEK_MSG, &tarbell_dev, TARBELL_SNAME ": SEEK track=%03d\n", pFD17XX->track);
|
sim_debug(SEEK_MSG, &tarbell_dev, TARBELL_SNAME ": SEEK track=%03d\n", pFD17XX->track);
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
pFD17XX->status |= FD17XX_STAT_SEEKERROR;
|
pFD17XX->status |= FD17XX_STAT_SEEKERROR;
|
||||||
sim_debug(SEEK_MSG, &tarbell_dev, TARBELL_SNAME ": SEEK ERR track=%03d\n", newTrack);
|
sim_debug(SEEK_MSG, &tarbell_dev, TARBELL_SNAME ": SEEK ERR track=%03d\n", newTrack);
|
||||||
}
|
}
|
||||||
|
@ -1162,8 +1148,7 @@ static uint8 TARBELL_Command(UNIT *uptr, FD17XX_REG *pFD17XX, int32 Data)
|
||||||
pFD17XX->track = newTrack;
|
pFD17XX->track = newTrack;
|
||||||
}
|
}
|
||||||
sim_debug(SEEK_MSG, &tarbell_dev, TARBELL_SNAME ": STEP track=%03d\n", pFD17XX->track);
|
sim_debug(SEEK_MSG, &tarbell_dev, TARBELL_SNAME ": STEP track=%03d\n", pFD17XX->track);
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
pFD17XX->status |= FD17XX_STAT_SEEKERROR;
|
pFD17XX->status |= FD17XX_STAT_SEEKERROR;
|
||||||
sim_debug(SEEK_MSG, &tarbell_dev, TARBELL_SNAME ": STEP ERR track=%03d\n", newTrack);
|
sim_debug(SEEK_MSG, &tarbell_dev, TARBELL_SNAME ": STEP ERR track=%03d\n", newTrack);
|
||||||
}
|
}
|
||||||
|
@ -1187,8 +1172,7 @@ static uint8 TARBELL_Command(UNIT *uptr, FD17XX_REG *pFD17XX, int32 Data)
|
||||||
TARBELL_HeadLoad(uptr, pFD17XX, (Data & TARBELL_FLAG_H) ? TRUE : FALSE);
|
TARBELL_HeadLoad(uptr, pFD17XX, (Data & TARBELL_FLAG_H) ? TRUE : FALSE);
|
||||||
|
|
||||||
sim_debug(SEEK_MSG, &tarbell_dev, TARBELL_SNAME ": STEPIN track=%03d\n", pFD17XX->track);
|
sim_debug(SEEK_MSG, &tarbell_dev, TARBELL_SNAME ": STEPIN track=%03d\n", pFD17XX->track);
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
pFD17XX->status |= FD17XX_STAT_SEEKERROR;
|
pFD17XX->status |= FD17XX_STAT_SEEKERROR;
|
||||||
sim_debug(SEEK_MSG, &tarbell_dev, TARBELL_SNAME ": STEPIN ERR track=%03d\n", pFD17XX->track+1);
|
sim_debug(SEEK_MSG, &tarbell_dev, TARBELL_SNAME ": STEPIN ERR track=%03d\n", pFD17XX->track+1);
|
||||||
}
|
}
|
||||||
|
@ -1211,8 +1195,7 @@ static uint8 TARBELL_Command(UNIT *uptr, FD17XX_REG *pFD17XX, int32 Data)
|
||||||
TARBELL_HeadLoad(uptr, pFD17XX, (Data & TARBELL_FLAG_H) ? TRUE : FALSE);
|
TARBELL_HeadLoad(uptr, pFD17XX, (Data & TARBELL_FLAG_H) ? TRUE : FALSE);
|
||||||
|
|
||||||
sim_debug(SEEK_MSG, &tarbell_dev, TARBELL_SNAME ": STEPOUT track=%03d\n", pFD17XX->track);
|
sim_debug(SEEK_MSG, &tarbell_dev, TARBELL_SNAME ": STEPOUT track=%03d\n", pFD17XX->track);
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
pFD17XX->status |= FD17XX_STAT_SEEKERROR;
|
pFD17XX->status |= FD17XX_STAT_SEEKERROR;
|
||||||
sim_debug(SEEK_MSG, &tarbell_dev, TARBELL_SNAME ": STEPOUT ERR track=%03d\n", pFD17XX->track-1);
|
sim_debug(SEEK_MSG, &tarbell_dev, TARBELL_SNAME ": STEPOUT ERR track=%03d\n", pFD17XX->track-1);
|
||||||
}
|
}
|
||||||
|
@ -1241,8 +1224,7 @@ static uint8 TARBELL_Command(UNIT *uptr, FD17XX_REG *pFD17XX, int32 Data)
|
||||||
pFD17XX->readActive = TRUE;
|
pFD17XX->readActive = TRUE;
|
||||||
|
|
||||||
showdata(TRUE);
|
showdata(TRUE);
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
sim_debug(ERROR_MSG, &tarbell_dev, TARBELL_SNAME ": sim_fread errno=%d\n", errno);
|
sim_debug(ERROR_MSG, &tarbell_dev, TARBELL_SNAME ": sim_fread errno=%d\n", errno);
|
||||||
|
|
||||||
pFD17XX->status |= FD17XX_STAT_NOTFOUND;
|
pFD17XX->status |= FD17XX_STAT_NOTFOUND;
|
||||||
|
@ -1266,8 +1248,7 @@ static uint8 TARBELL_Command(UNIT *uptr, FD17XX_REG *pFD17XX, int32 Data)
|
||||||
if ((uptr->flags & UNIT_TARBELL_WPROTECT) || tarbell_info->writeProtect) {
|
if ((uptr->flags & UNIT_TARBELL_WPROTECT) || tarbell_info->writeProtect) {
|
||||||
DBG_PRINT((TARBELL_SNAME ": Disk write protected. uptr->flags=%04x writeProtect=%04x\n", uptr->flags & UNIT_TARBELL_WPROTECT, tarbell_info->writeProtect));
|
DBG_PRINT((TARBELL_SNAME ": Disk write protected. uptr->flags=%04x writeProtect=%04x\n", uptr->flags & UNIT_TARBELL_WPROTECT, tarbell_info->writeProtect));
|
||||||
pFD17XX->intrq = TRUE;
|
pFD17XX->intrq = TRUE;
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
pFD17XX->writeActive = TRUE;
|
pFD17XX->writeActive = TRUE;
|
||||||
pFD17XX->dataCount = 0;
|
pFD17XX->dataCount = 0;
|
||||||
pFD17XX->status |= FD17XX_STAT_DRQ; /* Set DRQ */
|
pFD17XX->status |= FD17XX_STAT_DRQ; /* Set DRQ */
|
||||||
|
@ -1300,8 +1281,7 @@ static uint8 TARBELL_Command(UNIT *uptr, FD17XX_REG *pFD17XX, int32 Data)
|
||||||
if ((uptr->flags & UNIT_TARBELL_WPROTECT) || tarbell_info->writeProtect) {
|
if ((uptr->flags & UNIT_TARBELL_WPROTECT) || tarbell_info->writeProtect) {
|
||||||
DBG_PRINT((TARBELL_SNAME ": Disk write protected. uptr->flags=%04x writeProtect=%04x\n", uptr->flags & UNIT_TARBELL_WPROTECT, tarbell_info->writeProtect));
|
DBG_PRINT((TARBELL_SNAME ": Disk write protected. uptr->flags=%04x writeProtect=%04x\n", uptr->flags & UNIT_TARBELL_WPROTECT, tarbell_info->writeProtect));
|
||||||
pFD17XX->intrq = TRUE;
|
pFD17XX->intrq = TRUE;
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
pFD17XX->writeTrkActive = TRUE;
|
pFD17XX->writeTrkActive = TRUE;
|
||||||
pFD17XX->trkCount=0;
|
pFD17XX->trkCount=0;
|
||||||
pFD17XX->dataCount=0;
|
pFD17XX->dataCount=0;
|
||||||
|
|
|
@ -331,6 +331,10 @@
|
||||||
RelativePath="..\AltairZ80\s100_if3.c"
|
RelativePath="..\AltairZ80\s100_if3.c"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\AltairZ80\s100_icom.c"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\AltairZ80\s100_jadedd.c"
|
RelativePath="..\AltairZ80\s100_jadedd.c"
|
||||||
>
|
>
|
||||||
|
|
Binary file not shown.
1
makefile
1
makefile
|
@ -1736,6 +1736,7 @@ ALTAIRZ80 = ${ALTAIRZ80D}/altairz80_cpu.c ${ALTAIRZ80D}/altairz80_cpu_nommu.c \
|
||||||
${ALTAIRZ80D}/mfdc.c ${ALTAIRZ80D}/n8vem.c ${ALTAIRZ80D}/vfdhd.c \
|
${ALTAIRZ80D}/mfdc.c ${ALTAIRZ80D}/n8vem.c ${ALTAIRZ80D}/vfdhd.c \
|
||||||
${ALTAIRZ80D}/s100_disk1a.c ${ALTAIRZ80D}/s100_disk2.c ${ALTAIRZ80D}/s100_disk3.c \
|
${ALTAIRZ80D}/s100_disk1a.c ${ALTAIRZ80D}/s100_disk2.c ${ALTAIRZ80D}/s100_disk3.c \
|
||||||
${ALTAIRZ80D}/s100_fif.c ${ALTAIRZ80D}/s100_mdriveh.c \
|
${ALTAIRZ80D}/s100_fif.c ${ALTAIRZ80D}/s100_mdriveh.c \
|
||||||
|
${ALTAIRZ80D}/s100_icom.c \
|
||||||
${ALTAIRZ80D}/s100_jadedd.c \
|
${ALTAIRZ80D}/s100_jadedd.c \
|
||||||
${ALTAIRZ80D}/s100_mdsa.c \
|
${ALTAIRZ80D}/s100_mdsa.c \
|
||||||
${ALTAIRZ80D}/s100_mdsad.c ${ALTAIRZ80D}/s100_selchan.c \
|
${ALTAIRZ80D}/s100_mdsad.c ${ALTAIRZ80D}/s100_selchan.c \
|
||||||
|
|
Loading…
Add table
Reference in a new issue