imds-224, isys80xx: Rework attach routines to leverage SCP provided functionality
This commit is contained in:
parent
0586d34f16
commit
357910dfb9
21 changed files with 412 additions and 2392 deletions
|
@ -1,866 +0,0 @@
|
||||||
/* i8237.c: Intel 8237 DMA adapter
|
|
||||||
|
|
||||||
Copyright (c) 2016, William A. Beech
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a
|
|
||||||
copy of this software and associated documentation files (the "Software"),
|
|
||||||
to deal in the Software without restriction, including without limitation
|
|
||||||
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
||||||
and/or sell copies of the Software, and to permit persons to whom the
|
|
||||||
Software is furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in
|
|
||||||
all copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
|
||||||
WILLIAM A. BEECH BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
|
||||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
|
||||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
|
|
||||||
Except as contained in this notice, the name of William A. Beech shall not be
|
|
||||||
used in advertising or otherwise to promote the sale, use or other dealings
|
|
||||||
in this Software without prior written authorization from William A. Beech.
|
|
||||||
|
|
||||||
MODIFICATIONS:
|
|
||||||
|
|
||||||
11 Jul 16 - Original file.
|
|
||||||
|
|
||||||
NOTES:
|
|
||||||
|
|
||||||
|
|
||||||
Default is none. Since all channel registers in the i8237 are 16-bit, transfers
|
|
||||||
are done as two 8-bit operations, low- then high-byte.
|
|
||||||
|
|
||||||
Port addressing is as follows (Port offset = 0):
|
|
||||||
|
|
||||||
Port Mode Command Function
|
|
||||||
|
|
||||||
00 Write Load DMAC Channel 0 Base and Current Address Regsiters
|
|
||||||
Read Read DMAC Channel 0 Current Address Register
|
|
||||||
01 Write Load DMAC Channel 0 Base and Current Word Count Registers
|
|
||||||
Read Read DMAC Channel 0 Current Word Count Register
|
|
||||||
02 Write Load DMAC Channel 1 Base and Current Address Regsiters
|
|
||||||
Read Read DMAC Channel 1 Current Address Register
|
|
||||||
03 Write Load DMAC Channel 1 Base and Current Word Count Registers
|
|
||||||
Read Read DMAC Channel 1 Current Word Count Register
|
|
||||||
04 Write Load DMAC Channel 2 Base and Current Address Regsiters
|
|
||||||
Read Read DMAC Channel 2 Current Address Register
|
|
||||||
05 Write Load DMAC Channel 2 Base and Current Word Count Registers
|
|
||||||
Read Read DMAC Channel 2 Current Word Count Register
|
|
||||||
06 Write Load DMAC Channel 3 Base and Current Address Regsiters
|
|
||||||
Read Read DMAC Channel 3 Current Address Register
|
|
||||||
07 Write Load DMAC Channel 3 Base and Current Word Count Registers
|
|
||||||
Read Read DMAC Channel 3 Current Word Count Register
|
|
||||||
08 Write Load DMAC Command Register
|
|
||||||
Read Read DMAC Status Register
|
|
||||||
09 Write Load DMAC Request Register
|
|
||||||
0A Write Set/Reset DMAC Mask Register
|
|
||||||
0B Write Load DMAC Mode Register
|
|
||||||
0C Write Clear DMAC First/Last Flip-Flop
|
|
||||||
0D Write DMAC Master Clear
|
|
||||||
0F Write Load DMAC Mask Register
|
|
||||||
|
|
||||||
Register usage is defined in the following paragraphs.
|
|
||||||
|
|
||||||
Read/Write DMAC Address Registers
|
|
||||||
|
|
||||||
Used to simultaneously load a channel's current-address register and base-address
|
|
||||||
register with the memory address of the first byte to be transferred. (The Channel
|
|
||||||
0 current/base address register must be loaded prior to initiating a diskette read
|
|
||||||
or write operation.) Since each channel's address registers are 16 bits in length
|
|
||||||
(64K address range), two "write address register" commands must be executed in
|
|
||||||
order to load the complete current/base address registers for any channel.
|
|
||||||
|
|
||||||
Read/Write DMAC Word Count Registers
|
|
||||||
|
|
||||||
The Write DMAC Word Count Register command is used to simultaneously load a
|
|
||||||
channel's current and base word-count registers with the number of bytes
|
|
||||||
to be transferred during a subsequent DMA operation. Since the word-count
|
|
||||||
registers are 16-bits in length, two commands must be executed to load both
|
|
||||||
halves of the registers.
|
|
||||||
|
|
||||||
Write DMAC Command Register
|
|
||||||
|
|
||||||
The Write DMAC Command Register command loads an 8-bit byte into the
|
|
||||||
DMAC's command register to define the operating characteristics of the
|
|
||||||
DMAC. The functions of the individual bits in the command register are
|
|
||||||
defined in the following diagram. Note that only two bits within the
|
|
||||||
register are applicable to the controller; the remaining bits select
|
|
||||||
functions that are not supported and, accordingly, must always be set
|
|
||||||
to zero.
|
|
||||||
|
|
||||||
7 6 5 4 3 2 1 0
|
|
||||||
+---+---+---+---+---+---+---+---+
|
|
||||||
| 0 0 0 0 0 0 |
|
|
||||||
+---+---+---+---+---+---+---+---+
|
|
||||||
| |
|
|
||||||
| +---------- 0 CONTROLLER ENABLE
|
|
||||||
| 1 CONTROLLER DISABLE
|
|
||||||
|
|
|
||||||
+------------------ 0 FIXED PRIORITY
|
|
||||||
1 ROTATING PRIORITY
|
|
||||||
|
|
||||||
Read DMAC Status Register Command
|
|
||||||
|
|
||||||
The Read DMAC Status Register command accesses an 8-bit status byte that
|
|
||||||
identifies the DMA channels that have reached terminal count or that
|
|
||||||
have a pending DMA request.
|
|
||||||
|
|
||||||
7 6 5 4 3 2 1 0
|
|
||||||
+---+---+---+---+---+---+---+---+
|
|
||||||
| 0 0 |
|
|
||||||
+---+---+---+---+---+---+---+---+
|
|
||||||
| | | | | |
|
|
||||||
| | | | | +-- CHANNEL 0 TC
|
|
||||||
| | | | +---------- CHANNEL 2 TC
|
|
||||||
| | | +-------------- CHANNEL 3 TC
|
|
||||||
| | +------------------ CHANNEL 0 DMA REQUEST
|
|
||||||
| +-------------------------- CHANNEL 2 DMA REQUEST
|
|
||||||
+------------------------------ CHANNEL 3 DMA REQUEST
|
|
||||||
|
|
||||||
Write DMAC Request Register
|
|
||||||
|
|
||||||
The data byte associated with the Write DMAC Request Register command
|
|
||||||
sets or resets a channel's associated request bit within the DMAC's
|
|
||||||
internal 4-bit request register.
|
|
||||||
|
|
||||||
7 6 5 4 3 2 1 0
|
|
||||||
+---+---+---+---+---+---+---+---+
|
|
||||||
| X X X X X |
|
|
||||||
+---+---+---+---+---+---+---+---+
|
|
||||||
| | |
|
|
||||||
| +---+-- 00 SELECT CHANNEL 0
|
|
||||||
| 01 SELECT CHANNEL 1
|
|
||||||
| 10 SELECT CHANNEL 2
|
|
||||||
| 11 SELECT CHANNEL 3
|
|
||||||
|
|
|
||||||
+---------- 0 RESET REQUEST BIT
|
|
||||||
1 SET REQUEST BIT
|
|
||||||
|
|
||||||
Set/Reset DMAC Mask Register
|
|
||||||
|
|
||||||
Prior to a DREQ-initiated DMA transfer, the channel's mask bit must
|
|
||||||
be reset to enable recognition of the DREQ input. When the transfer
|
|
||||||
is complete (terminal count reached or external EOP applied) and
|
|
||||||
the channel is not programmed to autoinitialize, the channel's
|
|
||||||
mask bit is automatically set (disabling DREQ) and must be reset
|
|
||||||
prior to a subsequent DMA transfer. All four bits of the mask
|
|
||||||
register are set (disabling the DREQ inputs) by a DMAC master
|
|
||||||
clear or controller reset. Additionally, all four bits can be
|
|
||||||
set/reset by a single Write DMAC Mask Register command.
|
|
||||||
|
|
||||||
|
|
||||||
7 6 5 4 3 2 1 0
|
|
||||||
+---+---+---+---+---+---+---+---+
|
|
||||||
| X X X X X |
|
|
||||||
+---+---+---+---+---+---+---+---+
|
|
||||||
| | |
|
|
||||||
| +---+-- 00 SELECT CHANNEL 0
|
|
||||||
| 01 SELECT CHANNEL 1
|
|
||||||
| 10 SELECT CHANNEL 2
|
|
||||||
| 11 SELECT CHANNEL 3
|
|
||||||
|
|
|
||||||
+---------- 0 RESET REQUEST BIT
|
|
||||||
1 SET REQUEST BIT
|
|
||||||
|
|
||||||
Write DMAC Mode Register
|
|
||||||
|
|
||||||
The Write DMAC Mode Register command is used to define the
|
|
||||||
operating mode characteristics for each DMA channel. Each
|
|
||||||
channel has an internal 6-bit mode register; the high-order
|
|
||||||
six bits of the associated data byte are written into the
|
|
||||||
mode register addressed by the two low-order bits.
|
|
||||||
|
|
||||||
|
|
||||||
7 6 5 4 3 2 1 0
|
|
||||||
+---+---+---+---+---+---+---+---+
|
|
||||||
| |
|
|
||||||
+---+---+---+---+---+---+---+---+
|
|
||||||
| | | | | | | |
|
|
||||||
| | | | | | +---+-- 00 SELECT CHANNEL 0
|
|
||||||
| | | | | | 01 SELECT CHANNEL 1
|
|
||||||
| | | | | | 10 SELECT CHANNEL 2
|
|
||||||
| | | | | | 11 SELECT CHANNEL 3
|
|
||||||
| | | | | |
|
|
||||||
| | | | +---+---------- 00 VERIFY TRANSFER
|
|
||||||
| | | | 01 WRITE TRANSFER
|
|
||||||
| | | | 10 READ TRANSFER
|
|
||||||
| | | |
|
|
||||||
| | | +------------------ 0 AUTOINITIALIZE DISABLE
|
|
||||||
| | | 1 AUTOINITIALIZE ENABLE
|
|
||||||
| | |
|
|
||||||
| | +---------------------- 0 ADDRESS INCREMENT
|
|
||||||
| | 1 ADDRESS DECREMENT
|
|
||||||
| |
|
|
||||||
+---+-------------------------- 00 DEMAND MODE
|
|
||||||
01 SINGLE MODE
|
|
||||||
10 BLOCK MODE
|
|
||||||
|
|
||||||
Clear DMAC First/Last Flip-Flop
|
|
||||||
|
|
||||||
The Clear DMAC First/Last Flip-Flop command initializes
|
|
||||||
the DMAC's internal first/last flip-flop so that the
|
|
||||||
next byte written to or re~d from the 16-bit address
|
|
||||||
or word-count registers is the low-order byte. The
|
|
||||||
flip-flop is toggled with each register access so that
|
|
||||||
a second register read or write command accesses the
|
|
||||||
high-order byte.
|
|
||||||
|
|
||||||
DMAC Master Clear
|
|
||||||
|
|
||||||
The DMAC Master Clear command clears the DMAC's command, status,
|
|
||||||
request, and temporary registers to zero, initializes the
|
|
||||||
first/last flip-flop, and sets the four channel mask bits in
|
|
||||||
the mask register to disable all DMA requests (i.e., the DMAC
|
|
||||||
is placed in an idle state).
|
|
||||||
|
|
||||||
Write DMAC Mask Register
|
|
||||||
|
|
||||||
The Write DMAC Mask Register command allows all four bits of the
|
|
||||||
DMAC's mask register to be written with a single command.
|
|
||||||
|
|
||||||
7 6 5 4 3 2 1 0
|
|
||||||
+---+---+---+---+---+---+---+---+
|
|
||||||
| X X X X X |
|
|
||||||
+---+---+---+---+---+---+---+---+
|
|
||||||
| | |
|
|
||||||
| | +-- 0 CLEAR CHANNEL 0 MASK BIT
|
|
||||||
| | 1 SET CHANNEL 0 MASK BIT
|
|
||||||
| |
|
|
||||||
| +---------- 0 CLEAR CHANNEL 2 MASK BIT
|
|
||||||
| 1 SET CHANNEL 2 MASK BIT
|
|
||||||
|
|
|
||||||
+-------------- 0 CLEAR CHANNEL 3 MASK BIT
|
|
||||||
1 SET CHANNEL 3 MASK BIT
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "system_defs.h"
|
|
||||||
|
|
||||||
/* external globals */
|
|
||||||
|
|
||||||
extern uint16 port; //port called in dev_table[port]
|
|
||||||
|
|
||||||
/* globals */
|
|
||||||
|
|
||||||
int32 i8237_devnum = 0; //actual number of 8253 instances + 1
|
|
||||||
uint16 i8237_port[4]; //base port registered to each instance
|
|
||||||
|
|
||||||
/* function prototypes */
|
|
||||||
|
|
||||||
t_stat i8237_svc(UNIT *uptr);
|
|
||||||
t_stat i8237_reset(DEVICE *dptr, uint16 base);
|
|
||||||
void i8237_reset1(int32 devnum);
|
|
||||||
t_stat i8237_set_mode (UNIT *uptr, int32 val, CONST char *cptr, void *desc);
|
|
||||||
uint8 i8237_r0x(t_bool io, uint8 data);
|
|
||||||
uint8 i8237_r1x(t_bool io, uint8 data);
|
|
||||||
uint8 i8237_r2x(t_bool io, uint8 data);
|
|
||||||
uint8 i8237_r3x(t_bool io, uint8 data);
|
|
||||||
uint8 i8237_r4x(t_bool io, uint8 data);
|
|
||||||
uint8 i8237_r5x(t_bool io, uint8 data);
|
|
||||||
uint8 i8237_r6x(t_bool io, uint8 data);
|
|
||||||
uint8 i8237_r7x(t_bool io, uint8 data);
|
|
||||||
uint8 i8237_r8x(t_bool io, uint8 data);
|
|
||||||
uint8 i8237_r9x(t_bool io, uint8 data);
|
|
||||||
uint8 i8237_rAx(t_bool io, uint8 data);
|
|
||||||
uint8 i8237_rBx(t_bool io, uint8 data);
|
|
||||||
uint8 i8237_rCx(t_bool io, uint8 data);
|
|
||||||
uint8 i8237_rDx(t_bool io, uint8 data);
|
|
||||||
uint8 i8237_rEx(t_bool io, uint8 data);
|
|
||||||
uint8 i8237_rFx(t_bool io, uint8 data);
|
|
||||||
|
|
||||||
/* external function prototypes */
|
|
||||||
|
|
||||||
extern uint16 reg_dev(uint8 (*routine)(t_bool, uint8), uint16);
|
|
||||||
|
|
||||||
/* 8237 physical register definitions */
|
|
||||||
|
|
||||||
uint16 i8237_r0[4]; // 8237 ch 0 address register
|
|
||||||
uint16 i8237_r1[4]; // 8237 ch 0 count register
|
|
||||||
uint16 i8237_r2[4]; // 8237 ch 1 address register
|
|
||||||
uint16 i8237_r3[4]; // 8237 ch 1 count register
|
|
||||||
uint16 i8237_r4[4]; // 8237 ch 2 address register
|
|
||||||
uint16 i8237_r5[4]; // 8237 ch 2 count register
|
|
||||||
uint16 i8237_r6[4]; // 8237 ch 3 address register
|
|
||||||
uint16 i8237_r7[4]; // 8237 ch 3 count register
|
|
||||||
uint8 i8237_r8[4]; // 8237 status register
|
|
||||||
uint8 i8237_r9[4]; // 8237 command register
|
|
||||||
uint8 i8237_rA[4]; // 8237 mode register
|
|
||||||
uint8 i8237_rB[4]; // 8237 mask register
|
|
||||||
uint8 i8237_rC[4]; // 8237 request register
|
|
||||||
uint8 i8237_rD[4]; // 8237 first/last ff
|
|
||||||
uint8 i8237_rE[4]; // 8237
|
|
||||||
uint8 i8237_rF[4]; // 8237
|
|
||||||
|
|
||||||
/* i8237 physical register definitions */
|
|
||||||
|
|
||||||
uint16 i8237_sr[4]; // isbc-208 segment register
|
|
||||||
uint8 i8237_i[4]; // iSBC-208 interrupt register
|
|
||||||
uint8 i8237_a[4]; // iSBC-208 auxillary port register
|
|
||||||
|
|
||||||
/* i8237 Standard SIMH Device Data Structures - 1 unit */
|
|
||||||
|
|
||||||
UNIT i8237_unit[] = {
|
|
||||||
{ UDATA (0, 0, 0) ,20 }, /* i8237 0 */
|
|
||||||
{ UDATA (0, 0, 0) ,20 }, /* i8237 1 */
|
|
||||||
{ UDATA (0, 0, 0) ,20 }, /* i8237 2 */
|
|
||||||
{ UDATA (0, 0, 0) ,20 } /* i8237 3 */
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
REG i8237_reg[] = {
|
|
||||||
{ HRDATA (CH0ADR, i8237_r0[devnum], 16) },
|
|
||||||
{ HRDATA (CH0CNT, i8237_r1[devnum], 16) },
|
|
||||||
{ HRDATA (CH1ADR, i8237_r2[devnum], 16) },
|
|
||||||
{ HRDATA (CH1CNT, i8237_r3, 16) },
|
|
||||||
{ HRDATA (CH2ADR, i8237_r4, 16) },
|
|
||||||
{ HRDATA (CH2CNT, i8237_r5, 16) },
|
|
||||||
{ HRDATA (CH3ADR, i8237_r6, 16) },
|
|
||||||
{ HRDATA (CH3CNT, i8237_r7, 16) },
|
|
||||||
{ HRDATA (STAT37, i8237_r8, 8) },
|
|
||||||
{ HRDATA (CMD37, i8237_r9, 8) },
|
|
||||||
{ HRDATA (MODE, i8237_rA, 8) },
|
|
||||||
{ HRDATA (MASK, i8237_rB, 8) },
|
|
||||||
{ HRDATA (REQ, i8237_rC, 8) },
|
|
||||||
{ HRDATA (FF, i8237_rD, 8) },
|
|
||||||
{ HRDATA (SEGREG, i8237_sr, 8) },
|
|
||||||
{ HRDATA (AUX, i8237_a, 8) },
|
|
||||||
{ HRDATA (INT, i8237_i, 8) },
|
|
||||||
{ NULL }
|
|
||||||
};
|
|
||||||
|
|
||||||
MTAB i8237_mod[] = {
|
|
||||||
{ 0 }
|
|
||||||
};
|
|
||||||
|
|
||||||
DEBTAB i8237_debug[] = {
|
|
||||||
{ "ALL", DEBUG_all },
|
|
||||||
{ "FLOW", DEBUG_flow },
|
|
||||||
{ "READ", DEBUG_read },
|
|
||||||
{ "WRITE", DEBUG_write },
|
|
||||||
{ "LEV1", DEBUG_level1 },
|
|
||||||
{ "LEV2", DEBUG_level2 },
|
|
||||||
{ "REG", DEBUG_reg },
|
|
||||||
{ NULL }
|
|
||||||
};
|
|
||||||
|
|
||||||
DEVICE i8237_dev = {
|
|
||||||
"I8237", //name
|
|
||||||
i8237_unit, //units
|
|
||||||
i8237_reg, //registers
|
|
||||||
i8237_mod, //modifiers
|
|
||||||
1, //numunits
|
|
||||||
16, //aradix
|
|
||||||
32, //awidth
|
|
||||||
1, //aincr
|
|
||||||
16, //dradix
|
|
||||||
8, //dwidth
|
|
||||||
NULL, //examine
|
|
||||||
NULL, //deposit
|
|
||||||
// &i8237_reset, //deposit
|
|
||||||
NULL, //reset
|
|
||||||
NULL, //boot
|
|
||||||
NULL, //attach
|
|
||||||
NULL, //detach
|
|
||||||
NULL, //ctxt
|
|
||||||
DEV_DEBUG+DEV_DISABLE+DEV_DIS, //flags
|
|
||||||
0, //dctrl
|
|
||||||
// DEBUG_flow + DEBUG_read + DEBUG_write, //dctrl
|
|
||||||
i8237_debug, //debflags
|
|
||||||
NULL, //msize
|
|
||||||
NULL //lname
|
|
||||||
};
|
|
||||||
|
|
||||||
/* Service routines to handle simulator functions */
|
|
||||||
|
|
||||||
/* service routine - actually does the simulated DMA */
|
|
||||||
|
|
||||||
t_stat i8237_svc(UNIT *uptr)
|
|
||||||
{
|
|
||||||
sim_activate (&i8237_unit[uptr->u6], i8237_unit[uptr->u6].wait);
|
|
||||||
return SCPE_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Reset routine */
|
|
||||||
|
|
||||||
t_stat i8237_reset(DEVICE *dptr, uint16 base)
|
|
||||||
{
|
|
||||||
if (i8237_devnum > I8237_NUM) {
|
|
||||||
sim_printf("i8237_reset: too many devices!\n");
|
|
||||||
return SCPE_MEM;
|
|
||||||
}
|
|
||||||
sim_printf(" 8237 Reset\n");
|
|
||||||
sim_printf(" 8237: Registered at %03X\n", base);
|
|
||||||
i8237_port[i8237_devnum] = reg_dev(i8237_r0x, base);
|
|
||||||
reg_dev(i8237_r1x, base + 1);
|
|
||||||
reg_dev(i8237_r2x, base + 2);
|
|
||||||
reg_dev(i8237_r3x, base + 3);
|
|
||||||
reg_dev(i8237_r4x, base + 4);
|
|
||||||
reg_dev(i8237_r5x, base + 5);
|
|
||||||
reg_dev(i8237_r6x, base + 6);
|
|
||||||
reg_dev(i8237_r7x, base + 7);
|
|
||||||
reg_dev(i8237_r8x, base + 8);
|
|
||||||
reg_dev(i8237_r9x, base + 9);
|
|
||||||
reg_dev(i8237_rAx, base + 10);
|
|
||||||
reg_dev(i8237_rBx, base + 11);
|
|
||||||
reg_dev(i8237_rCx, base + 12);
|
|
||||||
reg_dev(i8237_rDx, base + 13);
|
|
||||||
reg_dev(i8237_rEx, base + 14);
|
|
||||||
reg_dev(i8237_rFx, base + 15);
|
|
||||||
sim_printf(" 8237 Reset\n");
|
|
||||||
sim_printf(" 8237: Registered at %03X\n", base);
|
|
||||||
sim_activate (&i8237_unit[i8237_devnum], i8237_unit[i8237_devnum].wait); /* activate unit */
|
|
||||||
if ((i8237_dev.flags & DEV_DIS) == 0)
|
|
||||||
i8237_reset1(i8237_devnum);
|
|
||||||
i8237_devnum++;
|
|
||||||
return SCPE_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8 i8237_get_dn(void)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i=0; i<I8237_NUM; i++)
|
|
||||||
if (port >=i8237_port[i] && port <= i8237_port[i] + 16)
|
|
||||||
return i;
|
|
||||||
sim_printf("i8237_get_dn: port %03X not in 8237 device table\n", port);
|
|
||||||
return 0xFF;
|
|
||||||
}
|
|
||||||
|
|
||||||
void i8237_reset1(int32 devnum)
|
|
||||||
{
|
|
||||||
int32 i;
|
|
||||||
UNIT *uptr;
|
|
||||||
|
|
||||||
uptr = i8237_dev[devnum].units;
|
|
||||||
if (uptr->capac == 0) { /* if not configured */
|
|
||||||
uptr->capac = 0; /* initialize unit */
|
|
||||||
uptr->u3 = 0;
|
|
||||||
uptr->u4 = 0;
|
|
||||||
uptr->u5 = 0;
|
|
||||||
uptr->u6 = i; /* unit number - only set here! */
|
|
||||||
sim_activate (&i8237_unit[devnum], i8237_unit[devnum].wait);
|
|
||||||
}
|
|
||||||
i8237_r8[devnum] = 0; /* status */
|
|
||||||
i8237_r9[devnum] = 0; /* command */
|
|
||||||
i8237_rB[devnum] = 0x0F; /* mask */
|
|
||||||
i8237_rC[devnum] = 0; /* request */
|
|
||||||
i8237_rD[devnum] = 0; /* first/last FF */
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* i8237 set mode = 8- or 16-bit data bus */
|
|
||||||
/* always 8-bit mode for current simulators */
|
|
||||||
|
|
||||||
t_stat i8237_set_mode(UNIT *uptr, int32 val, CONST char *cptr, void *desc)
|
|
||||||
{
|
|
||||||
sim_debug (DEBUG_flow, &i8237_dev, " i8237_set_mode: Entered with val=%08XH uptr->flags=%08X\n", val, uptr->flags);
|
|
||||||
sim_debug (DEBUG_flow, &i8237_dev, " i8237_set_mode: Done\n");
|
|
||||||
return SCPE_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* I/O instruction handlers, called from the CPU module when an
|
|
||||||
IN or OUT instruction is issued.
|
|
||||||
|
|
||||||
Each function is passed an 'io' flag, where 0 means a read from
|
|
||||||
the port, and 1 means a write to the port. On input, the actual
|
|
||||||
input is passed as the return value, on output, 'data' is written
|
|
||||||
to the device.
|
|
||||||
*/
|
|
||||||
|
|
||||||
uint8 i8237_r0x(t_bool io, uint8 data)
|
|
||||||
{
|
|
||||||
uint8 devnum;
|
|
||||||
|
|
||||||
if ((devnum = i8237_get_dn()) != 0xFF) {
|
|
||||||
if (io == 0) { /* read current address CH 0 */
|
|
||||||
if (i8237_rD) { /* high byte */
|
|
||||||
i8237_rD = 0;
|
|
||||||
sim_debug (DEBUG_reg, &i8237_dev, "i8237_r0[%d](H) read as %04X\n", devnum, i8237_r0[devnum]);
|
|
||||||
return (i8237_r0[devnum] >> 8);
|
|
||||||
} else { /* low byte */
|
|
||||||
i8237_rD++;
|
|
||||||
sim_debug (DEBUG_reg, &i8237_dev, "i8237_r0[%d](L) read as %04X\n", devnum, i8237_r0[devnum]);
|
|
||||||
return (i8237_r0[devnum] & 0xFF);
|
|
||||||
}
|
|
||||||
} else { /* write base & current address CH 0 */
|
|
||||||
if (i8237_rD) { /* high byte */
|
|
||||||
i8237_rD = 0;
|
|
||||||
i8237_r0[devnum] |= (data << 8);
|
|
||||||
sim_debug (DEBUG_reg, &i8237_dev, "i8237_r0[%d](H) set to %04X\n", devnum, i8237_r0[devnum]);
|
|
||||||
} else { /* low byte */
|
|
||||||
i8237_rD++;
|
|
||||||
i8237_r0[devnum] = data & 0xFF;
|
|
||||||
sim_debug (DEBUG_reg, &i8237_dev, "i8237_r0[%d](L) set to %04X\n"devnum, , i8237_r0[devnum]);
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8 i8237_r1x(t_bool io, uint8 data)
|
|
||||||
{
|
|
||||||
uint8 devnum;
|
|
||||||
|
|
||||||
if ((devnum = i8237_get_dn()) != 0xFF) {
|
|
||||||
if (io == 0) { /* read current word count CH 0 */
|
|
||||||
if (i8237_rD) { /* high byte */
|
|
||||||
i8237_rD = 0;
|
|
||||||
sim_debug (DEBUG_reg, &i8237_dev, "i8237_r1[%d](H) read as %04X\n", devnum, i8237_r1[devnum]);
|
|
||||||
return (i8237_r1[devnum][devnum] >> 8);
|
|
||||||
} else { /* low byte */
|
|
||||||
i8237_rD++;
|
|
||||||
sim_debug (DEBUG_reg, &i8237_dev, "i8237_r1[%d](L) read as %04X\n", devnum, i8237_r1[devnum]);
|
|
||||||
return (i8237_r1[devnum] & 0xFF);
|
|
||||||
}
|
|
||||||
} else { /* write base & current address CH 0 */
|
|
||||||
if (i8237_rD) { /* high byte */
|
|
||||||
i8237_rD = 0;
|
|
||||||
i8237_r1[devnum] |= (data << 8);
|
|
||||||
sim_debug (DEBUG_reg, &i8237_dev, "i8237_r1[%d](H) set to %04X\n", devnum, i8237_r1[devnum]);
|
|
||||||
} else { /* low byte */
|
|
||||||
i8237_rD++;
|
|
||||||
i8237_r1[devnum] = data & 0xFF;
|
|
||||||
sim_debug (DEBUG_reg, &i8237_dev, "i8237_r1[%d](L) set to %04X\n", devnum, i8237_r1[devnum]);
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8 i8237_r2x(t_bool io, uint8 data)
|
|
||||||
{
|
|
||||||
uint8 devnum;
|
|
||||||
|
|
||||||
if ((devnum = i8237_get_dn()) != 0xFF) {
|
|
||||||
if (io == 0) { /* read current address CH 1 */
|
|
||||||
if (i8237_rD) { /* high byte */
|
|
||||||
i8237_rD = 0;
|
|
||||||
sim_debug (DEBUG_reg, &i8237_dev, "i8237_r2[%d](H) read as %04X\n", devnum, i8237_r2[devnum]);
|
|
||||||
return (i8237_r2[devnum] >> 8);
|
|
||||||
} else { /* low byte */
|
|
||||||
i8237_rD++;
|
|
||||||
sim_debug (DEBUG_reg, &i8237_dev, "i8237_r2[%d](L) read as %04X\n", devnum, i8237_r2[devnum]);
|
|
||||||
return (i8237_r2[devnum] & 0xFF);
|
|
||||||
}
|
|
||||||
} else { /* write base & current address CH 1 */
|
|
||||||
if (i8237_rD) { /* high byte */
|
|
||||||
i8237_rD = 0;
|
|
||||||
i8237_r2[devnum] |= (data << 8);
|
|
||||||
sim_debug (DEBUG_reg, &i8237_dev, "i8237_r2[%d](H) set to %04X\n", devnum, i8237_r2[devnum]);
|
|
||||||
} else { /* low byte */
|
|
||||||
i8237_rD++;
|
|
||||||
i8237_r2[devnum] = data & 0xFF;
|
|
||||||
sim_debug (DEBUG_reg, &i8237_dev, "i8237_r2[%d](L) set to %04X\n", devnum, i8237_r2[devnum]);
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8 i8237_r3x(t_bool io, uint8 data)
|
|
||||||
{
|
|
||||||
uint8 devnum;
|
|
||||||
|
|
||||||
if ((devnum = i8237_get_dn()) != 0xFF) {
|
|
||||||
if (io == 0) { /* read current word count CH 1 */
|
|
||||||
if (i8237_rD) { /* high byte */
|
|
||||||
i8237_rD = 0;
|
|
||||||
sim_debug (DEBUG_reg, &i8237_dev, "i8237_r3(H) read as %04X\n", i8237_r3);
|
|
||||||
return (i8237_r3 >> 8);
|
|
||||||
} else { /* low byte */
|
|
||||||
i8237_rD++;
|
|
||||||
sim_debug (DEBUG_reg, &i8237_dev, "i8237_r3(L) read as %04X\n", i8237_r3);
|
|
||||||
return (i8237_r3 & 0xFF);
|
|
||||||
}
|
|
||||||
} else { /* write base & current address CH 1 */
|
|
||||||
if (i8237_rD) { /* high byte */
|
|
||||||
i8237_rD = 0;
|
|
||||||
i8237_r3 |= (data << 8);
|
|
||||||
sim_debug (DEBUG_reg, &i8237_dev, "i8237_r3(H) set to %04X\n", i8237_r3);
|
|
||||||
} else { /* low byte */
|
|
||||||
i8237_rD++;
|
|
||||||
i8237_r3 = data & 0xFF;
|
|
||||||
sim_debug (DEBUG_reg, &i8237_dev, "i8237_r3(L) set to %04X\n", i8237_r3);
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8 i8237_r4x(t_bool io, uint8 data)
|
|
||||||
{
|
|
||||||
uint8 devnum;
|
|
||||||
|
|
||||||
if ((devnum = i8237_get_dn()) != 0xFF) {
|
|
||||||
if (io == 0) { /* read current address CH 2 */
|
|
||||||
if (i8237_rD) { /* high byte */
|
|
||||||
i8237_rD = 0;
|
|
||||||
sim_debug (DEBUG_reg, &i8237_dev, "i8237_r4(H) read as %04X\n", i8237_r4);
|
|
||||||
return (i8237_r4 >> 8);
|
|
||||||
} else { /* low byte */
|
|
||||||
i8237_rD++;
|
|
||||||
sim_debug (DEBUG_reg, &i8237_dev, "i8237_r4(L) read as %04X\n", i8237_r4);
|
|
||||||
return (i8237_r4 & 0xFF);
|
|
||||||
}
|
|
||||||
} else { /* write base & current address CH 2 */
|
|
||||||
if (i8237_rD) { /* high byte */
|
|
||||||
i8237_rD = 0;
|
|
||||||
i8237_r4 |= (data << 8);
|
|
||||||
sim_debug (DEBUG_reg, &i8237_dev, "i8237_r4(H) set to %04X\n", i8237_r4);
|
|
||||||
} else { /* low byte */
|
|
||||||
i8237_rD++;
|
|
||||||
i8237_r4 = data & 0xFF;
|
|
||||||
sim_debug (DEBUG_reg, &i8237_dev, "i8237_r4(L) set to %04X\n", i8237_r4);
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8 i8237_r5x(t_bool io, uint8 data)
|
|
||||||
{
|
|
||||||
uint8 devnum;
|
|
||||||
|
|
||||||
if ((devnum = i8237_get_dn()) != 0xFF) {
|
|
||||||
if (io == 0) { /* read current word count CH 2 */
|
|
||||||
if (i8237_rD) { /* high byte */
|
|
||||||
i8237_rD = 0;
|
|
||||||
sim_debug (DEBUG_reg, &i8237_dev, "i8237_r5(H) read as %04X\n", i8237_r5);
|
|
||||||
return (i8237_r5 >> 8);
|
|
||||||
} else { /* low byte */
|
|
||||||
i8237_rD++;
|
|
||||||
sim_debug (DEBUG_reg, &i8237_dev, "i8237_r5(L) read as %04X\n", i8237_r5);
|
|
||||||
return (i8237_r5 & 0xFF);
|
|
||||||
}
|
|
||||||
} else { /* write base & current address CH 2 */
|
|
||||||
if (i8237_rD) { /* high byte */
|
|
||||||
i8237_rD = 0;
|
|
||||||
i8237_r5 |= (data << 8);
|
|
||||||
sim_debug (DEBUG_reg, &i8237_dev, "i8237_r5(H) set to %04X\n", i8237_r5);
|
|
||||||
} else { /* low byte */
|
|
||||||
i8237_rD++;
|
|
||||||
i8237_r5 = data & 0xFF;
|
|
||||||
sim_debug (DEBUG_reg, &i8237_dev, "i8237_r5(L) set to %04X\n", i8237_r5);
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8 i8237_r6x(t_bool io, uint8 data)
|
|
||||||
{
|
|
||||||
uint8 devnum;
|
|
||||||
|
|
||||||
if ((devnum = i8237_get_dn()) != 0xFF) {
|
|
||||||
if (io == 0) { /* read current address CH 3 */
|
|
||||||
if (i8237_rD) { /* high byte */
|
|
||||||
i8237_rD = 0;
|
|
||||||
sim_debug (DEBUG_reg, &i8237_dev, "i8237_r6(H) read as %04X\n", i8237_r6);
|
|
||||||
return (i8237_r6 >> 8);
|
|
||||||
} else { /* low byte */
|
|
||||||
i8237_rD++;
|
|
||||||
sim_debug (DEBUG_reg, &i8237_dev, "i8237_r6(L) read as %04X\n", i8237_r6);
|
|
||||||
return (i8237_r6 & 0xFF);
|
|
||||||
}
|
|
||||||
} else { /* write base & current address CH 3 */
|
|
||||||
if (i8237_rD) { /* high byte */
|
|
||||||
i8237_rD = 0;
|
|
||||||
i8237_r6 |= (data << 8);
|
|
||||||
sim_debug (DEBUG_reg, &i8237_dev, "i8237_r6(H) set to %04X\n", i8237_r6);
|
|
||||||
} else { /* low byte */
|
|
||||||
i8237_rD++;
|
|
||||||
i8237_r6 = data & 0xFF;
|
|
||||||
sim_debug (DEBUG_reg, &i8237_dev, "i8237_r6(L) set to %04X\n", i8237_r6);
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8 i8237_r7x(t_bool io, uint8 data)
|
|
||||||
{
|
|
||||||
uint8 devnum;
|
|
||||||
|
|
||||||
if ((devnum = i8237_get_dn()) != 0xFF) {
|
|
||||||
if (io == 0) { /* read current word count CH 3 */
|
|
||||||
if (i8237_rD) { /* high byte */
|
|
||||||
i8237_rD = 0;
|
|
||||||
sim_debug (DEBUG_reg, &i8237_dev, "i8237_r7(H) read as %04X\n", i8237_r7);
|
|
||||||
return (i8237_r7 >> 8);
|
|
||||||
} else { /* low byte */
|
|
||||||
i8237_rD++;
|
|
||||||
sim_debug (DEBUG_reg, &i8237_dev, "i8237_r7(L) read as %04X\n", i8237_r7);
|
|
||||||
return (i8237_r7 & 0xFF);
|
|
||||||
}
|
|
||||||
} else { /* write base & current address CH 3 */
|
|
||||||
if (i8237_rD) { /* high byte */
|
|
||||||
i8237_rD = 0;
|
|
||||||
i8237_r7 |= (data << 8);
|
|
||||||
sim_debug (DEBUG_reg, &i8237_dev, "i8237_r7(H) set to %04X\n", i8237_r7);
|
|
||||||
} else { /* low byte */
|
|
||||||
i8237_rD++;
|
|
||||||
i8237_r7 = data & 0xFF;
|
|
||||||
sim_debug (DEBUG_reg, &i8237_dev, "i8237_r7(L) set to %04X\n", i8237_r7);
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8 i8237_r8x(t_bool io, uint8 data)
|
|
||||||
{
|
|
||||||
uint8 devnum;
|
|
||||||
|
|
||||||
if ((devnum = i8237_get_dn()) != 0xFF) {
|
|
||||||
if (io == 0) { /* read status register */
|
|
||||||
sim_debug (DEBUG_reg, &i8237_dev, "i8237_r8 (status) read as %02X\n", i8237_r8);
|
|
||||||
return (i8237_r8);
|
|
||||||
} else { /* write command register */
|
|
||||||
i8237_r9 = data & 0xFF;
|
|
||||||
sim_debug (DEBUG_reg, &i8237_dev, "i8237_r9 (command) set to %02X\n", i8237_r9);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8 i8237_r9x(t_bool io, uint8 data)
|
|
||||||
{
|
|
||||||
uint8 devnum;
|
|
||||||
|
|
||||||
if ((devnum = i8237_get_dn()) != 0xFF) {
|
|
||||||
if (io == 0) {
|
|
||||||
sim_debug (DEBUG_reg, &i8237_dev, "Illegal read of i8237_r9\n");
|
|
||||||
return 0;
|
|
||||||
} else { /* write request register */
|
|
||||||
i8237_rC = data & 0xFF;
|
|
||||||
sim_debug (DEBUG_reg, &i8237_dev, "i8237_rC (request) set to %02X\n", i8237_rC);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8 i8237_rAx(t_bool io, uint8 data)
|
|
||||||
{
|
|
||||||
uint8 devnum;
|
|
||||||
|
|
||||||
if ((devnum = i8237_get_dn()) != 0xFF) {
|
|
||||||
if (io == 0) {
|
|
||||||
sim_debug (DEBUG_reg, &i8237_dev, "Illegal read of i8237_rA\n");
|
|
||||||
return 0;
|
|
||||||
} else { /* write single mask register */
|
|
||||||
switch(data & 0x03) {
|
|
||||||
case 0:
|
|
||||||
if (data & 0x04)
|
|
||||||
i8237_rB |= 1;
|
|
||||||
else
|
|
||||||
i8237_rB &= ~1;
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
if (data & 0x04)
|
|
||||||
i8237_rB |= 2;
|
|
||||||
else
|
|
||||||
i8237_rB &= ~2;
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
if (data & 0x04)
|
|
||||||
i8237_rB |= 4;
|
|
||||||
else
|
|
||||||
i8237_rB &= ~4;
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
if (data & 0x04)
|
|
||||||
i8237_rB |= 8;
|
|
||||||
else
|
|
||||||
i8237_rB &= ~8;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
sim_debug (DEBUG_reg, &i8237_dev, "i8237_rB (mask) set to %02X\n", i8237_rB);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8 i8237_rBx(t_bool io, uint8 data)
|
|
||||||
{
|
|
||||||
uint8 devnum;
|
|
||||||
|
|
||||||
if ((devnum = i8237_get_dn()) != 0xFF) {
|
|
||||||
if (io == 0) {
|
|
||||||
sim_debug (DEBUG_reg, &i8237_dev, "Illegal read of i8237_rB\n");
|
|
||||||
return 0;
|
|
||||||
} else { /* write mode register */
|
|
||||||
i8237_rA = data & 0xFF;
|
|
||||||
sim_debug (DEBUG_reg, &i8237_dev, "i8237_rA (mode) set to %02X\n", i8237_rA);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8 i8237_rCx(t_bool io, uint8 data)
|
|
||||||
{
|
|
||||||
uint8 devnum;
|
|
||||||
|
|
||||||
if ((devnum = i8237_get_dn()) != 0xFF) {
|
|
||||||
if (io == 0) {
|
|
||||||
sim_debug (DEBUG_reg, &i8237_dev, "Illegal read of i8237_rC\n");
|
|
||||||
return 0;
|
|
||||||
} else { /* clear byte pointer FF */
|
|
||||||
i8237_rD = 0;
|
|
||||||
sim_debug (DEBUG_reg, &i8237_dev, "i8237_rD (FF) cleared\n");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8 i8237_rDx(t_bool io, uint8 data)
|
|
||||||
{
|
|
||||||
uint8 devnum;
|
|
||||||
|
|
||||||
if ((devnum = i8237_get_dn()) != 0xFF) {
|
|
||||||
if (io == 0) { /* read temporary register */
|
|
||||||
sim_debug (DEBUG_reg, &i8237_dev, "Illegal read of i8237_rD\n");
|
|
||||||
return 0;
|
|
||||||
} else { /* master clear */
|
|
||||||
i8237_reset1();
|
|
||||||
sim_debug (DEBUG_reg, &i8237_dev, "i8237 master clear\n");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8 i8237_rEx(t_bool io, uint8 data)
|
|
||||||
{
|
|
||||||
uint8 devnum;
|
|
||||||
|
|
||||||
if ((devnum = i8237_get_dn()) != 0xFF) {
|
|
||||||
if (io == 0) {
|
|
||||||
sim_debug (DEBUG_reg, &i8237_dev, "Illegal read of i8237_rE\n");
|
|
||||||
return 0;
|
|
||||||
} else { /* clear mask register */
|
|
||||||
i8237_rB = 0;
|
|
||||||
sim_debug (DEBUG_reg, &i8237_dev, "i8237_rB (mask) cleared\n");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8 i8237_rFx(t_bool io, uint8 data)
|
|
||||||
{
|
|
||||||
uint8 devnum;
|
|
||||||
|
|
||||||
if ((devnum = i8237_get_dn()) != 0xFF) {
|
|
||||||
if (io == 0) {
|
|
||||||
sim_debug (DEBUG_reg, &i8237_dev, "Illegal read of i8237_rF\n");
|
|
||||||
return 0;
|
|
||||||
} else { /* write all mask register bits */
|
|
||||||
i8237_rB = data & 0x0F;
|
|
||||||
sim_debug (DEBUG_reg, &i8237_dev, "i8237_rB (mask) set to %02X\n", i8237_rB);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* end of i8237.c */
|
|
|
@ -142,8 +142,8 @@ t_stat i8253_reset (DEVICE *dptr, uint16 baseport)
|
||||||
sim_printf("i8253_reset: too many devices!\n");
|
sim_printf("i8253_reset: too many devices!\n");
|
||||||
return SCPE_MEM;
|
return SCPE_MEM;
|
||||||
}
|
}
|
||||||
sim_printf(" 8253-%d: Reset\n", i8253_devnum);
|
sim_printf(" 8253-%d: Reset\n", i8253_devnum);
|
||||||
sim_printf(" 8253-%d: Registered at %04X\n", i8253_devnum, baseport);
|
sim_printf(" 8253-%d: Registered at %04X\n", i8253_devnum, baseport);
|
||||||
i8253_port[i8253_devnum] = baseport;
|
i8253_port[i8253_devnum] = baseport;
|
||||||
reg_dev(i8253t0, baseport, i8253_devnum);
|
reg_dev(i8253t0, baseport, i8253_devnum);
|
||||||
reg_dev(i8253t1, baseport + 1, i8253_devnum);
|
reg_dev(i8253t1, baseport + 1, i8253_devnum);
|
||||||
|
|
|
@ -58,6 +58,12 @@ extern uint16 reg_dev(uint8 (*routine)(t_bool, uint8), uint16, uint8);
|
||||||
int32 i8259_devnum = 0; //actual number of 8259 instances + 1
|
int32 i8259_devnum = 0; //actual number of 8259 instances + 1
|
||||||
uint16 i8259_port[4]; //baseport port registered to each instance
|
uint16 i8259_port[4]; //baseport port registered to each instance
|
||||||
|
|
||||||
|
/* these bytes represent the input and output to/from a port instance */
|
||||||
|
|
||||||
|
uint8 i8259_IR[4]; //interrupt inputs (bits 0-7)
|
||||||
|
uint8 i8259_CAS[4]; //interrupt cascade I/O (bits 0-2)
|
||||||
|
uint8 i8259_INT[4]; //interrupt output (bit 0)
|
||||||
|
|
||||||
uint8 i8259_base[I8259_NUM];
|
uint8 i8259_base[I8259_NUM];
|
||||||
uint8 i8259_icw1[I8259_NUM];
|
uint8 i8259_icw1[I8259_NUM];
|
||||||
uint8 i8259_icw2[I8259_NUM];
|
uint8 i8259_icw2[I8259_NUM];
|
||||||
|
@ -144,8 +150,8 @@ t_stat i8259_reset (DEVICE *dptr, uint16 baseport)
|
||||||
sim_printf("i8255_reset: too many devices!\n");
|
sim_printf("i8255_reset: too many devices!\n");
|
||||||
return SCPE_MEM;
|
return SCPE_MEM;
|
||||||
}
|
}
|
||||||
sim_printf(" 8259-%d: Reset\n", i8259_devnum);
|
sim_printf(" 8259-%d: Reset\n", i8259_devnum);
|
||||||
sim_printf(" 8259-%d: Registered at %04X\n", i8259_devnum, baseport);
|
sim_printf(" 8259-%d: Registered at %04X\n", i8259_devnum, baseport);
|
||||||
i8259_port[i8259_devnum] = baseport;
|
i8259_port[i8259_devnum] = baseport;
|
||||||
reg_dev(i8259a, baseport, i8259_devnum);
|
reg_dev(i8259a, baseport, i8259_devnum);
|
||||||
reg_dev(i8259b, baseport + 1, i8259_devnum);
|
reg_dev(i8259b, baseport + 1, i8259_devnum);
|
||||||
|
|
|
@ -40,6 +40,8 @@
|
||||||
|
|
||||||
#include "system_defs.h"
|
#include "system_defs.h"
|
||||||
|
|
||||||
|
#define DEBUG 0
|
||||||
|
|
||||||
/* function prototypes */
|
/* function prototypes */
|
||||||
|
|
||||||
t_stat EPROM_attach (UNIT *uptr, CONST char *cptr);
|
t_stat EPROM_attach (UNIT *uptr, CONST char *cptr);
|
||||||
|
@ -48,13 +50,13 @@ uint8 EPROM_get_mbyte(uint16 addr);
|
||||||
|
|
||||||
/* external function prototypes */
|
/* external function prototypes */
|
||||||
|
|
||||||
extern uint8 i8255_C[4]; //port c byte I/O
|
//extern uint8 i8255_C[4]; //port c byte I/O
|
||||||
extern uint8 xack; /* XACK signal */
|
extern uint8 xack; /* XACK signal */
|
||||||
|
|
||||||
/* SIMH EPROM Standard I/O Data Structures */
|
/* SIMH EPROM Standard I/O Data Structures */
|
||||||
|
|
||||||
UNIT EPROM_unit = {
|
UNIT EPROM_unit = {
|
||||||
UDATA (NULL, UNIT_ATTABLE+UNIT_BINK+UNIT_ROABLE+UNIT_RO, 0), 0
|
UDATA (NULL, UNIT_ATTABLE+UNIT_BINK+UNIT_ROABLE+UNIT_RO+UNIT_BUFABLE+UNIT_MUSTBUF, 0), 0
|
||||||
};
|
};
|
||||||
|
|
||||||
DEBTAB EPROM_debug[] = {
|
DEBTAB EPROM_debug[] = {
|
||||||
|
@ -88,8 +90,7 @@ DEVICE EPROM_dev = {
|
||||||
NULL, //detach
|
NULL, //detach
|
||||||
NULL, //ctxt
|
NULL, //ctxt
|
||||||
DEV_DEBUG, //flags
|
DEV_DEBUG, //flags
|
||||||
DEBUG_flow + DEBUG_read + DEBUG_write, //dctrl
|
0, //dctrl
|
||||||
// 0, //dctrl
|
|
||||||
EPROM_debug, //debflags
|
EPROM_debug, //debflags
|
||||||
NULL, //msize
|
NULL, //msize
|
||||||
NULL //lname
|
NULL //lname
|
||||||
|
@ -99,54 +100,6 @@ DEVICE EPROM_dev = {
|
||||||
|
|
||||||
/* EPROM functions */
|
/* EPROM functions */
|
||||||
|
|
||||||
/* EPROM attach */
|
|
||||||
|
|
||||||
t_stat EPROM_attach (UNIT *uptr, CONST char *cptr)
|
|
||||||
{
|
|
||||||
uint16 j;
|
|
||||||
int c;
|
|
||||||
FILE *fp;
|
|
||||||
t_stat r;
|
|
||||||
|
|
||||||
sim_debug (DEBUG_flow, &EPROM_dev, "EPROM_attach: cptr=%s\n", cptr);
|
|
||||||
if ((r = attach_unit (uptr, cptr)) != SCPE_OK) {
|
|
||||||
sim_debug (DEBUG_flow, &EPROM_dev, "EPROM_attach: Error\n");
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
sim_debug (DEBUG_read, &EPROM_dev, "\tAllocate buffer\n");
|
|
||||||
if (EPROM_unit.filebuf == NULL) { /* no buffer allocated */
|
|
||||||
EPROM_unit.filebuf = malloc(EPROM_unit.capac); /* allocate EPROM buffer */
|
|
||||||
if (EPROM_unit.filebuf == NULL) {
|
|
||||||
sim_debug (DEBUG_flow, &EPROM_dev, "EPROM_attach: Malloc error\n");
|
|
||||||
return SCPE_MEM;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
sim_debug (DEBUG_read, &EPROM_dev, "\tOpen file %s\n", EPROM_unit.filename);
|
|
||||||
fp = fopen(EPROM_unit.filename, "rb"); /* open EPROM file */
|
|
||||||
if (fp == NULL) {
|
|
||||||
sim_printf("EPROM: Unable to open ROM file %s\n", EPROM_unit.filename);
|
|
||||||
sim_printf("\tNo ROM image loaded!!!\n");
|
|
||||||
return SCPE_OK;
|
|
||||||
}
|
|
||||||
sim_debug (DEBUG_read, &EPROM_dev, "\tRead file\n");
|
|
||||||
j = 0; /* load EPROM file */
|
|
||||||
c = fgetc(fp);
|
|
||||||
while (c != EOF) {
|
|
||||||
*((uint8 *)EPROM_unit.filebuf + j++) = c & 0xFF;
|
|
||||||
c = fgetc(fp);
|
|
||||||
if (j >= EPROM_unit.capac) {
|
|
||||||
sim_printf("\tImage is too large - Load truncated!!!\n");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
sim_debug (DEBUG_read, &EPROM_dev, "\tClose file\n");
|
|
||||||
fclose(fp);
|
|
||||||
sim_printf(" EPROM: Configured %d bytes, Attached to %s\n",
|
|
||||||
EPROM_unit.capac, EPROM_unit.filename);
|
|
||||||
sim_debug (DEBUG_flow, &EPROM_dev, "EPROM_attach: Done\n");
|
|
||||||
return SCPE_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* EPROM reset */
|
/* EPROM reset */
|
||||||
|
|
||||||
t_stat EPROM_reset (DEVICE *dptr, uint16 size)
|
t_stat EPROM_reset (DEVICE *dptr, uint16 size)
|
||||||
|
@ -164,6 +117,24 @@ t_stat EPROM_reset (DEVICE *dptr, uint16 size)
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* EPROM attach */
|
||||||
|
|
||||||
|
t_stat EPROM_attach (UNIT *uptr, CONST char *cptr)
|
||||||
|
{
|
||||||
|
t_stat r;
|
||||||
|
|
||||||
|
sim_debug (DEBUG_flow, &EPROM_dev, "EPROM_attach: cptr=%s\n", cptr);
|
||||||
|
if ((r = attach_unit (uptr, cptr)) != SCPE_OK) {
|
||||||
|
sim_debug (DEBUG_flow, &EPROM_dev, "EPROM_attach: Error\n");
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
sim_debug (DEBUG_read, &EPROM_dev, "\tClose file\n");
|
||||||
|
sim_printf(" EPROM: Configured %d bytes, Attached to %s\n",
|
||||||
|
EPROM_unit.capac, EPROM_unit.filename);
|
||||||
|
sim_debug (DEBUG_flow, &EPROM_dev, "EPROM_attach: Done\n");
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
/* get a byte from memory */
|
/* get a byte from memory */
|
||||||
|
|
||||||
uint8 EPROM_get_mbyte(uint16 addr)
|
uint8 EPROM_get_mbyte(uint16 addr)
|
||||||
|
|
|
@ -140,8 +140,8 @@ DEVICE ioc_cont_dev = {
|
||||||
|
|
||||||
t_stat ioc_cont_reset(DEVICE *dptr, uint16 baseport)
|
t_stat ioc_cont_reset(DEVICE *dptr, uint16 baseport)
|
||||||
{
|
{
|
||||||
sim_printf(" ioc_cont[%d]: Reset\n", 0);
|
sim_printf(" ioc_cont[%d]: Reset\n", 0);
|
||||||
sim_printf(" ioc_cont[%d]: Registered at %04X\n", 0, baseport);
|
sim_printf(" ioc_cont[%d]: Registered at %04X\n", 0, baseport);
|
||||||
reg_dev(ioc_cont0, baseport, 0);
|
reg_dev(ioc_cont0, baseport, 0);
|
||||||
reg_dev(ioc_cont1, baseport + 1, 0);
|
reg_dev(ioc_cont1, baseport + 1, 0);
|
||||||
dbb_stat = 0x00; /* clear DBB status */
|
dbb_stat = 0x00; /* clear DBB status */
|
||||||
|
|
|
@ -33,6 +33,8 @@
|
||||||
|
|
||||||
#include "system_defs.h" /* system header in system dir */
|
#include "system_defs.h" /* system header in system dir */
|
||||||
|
|
||||||
|
#define DEBUG 0
|
||||||
|
|
||||||
/* function prototypes */
|
/* function prototypes */
|
||||||
|
|
||||||
uint8 ipc_cont(t_bool io, uint8 data); /* ipc_cont*/
|
uint8 ipc_cont(t_bool io, uint8 data); /* ipc_cont*/
|
||||||
|
@ -96,8 +98,8 @@ DEVICE ipc_cont_dev = {
|
||||||
|
|
||||||
t_stat ipc_cont_reset(DEVICE *dptr, uint16 baseport)
|
t_stat ipc_cont_reset(DEVICE *dptr, uint16 baseport)
|
||||||
{
|
{
|
||||||
sim_printf(" ipc_cont[%d]: Reset\n", 0);
|
sim_printf(" ipc_cont[%d]: Reset\n", 0);
|
||||||
sim_printf(" ipc_cont[%d]: Registered at %04X\n", 0, baseport);
|
sim_printf(" ipc_cont[%d]: Registered at %04X\n", 0, baseport);
|
||||||
reg_dev(ipc_cont, baseport, 0);
|
reg_dev(ipc_cont, baseport, 0);
|
||||||
ipc_cont_unit[0].u3 = 0x00; /* ipc reset */
|
ipc_cont_unit[0].u3 = 0x00; /* ipc reset */
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
|
@ -112,8 +114,9 @@ t_stat ipc_cont_reset(DEVICE *dptr, uint16 baseport)
|
||||||
uint8 ipc_cont(t_bool io, uint8 data)
|
uint8 ipc_cont(t_bool io, uint8 data)
|
||||||
{
|
{
|
||||||
if (io == 0) { /* read status port */
|
if (io == 0) { /* read status port */
|
||||||
sim_printf(" ipc_cont: read data=%02X ipc_cont_unit[%d].u3=%02X\n",
|
if (DEBUG)
|
||||||
ipc_cont_unit[0].u3, 0, ipc_cont_unit[0].u3);
|
sim_printf(" ipc_cont: read data=%02X ipc_cont_unit[%d].u3=%02X\n",
|
||||||
|
ipc_cont_unit[0].u3, 0, ipc_cont_unit[0].u3);
|
||||||
return ipc_cont_unit[0].u3;
|
return ipc_cont_unit[0].u3;
|
||||||
} else { /* write control port */
|
} else { /* write control port */
|
||||||
//this simulates an 74LS259 register
|
//this simulates an 74LS259 register
|
||||||
|
@ -152,7 +155,8 @@ uint8 ipc_cont(t_bool io, uint8 data)
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
sim_printf(" ipc_cont: write data=%02X ipc_cont_unit[%d].u3=%02X\n", data, 0, ipc_cont_unit[0].u3);
|
if (DEBUG)
|
||||||
|
sim_printf(" ipc_cont: write data=%02X ipc_cont_unit[%d].u3=%02X\n", data, 0, ipc_cont_unit[0].u3);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,186 +0,0 @@
|
||||||
/* ipcEPROM.c: Intel EPROM simulator for 8-bit SBCs
|
|
||||||
|
|
||||||
Copyright (c) 2010, William A. Beech
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a
|
|
||||||
copy of this software and associated documentation files (the "Software"),
|
|
||||||
to deal in the Software without restriction, including without limitation
|
|
||||||
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
||||||
and/or sell copies of the Software, and to permit persons to whom the
|
|
||||||
Software is furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in
|
|
||||||
all copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
|
||||||
WILLIAM A. BEECH BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
|
||||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
|
||||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
|
|
||||||
Except as contained in this notice, the name of William A. Beech shall not be
|
|
||||||
used in advertising or otherwise to promote the sale, use or other dealings
|
|
||||||
in this Software without prior written authorization from William A. Beech.
|
|
||||||
|
|
||||||
MODIFICATIONS:
|
|
||||||
|
|
||||||
?? ??? 10 - Original file.
|
|
||||||
16 Dec 12 - Modified to use isbc_80_10.cfg file to set base and size.
|
|
||||||
24 Apr 15 -- Modified to use simh_debug
|
|
||||||
|
|
||||||
NOTES:
|
|
||||||
|
|
||||||
These functions support a simulated ROM devices on an iSBC-80/XX SBCs.
|
|
||||||
This allows the attachment of the device to a binary file containing the EPROM
|
|
||||||
code image. Unit will support a single 2708, 2716, 2732, or 2764 type EPROM.
|
|
||||||
These functions also support bit 1 of 8255 number 1, port B, to enable/
|
|
||||||
disable the onboard ROM.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "system_defs.h"
|
|
||||||
|
|
||||||
/* function prototypes */
|
|
||||||
|
|
||||||
t_stat EPROM_attach (UNIT *uptr, CONST char *cptr);
|
|
||||||
t_stat EPROM_reset (DEVICE *dptr, uint16 size);
|
|
||||||
uint8 EPROM_get_mbyte(uint16 addr);
|
|
||||||
|
|
||||||
/* external function prototypes */
|
|
||||||
|
|
||||||
extern uint8 xack; /* XACK signal */
|
|
||||||
extern UNIT ipc_cont_unit[];
|
|
||||||
|
|
||||||
/* SIMH EPROM Standard I/O Data Structures */
|
|
||||||
|
|
||||||
UNIT EPROM_unit = {
|
|
||||||
UDATA (NULL, UNIT_ATTABLE+UNIT_BINK+UNIT_ROABLE+UNIT_RO, 0), 0
|
|
||||||
};
|
|
||||||
|
|
||||||
DEBTAB EPROM_debug[] = {
|
|
||||||
{ "ALL", DEBUG_all },
|
|
||||||
{ "FLOW", DEBUG_flow },
|
|
||||||
{ "READ", DEBUG_read },
|
|
||||||
{ "WRITE", DEBUG_write },
|
|
||||||
{ "XACK", DEBUG_xack },
|
|
||||||
{ "LEV1", DEBUG_level1 },
|
|
||||||
{ "LEV2", DEBUG_level2 },
|
|
||||||
{ NULL }
|
|
||||||
};
|
|
||||||
|
|
||||||
DEVICE EPROM_dev = {
|
|
||||||
"EPROM", //name
|
|
||||||
&EPROM_unit, //units
|
|
||||||
NULL, //registers
|
|
||||||
NULL, //modifiers
|
|
||||||
1, //numunits
|
|
||||||
16, //aradix
|
|
||||||
16, //awidth
|
|
||||||
1, //aincr
|
|
||||||
16, //dradix
|
|
||||||
8, //dwidth
|
|
||||||
NULL, //examine
|
|
||||||
NULL, //deposit
|
|
||||||
// &EPROM_reset, //reset
|
|
||||||
NULL, //reset
|
|
||||||
NULL, //boot
|
|
||||||
&EPROM_attach, //attach
|
|
||||||
NULL, //detach
|
|
||||||
NULL, //ctxt
|
|
||||||
DEV_DEBUG, //flags
|
|
||||||
0, //dctrl
|
|
||||||
EPROM_debug, //debflags
|
|
||||||
NULL, //msize
|
|
||||||
NULL //lname
|
|
||||||
};
|
|
||||||
|
|
||||||
/* global variables */
|
|
||||||
|
|
||||||
/* EPROM functions */
|
|
||||||
|
|
||||||
/* EPROM attach */
|
|
||||||
|
|
||||||
t_stat EPROM_attach (UNIT *uptr, CONST char *cptr)
|
|
||||||
{
|
|
||||||
uint16 j;
|
|
||||||
int c;
|
|
||||||
FILE *fp;
|
|
||||||
t_stat r;
|
|
||||||
|
|
||||||
sim_debug (DEBUG_flow, &EPROM_dev, "EPROM_attach: cptr=%s\n", cptr);
|
|
||||||
if ((r = attach_unit (uptr, cptr)) != SCPE_OK) {
|
|
||||||
sim_debug (DEBUG_flow, &EPROM_dev, "EPROM_attach: Error\n");
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
sim_debug (DEBUG_read, &EPROM_dev, "\tAllocate buffer\n");
|
|
||||||
if (EPROM_unit.filebuf == NULL) { /* no buffer allocated */
|
|
||||||
EPROM_unit.filebuf = malloc(EPROM_unit.capac); /* allocate EPROM buffer */
|
|
||||||
if (EPROM_unit.filebuf == NULL) {
|
|
||||||
sim_debug (DEBUG_flow, &EPROM_dev, "EPROM_attach: Malloc error\n");
|
|
||||||
return SCPE_MEM;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
sim_debug (DEBUG_read, &EPROM_dev, "\tOpen file %s\n", EPROM_unit.filename);
|
|
||||||
fp = fopen(EPROM_unit.filename, "rb"); /* open EPROM file */
|
|
||||||
if (fp == NULL) {
|
|
||||||
sim_printf("EPROM: Unable to open ROM file %s\n", EPROM_unit.filename);
|
|
||||||
sim_printf("\tNo ROM image loaded!!!\n");
|
|
||||||
return SCPE_OK;
|
|
||||||
}
|
|
||||||
sim_debug (DEBUG_read, &EPROM_dev, "\tRead file\n");
|
|
||||||
j = 0; /* load EPROM file */
|
|
||||||
c = fgetc(fp);
|
|
||||||
while (c != EOF) {
|
|
||||||
*((uint8 *)EPROM_unit.filebuf + j++) = c & 0xFF;
|
|
||||||
c = fgetc(fp);
|
|
||||||
if (j > EPROM_unit.capac) {
|
|
||||||
sim_printf("\tImage is too large - Load truncated!!!\n");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
sim_printf("\tImage size=%04X unit_capac=%04X\n", j, EPROM_unit.capac);
|
|
||||||
sim_debug (DEBUG_read, &EPROM_dev, "\tClose file\n");
|
|
||||||
fclose(fp);
|
|
||||||
sim_printf("EPROM: %d bytes of ROM image %s loaded\n", j, EPROM_unit.filename);
|
|
||||||
sim_debug (DEBUG_flow, &EPROM_dev, "EPROM_attach: Done\n");
|
|
||||||
return SCPE_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* EPROM reset */
|
|
||||||
|
|
||||||
t_stat EPROM_reset (DEVICE *dptr, uint16 size)
|
|
||||||
{
|
|
||||||
// sim_debug (DEBUG_flow, &EPROM_dev, " EPROM_reset: base=0000 size=%04X\n", size);
|
|
||||||
if ((EPROM_unit.flags & UNIT_ATT) == 0) { /* if unattached */
|
|
||||||
EPROM_unit.capac = size; /* set EPROM size to 0 */
|
|
||||||
sim_debug (DEBUG_flow, &EPROM_dev, "Done1\n");
|
|
||||||
// sim_printf(" EPROM: Available [%04X-%04XH]\n",
|
|
||||||
// 0, EPROM_unit.capac - 1);
|
|
||||||
return SCPE_OK;
|
|
||||||
}
|
|
||||||
if ((EPROM_unit.flags & UNIT_ATT) == 0) {
|
|
||||||
sim_printf("EPROM: No file attached\n");
|
|
||||||
}
|
|
||||||
sim_debug (DEBUG_flow, &EPROM_dev, "Done2\n");
|
|
||||||
return SCPE_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* get a byte from memory */
|
|
||||||
|
|
||||||
uint8 EPROM_get_mbyte(uint16 addr)
|
|
||||||
{
|
|
||||||
uint8 val;
|
|
||||||
|
|
||||||
sim_debug (DEBUG_read, &EPROM_dev, "EPROM_get_mbyte: addr=%04X\n", addr);
|
|
||||||
if (addr < EPROM_unit.capac) {
|
|
||||||
SET_XACK(1); /* good memory address */
|
|
||||||
sim_debug (DEBUG_xack, &EPROM_dev, "EPROM_get_mbyte: Set XACK for %04X\n", addr);
|
|
||||||
val = *((uint8 *)EPROM_unit.filebuf + addr);
|
|
||||||
sim_debug (DEBUG_read, &EPROM_dev, " val=%04X\n", val);
|
|
||||||
return (val & 0xFF);
|
|
||||||
}
|
|
||||||
sim_debug (DEBUG_read, &EPROM_dev, " Out of range\n");
|
|
||||||
return 0xFF;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* end of ipcEPROM.c */
|
|
|
@ -60,7 +60,6 @@ void multibus_put_mword(uint16 addr, uint16 val);
|
||||||
|
|
||||||
extern t_stat SBC_reset(DEVICE *dptr); /* reset the IPC simulator */
|
extern t_stat SBC_reset(DEVICE *dptr); /* reset the IPC simulator */
|
||||||
extern void set_cpuint(int32 int_num);
|
extern void set_cpuint(int32 int_num);
|
||||||
extern UNIT zx200a_unit;
|
|
||||||
extern t_stat zx200a_reset(DEVICE *dptr, uint16 base);
|
extern t_stat zx200a_reset(DEVICE *dptr, uint16 base);
|
||||||
extern t_stat isbc201_reset (DEVICE *dptr, uint16);
|
extern t_stat isbc201_reset (DEVICE *dptr, uint16);
|
||||||
extern t_stat isbc202_reset (DEVICE *dptr, uint16);
|
extern t_stat isbc202_reset (DEVICE *dptr, uint16);
|
||||||
|
@ -150,8 +149,7 @@ t_stat multibus_reset(DEVICE *dptr)
|
||||||
SBC_reset(NULL);
|
SBC_reset(NULL);
|
||||||
sim_printf(" Multibus: Reset\n");
|
sim_printf(" Multibus: Reset\n");
|
||||||
zx200a_fdcnum = 0;
|
zx200a_fdcnum = 0;
|
||||||
zx200a_reset(NULL, ZX200A_BASE_DD);
|
zx200a_reset(NULL, ZX200A_BASE);
|
||||||
// zx200a_reset(NULL, ZX200A_BASE_SD);
|
|
||||||
isbc201_fdcnum = 0;
|
isbc201_fdcnum = 0;
|
||||||
isbc201_reset(NULL, SBC201_BASE);
|
isbc201_reset(NULL, SBC201_BASE);
|
||||||
isbc202_fdcnum = 0;
|
isbc202_fdcnum = 0;
|
||||||
|
@ -258,9 +256,9 @@ uint8 nulldev(t_bool flag, uint8 data)
|
||||||
uint16 reg_dev(uint8 (*routine)(t_bool io, uint8 data), uint16 port, uint8 devnum)
|
uint16 reg_dev(uint8 (*routine)(t_bool io, uint8 data), uint16 port, uint8 devnum)
|
||||||
{
|
{
|
||||||
if (dev_table[port].routine != &nulldev) { /* port already assigned */
|
if (dev_table[port].routine != &nulldev) { /* port already assigned */
|
||||||
sim_printf("Multibus: I/O Port %04X is already assigned\n", port);
|
sim_printf(" Multibus: I/O Port %04X is already assigned\n", port);
|
||||||
} else {
|
} else {
|
||||||
sim_printf("Port %04X is assigned\n", port);
|
sim_printf(" Port %04X is assigned\n", port);
|
||||||
dev_table[port].routine = routine;
|
dev_table[port].routine = routine;
|
||||||
dev_table[port].devnum = devnum;
|
dev_table[port].devnum = devnum;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,145 +0,0 @@
|
||||||
/* ipcRAM8.c: Intel RAM simulator for 8-bit SBCs
|
|
||||||
|
|
||||||
Copyright (c) 2011, William A. Beech
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a
|
|
||||||
copy of this software and associated documentation files (the "Software"),
|
|
||||||
to deal in the Software without restriction, including without limitation
|
|
||||||
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
||||||
and/or sell copies of the Software, and to permit persons to whom the
|
|
||||||
Software is furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in
|
|
||||||
all copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
|
||||||
WILLIAM A. BEECH BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
|
||||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
|
||||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
|
|
||||||
Except as contained in this notice, the name of William A. Beech shall not be
|
|
||||||
used in advertising or otherwise to promote the sale, use or other dealings
|
|
||||||
in this Software without prior written authorization from William A. Beech.
|
|
||||||
|
|
||||||
MODIFICATIONS:
|
|
||||||
|
|
||||||
?? ??? 11 - Original file.
|
|
||||||
16 Dec 12 - Modified to use isbc_80_10.cfg file to set base and size.
|
|
||||||
24 Apr 15 -- Modified to use simh_debug
|
|
||||||
|
|
||||||
NOTES:
|
|
||||||
|
|
||||||
These functions support a simulated RAM devices on an iSBC-80/XX SBCs.
|
|
||||||
These functions also support bit 2 of 8255 number 1, port B, to enable/
|
|
||||||
disable the onboard RAM.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "system_defs.h"
|
|
||||||
|
|
||||||
/* function prototypes */
|
|
||||||
|
|
||||||
t_stat RAM_svc (UNIT *uptr);
|
|
||||||
t_stat RAM_reset (DEVICE *dptr, uint16 base, uint16 size);
|
|
||||||
uint8 RAM_get_mbyte(uint16 addr);
|
|
||||||
void RAM_put_mbyte(uint16 addr, uint8 val);
|
|
||||||
|
|
||||||
/* external function prototypes */
|
|
||||||
|
|
||||||
extern uint8 xack; /* XACK signal */
|
|
||||||
|
|
||||||
/* SIMH RAM Standard I/O Data Structures */
|
|
||||||
|
|
||||||
UNIT RAM_unit = { UDATA (NULL, UNIT_BINK, 0), KBD_POLL_WAIT };
|
|
||||||
|
|
||||||
DEBTAB RAM_debug[] = {
|
|
||||||
{ "ALL", DEBUG_all },
|
|
||||||
{ "FLOW", DEBUG_flow },
|
|
||||||
{ "READ", DEBUG_read },
|
|
||||||
{ "WRITE", DEBUG_write },
|
|
||||||
{ "XACK", DEBUG_xack },
|
|
||||||
{ "LEV1", DEBUG_level1 },
|
|
||||||
{ "LEV2", DEBUG_level2 },
|
|
||||||
{ NULL }
|
|
||||||
};
|
|
||||||
|
|
||||||
DEVICE RAM_dev = {
|
|
||||||
"RAM", //name
|
|
||||||
&RAM_unit, //units
|
|
||||||
NULL, //registers
|
|
||||||
NULL, //modifiers
|
|
||||||
1, //numunits
|
|
||||||
16, //aradix
|
|
||||||
16, //awidth
|
|
||||||
1, //aincr
|
|
||||||
16, //dradix
|
|
||||||
8, //dwidth
|
|
||||||
NULL, //examine
|
|
||||||
NULL, //deposit
|
|
||||||
// &RAM_reset, //reset
|
|
||||||
NULL, //reset
|
|
||||||
NULL, //boot
|
|
||||||
NULL, //attach
|
|
||||||
NULL, //detach
|
|
||||||
NULL, //ctxt
|
|
||||||
DEV_DEBUG, //flags
|
|
||||||
0, //dctrl
|
|
||||||
RAM_debug, //debflags
|
|
||||||
NULL, //msize
|
|
||||||
NULL //lname
|
|
||||||
};
|
|
||||||
|
|
||||||
/* global variables */
|
|
||||||
|
|
||||||
/* RAM functions */
|
|
||||||
|
|
||||||
/* RAM reset */
|
|
||||||
|
|
||||||
t_stat RAM_reset (DEVICE *dptr, uint16 base, uint16 size)
|
|
||||||
{
|
|
||||||
sim_debug (DEBUG_flow, &RAM_dev, " RAM_reset: base=%04X size=%04X\n", base, size-1);
|
|
||||||
if (RAM_unit.capac == 0) { /* if undefined */
|
|
||||||
RAM_unit.capac = size;
|
|
||||||
RAM_unit.u3 = base;
|
|
||||||
}
|
|
||||||
if (RAM_unit.filebuf == NULL) { /* no buffer allocated */
|
|
||||||
RAM_unit.filebuf = malloc(RAM_unit.capac);
|
|
||||||
if (RAM_unit.filebuf == NULL) {
|
|
||||||
sim_debug (DEBUG_flow, &RAM_dev, "RAM_set_size: Malloc error\n");
|
|
||||||
return SCPE_MEM;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// sim_printf(" RAM: Available [%04X-%04XH]\n",
|
|
||||||
// RAM_unit.u3,
|
|
||||||
// RAM_unit.u3 + RAM_unit.capac - 1);
|
|
||||||
sim_debug (DEBUG_flow, &RAM_dev, "RAM_reset: Done\n");
|
|
||||||
return SCPE_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* get a byte from memory */
|
|
||||||
|
|
||||||
uint8 RAM_get_mbyte(uint16 addr)
|
|
||||||
{
|
|
||||||
uint8 val;
|
|
||||||
|
|
||||||
sim_debug (DEBUG_read, &RAM_dev, "RAM_get_mbyte: addr=%04X\n", addr);
|
|
||||||
SET_XACK(1); /* good memory address */
|
|
||||||
sim_debug (DEBUG_xack, &RAM_dev, "RAM_get_mbyte: Set XACK for %04X\n", addr);
|
|
||||||
val = *((uint8 *)RAM_unit.filebuf + (addr - RAM_unit.u3));
|
|
||||||
sim_debug (DEBUG_read, &RAM_dev, " val=%04X\n", val);
|
|
||||||
return (val & 0xFF);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* put a byte to memory */
|
|
||||||
|
|
||||||
void RAM_put_mbyte(uint16 addr, uint8 val)
|
|
||||||
{
|
|
||||||
sim_debug (DEBUG_write, &RAM_dev, "RAM_put_mbyte: addr=%04X, val=%02X\n", addr, val);
|
|
||||||
SET_XACK(1); /* good memory address */
|
|
||||||
sim_debug (DEBUG_xack, &RAM_dev, "RAM_put_mbyte: Set XACK for %04X\n", addr);
|
|
||||||
*((uint8 *)RAM_unit.filebuf + (addr - RAM_unit.u3)) = val & 0xFF;
|
|
||||||
sim_debug (DEBUG_write, &RAM_dev, "\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
/* end of ipcRAM8.c */
|
|
|
@ -38,6 +38,8 @@
|
||||||
|
|
||||||
#include "system_defs.h"
|
#include "system_defs.h"
|
||||||
|
|
||||||
|
#define DEBUG 0
|
||||||
|
|
||||||
/* function prototypes */
|
/* function prototypes */
|
||||||
|
|
||||||
t_stat RAM_reset (DEVICE *dptr, uint16 base, uint16 size);
|
t_stat RAM_reset (DEVICE *dptr, uint16 base, uint16 size);
|
||||||
|
@ -108,9 +110,10 @@ t_stat RAM_reset (DEVICE *dptr, uint16 base, uint16 size)
|
||||||
return SCPE_MEM;
|
return SCPE_MEM;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sim_printf(" RAM: Available [%04X-%04XH]\n",
|
if (DEBUG)
|
||||||
RAM_unit.u3,
|
sim_printf(" RAM: Available [%04X-%04XH]\n",
|
||||||
RAM_unit.u3 + RAM_unit.capac - 1);
|
RAM_unit.u3,
|
||||||
|
RAM_unit.u3 + RAM_unit.capac - 1);
|
||||||
sim_debug (DEBUG_flow, &RAM_dev, "RAM_reset: Done\n");
|
sim_debug (DEBUG_flow, &RAM_dev, "RAM_reset: Done\n");
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
|
|
@ -136,7 +136,7 @@
|
||||||
|
|
||||||
u3 -
|
u3 -
|
||||||
u4 -
|
u4 -
|
||||||
u5 - fdc number.
|
u5 - fdc number (board instance number).
|
||||||
u6 - fdd number.
|
u6 - fdd number.
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
@ -183,12 +183,16 @@
|
||||||
#define RB1RD0 0x40 //drive 0 ready
|
#define RB1RD0 0x40 //drive 0 ready
|
||||||
#define RB1RD1 0x80 //drive 1 ready
|
#define RB1RD1 0x80 //drive 1 ready
|
||||||
|
|
||||||
|
//disk geometry values
|
||||||
#define MDSSD 256256 //single density FDD size
|
#define MDSSD 256256 //single density FDD size
|
||||||
#define MDSDD 512512 //double density FDD size
|
#define MDSDD 512512 //double density FDD size
|
||||||
|
#define MAXSECSD 26 //single density last sector
|
||||||
|
#define MAXSECDD 52 //double density last sector
|
||||||
|
#define MAXTRK 76 //last track
|
||||||
|
|
||||||
/* external globals */
|
/* external globals */
|
||||||
|
|
||||||
extern uint16 port; //port called in dev_table[port]
|
extern uint16 port; //port called in dev_table[port]
|
||||||
extern int32 PCX;
|
extern int32 PCX;
|
||||||
|
|
||||||
/* external function prototypes */
|
/* external function prototypes */
|
||||||
|
@ -218,11 +222,10 @@ void isbc201_diskio(uint8 fdcnum); //do actual disk i/o
|
||||||
int32 isbc201_fdcnum = 0; //actual number of SBC-201 instances + 1
|
int32 isbc201_fdcnum = 0; //actual number of SBC-201 instances + 1
|
||||||
|
|
||||||
typedef struct { //FDD definition
|
typedef struct { //FDD definition
|
||||||
uint8 *buf;
|
|
||||||
int t0;
|
int t0;
|
||||||
int rdy;
|
int rdy;
|
||||||
uint8 maxsec;
|
uint8 sec;
|
||||||
uint8 maxcyl;
|
uint8 cyl;
|
||||||
} FDDDEF;
|
} FDDDEF;
|
||||||
|
|
||||||
typedef struct { //FDC definition
|
typedef struct { //FDC definition
|
||||||
|
@ -240,25 +243,33 @@ typedef struct { //FDC definition
|
||||||
FDCDEF fdc201[4]; //indexed by the isbc-201 instance number
|
FDCDEF fdc201[4]; //indexed by the isbc-201 instance number
|
||||||
|
|
||||||
UNIT isbc201_unit[] = {
|
UNIT isbc201_unit[] = {
|
||||||
{ UDATA (0, UNIT_ATTABLE+UNIT_DISABLE, 0), 20 },
|
{ UDATA (0, UNIT_ATTABLE+UNIT_DISABLE+UNIT_BUFABLE+UNIT_MUSTBUF, MDSSD), 20 },
|
||||||
{ UDATA (0, UNIT_ATTABLE+UNIT_DISABLE, 0), 20 },
|
{ UDATA (0, UNIT_ATTABLE+UNIT_DISABLE+UNIT_BUFABLE+UNIT_MUSTBUF, MDSSD), 20 },
|
||||||
{ UDATA (0, UNIT_ATTABLE+UNIT_DISABLE, 0), 20 },
|
{ UDATA (0, UNIT_ATTABLE+UNIT_DISABLE+UNIT_BUFABLE+UNIT_MUSTBUF, MDSSD), 20 },
|
||||||
{ UDATA (0, UNIT_ATTABLE+UNIT_DISABLE, 0), 20 }
|
{ UDATA (0, UNIT_ATTABLE+UNIT_DISABLE+UNIT_BUFABLE+UNIT_MUSTBUF, MDSSD), 20 }
|
||||||
};
|
};
|
||||||
|
|
||||||
REG isbc201_reg[] = {
|
REG isbc201_reg[] = {
|
||||||
{ HRDATA (STATUS0, isbc201_unit[0].u3, 8) }, /* isbc201 0 status */
|
{ HRDATA (STAT0, fdc201[0].stat, 8) }, /* fdc201 0 status */
|
||||||
{ HRDATA (RTYP0, isbc201_unit[0].u4, 8) }, /* isbc201 0 result type */
|
{ HRDATA (RTYP0, fdc201[0].rtype, 8) }, /* fdc201 0 result type */
|
||||||
{ HRDATA (RBYT0, isbc201_unit[0].u5, 8) }, /* isbc201 0 result byte */
|
{ HRDATA (RBYT0A, fdc201[0].rbyte0, 8) }, /* fdc201 0 result byte 0 */
|
||||||
{ HRDATA (STATUS1, isbc201_unit[1].u3, 8) }, /* isbc201 1 status */
|
{ HRDATA (RBYT0B, fdc201[0].rbyte1, 8) }, /* fdc201 0 result byte 1 */
|
||||||
{ HRDATA (RTYP1, isbc201_unit[1].u4, 8) }, /* isbc201 0 result type */
|
{ HRDATA (INTFF0, fdc201[0].intff, 8) }, /* fdc201 0 interrupt f/f */
|
||||||
{ HRDATA (RBYT1, isbc201_unit[1].u5, 8) }, /* isbc201 0 result byte */
|
{ HRDATA (STAT1, fdc201[1].stat, 8) }, /* fdc201 1 status */
|
||||||
{ HRDATA (STATUS2, isbc201_unit[2].u3, 8) }, /* isbc201 2 status */
|
{ HRDATA (RTYP1, fdc201[1].rtype, 8) }, /* fdc201 1 result type */
|
||||||
{ HRDATA (RTYP2, isbc201_unit[0].u4, 8) }, /* isbc201 0 result type */
|
{ HRDATA (RBYT1A, fdc201[1].rbyte0, 8) }, /* fdc201 1 result byte 0 */
|
||||||
{ HRDATA (R$BYT2, isbc201_unit[2].u5, 8) }, /* isbc201 0 result byte */
|
{ HRDATA (RBYT1B, fdc201[1].rbyte1, 8) }, /* fdc201 1 result byte 1 */
|
||||||
{ HRDATA (STATUS3, isbc201_unit[3].u3, 8) }, /* isbc201 3 status */
|
{ HRDATA (INTFF1, fdc201[1].intff, 8) }, /* fdc201 1 interrupt f/f */
|
||||||
{ HRDATA (RTYP3, isbc201_unit[3].u4, 8) }, /* isbc201 0 result type */
|
{ HRDATA (STAT2, fdc201[2].stat, 8) }, /* fdc201 2 status */
|
||||||
{ HRDATA (RBYT3, isbc201_unit[3].u5, 8) }, /* isbc201 0 result byte */
|
{ HRDATA (RTYP2, fdc201[2].rtype, 8) }, /* fdc201 2 result type */
|
||||||
|
{ HRDATA (RBYT2A, fdc201[2].rbyte0, 8) }, /* fdc201 2 result byte 0 */
|
||||||
|
{ HRDATA (RBYT2B, fdc201[2].rbyte1, 8) }, /* fdc201 2 result byte 1 */
|
||||||
|
{ HRDATA (INTFF2, fdc201[2].intff, 8) }, /* fdc201 2 interrupt f/f */
|
||||||
|
{ HRDATA (STAT3, fdc201[3].stat, 8) }, /* fdc201 3 status */
|
||||||
|
{ HRDATA (RTYP3, fdc201[3].rtype, 8) }, /* fdc201 3 result type */
|
||||||
|
{ HRDATA (RBYT3A, fdc201[3].rbyte0, 8) }, /* fdc201 3 result byte 0 */
|
||||||
|
{ HRDATA (RBYT3B, fdc201[3].rbyte1, 8) }, /* fdc201 3 result byte 1 */
|
||||||
|
{ HRDATA (INTFF3, fdc201[3].intff, 8) }, /* fdc201 3 interrupt f/f */
|
||||||
{ NULL }
|
{ NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -310,17 +321,29 @@ DEVICE isbc201_dev = {
|
||||||
|
|
||||||
t_stat isbc201_reset(DEVICE *dptr, uint16 base)
|
t_stat isbc201_reset(DEVICE *dptr, uint16 base)
|
||||||
{
|
{
|
||||||
|
int32 i;
|
||||||
|
UNIT *uptr;
|
||||||
|
|
||||||
sim_printf(" iSBC-201 FDC Board");
|
sim_printf(" iSBC-201 FDC Board");
|
||||||
if (SBC201_NUM) {
|
if (SBC201_NUM) {
|
||||||
sim_printf(" - Found\n");
|
sim_printf(" - Found\n");
|
||||||
sim_printf(" isbc201-%d: Hardware Reset\n", isbc201_fdcnum);
|
sim_printf(" isbc201-%d: Hardware Reset\n", isbc201_fdcnum);
|
||||||
sim_printf(" isbc201-%d: Registered at %04X\n", isbc201_fdcnum, base);
|
sim_printf(" isbc201-%d: Registered at %04X\n", isbc201_fdcnum, base);
|
||||||
|
//register base port address for this FDC instance
|
||||||
fdc201[isbc201_fdcnum].baseport = base;
|
fdc201[isbc201_fdcnum].baseport = base;
|
||||||
|
//register I/O port addresses for each function
|
||||||
reg_dev(isbc2010, base, isbc201_fdcnum); //read status
|
reg_dev(isbc2010, base, isbc201_fdcnum); //read status
|
||||||
reg_dev(isbc2011, base + 1, isbc201_fdcnum); //read rslt type/write IOPB addr-l
|
reg_dev(isbc2011, base + 1, isbc201_fdcnum); //read rslt type/write IOPB addr-l
|
||||||
reg_dev(isbc2012, base + 2, isbc201_fdcnum); //write IOPB addr-h and start
|
reg_dev(isbc2012, base + 2, isbc201_fdcnum); //write IOPB addr-h and start
|
||||||
reg_dev(isbc2013, base + 3, isbc201_fdcnum); //read rstl byte
|
reg_dev(isbc2013, base + 3, isbc201_fdcnum); //read rstl byte
|
||||||
reg_dev(isbc2017, base + 7, isbc201_fdcnum); //write reset isbc202
|
reg_dev(isbc2017, base + 7, isbc201_fdcnum); //write reset fdc201
|
||||||
|
// one-time initialization for all FDDs for this FDC instance
|
||||||
|
for (i = 0; i < FDD_NUM; i++) {
|
||||||
|
uptr = isbc201_dev.units + i;
|
||||||
|
uptr->u5 = isbc201_fdcnum; //fdc device number
|
||||||
|
uptr->u6 = i; //fdd unit number
|
||||||
|
uptr->flags |= UNIT_WPMODE; //set WP in unit flags
|
||||||
|
}
|
||||||
isbc201_reset1(isbc201_fdcnum);
|
isbc201_reset1(isbc201_fdcnum);
|
||||||
isbc201_fdcnum++;
|
isbc201_fdcnum++;
|
||||||
} else
|
} else
|
||||||
|
@ -342,38 +365,30 @@ void isbc201_reset1(uint8 fdcnum)
|
||||||
fdc201[fdcnum].stat |= FDCPRE; //set the FDC status
|
fdc201[fdcnum].stat |= FDCPRE; //set the FDC status
|
||||||
fdc201[fdcnum].rtype = ROK;
|
fdc201[fdcnum].rtype = ROK;
|
||||||
if (uptr->capac == 0) { /* if not configured */
|
if (uptr->capac == 0) { /* if not configured */
|
||||||
uptr->capac = 0; /* initialize unit */
|
|
||||||
uptr->u5 = fdcnum; //fdc device number
|
|
||||||
uptr->u6 = i; //fdd unit number
|
|
||||||
uptr->flags |= UNIT_WPMODE; /* set WP in unit flags */
|
|
||||||
sim_printf(" isbc201-%d: Configured, Status=%02X Not attached\n", i, fdc201[fdcnum].stat);
|
sim_printf(" isbc201-%d: Configured, Status=%02X Not attached\n", i, fdc201[fdcnum].stat);
|
||||||
} else {
|
} else {
|
||||||
switch(i){
|
switch(i){
|
||||||
case 0:
|
case 0:
|
||||||
fdc201[fdcnum].stat |= RDY0; //set FDD 0 ready
|
fdc201[fdcnum].stat |= RDY0; //set FDD 0 ready
|
||||||
fdc201[fdcnum].rbyte1 |= RB1RD0;
|
fdc201[fdcnum].rbyte1 |= RB1RD0;
|
||||||
fdc201[fdcnum].rdychg = 0;
|
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
fdc201[fdcnum].stat |= RDY1; //set FDD 1 ready
|
fdc201[fdcnum].stat |= RDY1; //set FDD 1 ready
|
||||||
fdc201[fdcnum].rbyte1 |= RB1RD1;
|
fdc201[fdcnum].rbyte1 |= RB1RD1;
|
||||||
fdc201[fdcnum].rdychg = 0;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
fdc201[fdcnum].rdychg = 0;
|
||||||
sim_printf(" isbc201-%d: Configured, Status=%02X Attached to %s\n",
|
sim_printf(" isbc201-%d: Configured, Status=%02X Attached to %s\n",
|
||||||
i, fdc201[fdcnum].stat, uptr->filename);
|
i, fdc201[fdcnum].stat, uptr->filename);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* isbc202 attach - attach an .IMG file to a FDD */
|
/* fdc201 attach - attach an .IMG file to a FDD */
|
||||||
|
|
||||||
t_stat isbc201_attach (UNIT *uptr, CONST char *cptr)
|
t_stat isbc201_attach (UNIT *uptr, CONST char *cptr)
|
||||||
{
|
{
|
||||||
t_stat r;
|
t_stat r;
|
||||||
FILE *fp;
|
|
||||||
int32 i, c = 0;
|
|
||||||
long flen;
|
|
||||||
uint8 fdcnum, fddnum;
|
uint8 fdcnum, fddnum;
|
||||||
|
|
||||||
sim_debug (DEBUG_flow, &isbc201_dev, " isbc201_attach: Entered with cptr=%s\n", cptr);
|
sim_debug (DEBUG_flow, &isbc201_dev, " isbc201_attach: Entered with cptr=%s\n", cptr);
|
||||||
|
@ -383,60 +398,24 @@ t_stat isbc201_attach (UNIT *uptr, CONST char *cptr)
|
||||||
}
|
}
|
||||||
fdcnum = uptr->u5;
|
fdcnum = uptr->u5;
|
||||||
fddnum = uptr->u6;
|
fddnum = uptr->u6;
|
||||||
fp = fopen(uptr->filename, "rb");
|
switch(fddnum){
|
||||||
if (fp == NULL) {
|
case 0:
|
||||||
sim_printf(" Unable to open disk image file %s\n", uptr->filename);
|
fdc201[fdcnum].stat |= RDY0; //set FDD 0 ready
|
||||||
sim_printf(" No disk image loaded!!!\n");
|
fdc201[fdcnum].rbyte1 |= RB1RD0;
|
||||||
} else {
|
break;
|
||||||
sim_printf("isbc202: Attach\n");
|
case 1:
|
||||||
fseek(fp, 0, SEEK_END); /* size disk image */
|
fdc201[fdcnum].stat |= RDY1; //set FDD 1 ready
|
||||||
flen = ftell(fp);
|
fdc201[fdcnum].rbyte1 |= RB1RD1;
|
||||||
fseek(fp, 0, SEEK_SET);
|
break;
|
||||||
if (flen == -1) {
|
|
||||||
sim_printf(" isbc201_attach: File error\n");
|
|
||||||
fclose(fp);
|
|
||||||
return SCPE_IOERR;
|
|
||||||
}
|
|
||||||
if (fdc201[fdcnum].fdd[fddnum].buf == NULL) { /* no buffer allocated */
|
|
||||||
fdc201[fdcnum].fdd[fddnum].buf = (uint8 *)malloc(flen);
|
|
||||||
if (fdc201[fdcnum].fdd[fddnum].buf == NULL) {
|
|
||||||
sim_printf(" isbc201_attach: Malloc error\n");
|
|
||||||
fclose(fp);
|
|
||||||
return SCPE_MEM;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
uptr->capac = flen;
|
|
||||||
i = 0;
|
|
||||||
c = fgetc(fp); // copy disk image into buffer
|
|
||||||
while (c != EOF) {
|
|
||||||
*(fdc201[fdcnum].fdd[fddnum].buf + i++) = c & 0xFF;
|
|
||||||
c = fgetc(fp);
|
|
||||||
}
|
|
||||||
fclose(fp);
|
|
||||||
switch(fddnum){
|
|
||||||
case 0:
|
|
||||||
fdc201[fdcnum].stat |= RDY0; //set FDD 0 ready
|
|
||||||
fdc201[fdcnum].rtype = ROK;
|
|
||||||
fdc201[fdcnum].rbyte1 |= RB1RD0;
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
fdc201[fdcnum].stat |= RDY1; //set FDD 1 ready
|
|
||||||
fdc201[fdcnum].rtype = ROK;
|
|
||||||
fdc201[fdcnum].rbyte1 |= RB1RD1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (flen == 256256) { /* 8" 256K SSSD */
|
|
||||||
fdc201[fdcnum].fdd[fddnum].maxcyl = 77;
|
|
||||||
fdc201[fdcnum].fdd[fddnum].maxsec = 26;
|
|
||||||
}
|
|
||||||
sim_printf(" iSBC-201%d: Configured %d bytes, Attached to %s\n",
|
|
||||||
fdcnum, uptr->capac, uptr->filename);
|
|
||||||
}
|
}
|
||||||
|
fdc201[fdcnum].rtype = ROK;
|
||||||
|
sim_printf(" iSBC-201%d: FDD %d Configured %d bytes, Attached to %s\n",
|
||||||
|
fdcnum, fddnum, uptr->capac, uptr->filename);
|
||||||
sim_debug (DEBUG_flow, &isbc201_dev, " isbc201_attach: Done\n");
|
sim_debug (DEBUG_flow, &isbc201_dev, " isbc201_attach: Done\n");
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* isbc202 set mode = Write protect */
|
/* fdc201 set mode = Write protect */
|
||||||
|
|
||||||
t_stat isbc201_set_mode (UNIT *uptr, int32 val, CONST char *cptr, void *desc)
|
t_stat isbc201_set_mode (UNIT *uptr, int32 val, CONST char *cptr, void *desc)
|
||||||
{
|
{
|
||||||
|
@ -458,7 +437,7 @@ uint8 isbc201_get_dn(void)
|
||||||
for (i=0; i<SBC201_NUM; i++)
|
for (i=0; i<SBC201_NUM; i++)
|
||||||
if (port >= fdc201[i].baseport && port <= fdc201[i].baseport + 7)
|
if (port >= fdc201[i].baseport && port <= fdc201[i].baseport + 7)
|
||||||
return i;
|
return i;
|
||||||
sim_printf("isbc201_get_dn: port %04X not in isbc202 device table\n", port);
|
sim_printf("isbc201_get_dn: port %04X not in fdc201 device table\n", port);
|
||||||
return 0xFF;
|
return 0xFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -574,13 +553,13 @@ uint8 isbc2017(t_bool io, uint8 data)
|
||||||
|
|
||||||
void isbc201_diskio(uint8 fdcnum)
|
void isbc201_diskio(uint8 fdcnum)
|
||||||
{
|
{
|
||||||
uint8 cw, di, nr, ta, sa, bn, data, nrptr, c;
|
uint8 cw, di, nr, ta, sa, bn, data, nrptr;
|
||||||
uint16 ba, ni;
|
uint16 ba, ni;
|
||||||
uint32 dskoff;
|
uint32 dskoff;
|
||||||
uint8 fddnum;
|
uint8 fddnum, fmtb;
|
||||||
uint32 i;
|
uint32 i;
|
||||||
UNIT *uptr;
|
UNIT *uptr;
|
||||||
FILE *fp;
|
uint8 *fbuf;
|
||||||
|
|
||||||
//parse the IOPB
|
//parse the IOPB
|
||||||
cw = multibus_get_mbyte(fdc201[fdcnum].iopb);
|
cw = multibus_get_mbyte(fdc201[fdcnum].iopb);
|
||||||
|
@ -593,6 +572,7 @@ void isbc201_diskio(uint8 fdcnum)
|
||||||
ni = multibus_get_mword(fdc201[fdcnum].iopb + 8);
|
ni = multibus_get_mword(fdc201[fdcnum].iopb + 8);
|
||||||
fddnum = (di & 0x30) >> 4;
|
fddnum = (di & 0x30) >> 4;
|
||||||
uptr = isbc201_dev.units + fddnum;
|
uptr = isbc201_dev.units + fddnum;
|
||||||
|
fbuf = (uint8 *) (isbc201_dev.units + fddnum)->filebuf;
|
||||||
if (DEBUG) {
|
if (DEBUG) {
|
||||||
sim_printf("\n isbc201-%d: isbc201_diskio IOPB=%04X FDD=%02X STAT=%02X",
|
sim_printf("\n isbc201-%d: isbc201_diskio IOPB=%04X FDD=%02X STAT=%02X",
|
||||||
fdcnum, fdc201[fdcnum].iopb, fddnum, fdc201[fdcnum].stat);
|
fdcnum, fdc201[fdcnum].iopb, fddnum, fdc201[fdcnum].stat);
|
||||||
|
@ -605,7 +585,7 @@ void isbc201_diskio(uint8 fdcnum)
|
||||||
if ((fdc201[fdcnum].stat & RDY0) == 0) {
|
if ((fdc201[fdcnum].stat & RDY0) == 0) {
|
||||||
fdc201[fdcnum].rtype = RERR;
|
fdc201[fdcnum].rtype = RERR;
|
||||||
fdc201[fdcnum].rbyte0 = RB0NR;
|
fdc201[fdcnum].rbyte0 = RB0NR;
|
||||||
fdc201[fdcnum].intff = 1; //set interrupt FF
|
fdc201[fdcnum].intff = 1; //set interrupt FF
|
||||||
sim_printf("\n isbc201-%d: Ready error on drive %d", fdcnum, fddnum);
|
sim_printf("\n isbc201-%d: Ready error on drive %d", fdcnum, fddnum);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -614,7 +594,7 @@ void isbc201_diskio(uint8 fdcnum)
|
||||||
if ((fdc201[fdcnum].stat & RDY1) == 0) {
|
if ((fdc201[fdcnum].stat & RDY1) == 0) {
|
||||||
fdc201[fdcnum].rtype = RERR;
|
fdc201[fdcnum].rtype = RERR;
|
||||||
fdc201[fdcnum].rbyte0 = RB0NR;
|
fdc201[fdcnum].rbyte0 = RB0NR;
|
||||||
fdc201[fdcnum].intff = 1; //set interrupt FF
|
fdc201[fdcnum].intff = 1; //set interrupt FF
|
||||||
sim_printf("\n isbc201-%d: Ready error on drive %d", fdcnum, fddnum);
|
sim_printf("\n isbc201-%d: Ready error on drive %d", fdcnum, fddnum);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -622,38 +602,68 @@ void isbc201_diskio(uint8 fdcnum)
|
||||||
}
|
}
|
||||||
//check for address error
|
//check for address error
|
||||||
if (
|
if (
|
||||||
((di & 0x07) != 0x03) ||
|
((di & 0x07) != DHOME) && (
|
||||||
(sa > fdc201[fdcnum].fdd[fddnum].maxsec) ||
|
(sa > MAXSECSD) ||
|
||||||
((sa + nr) > (fdc201[fdcnum].fdd[fddnum].maxsec + 1)) ||
|
((sa + nr) > (MAXSECSD + 1)) ||
|
||||||
(sa == 0) ||
|
(sa == 0) ||
|
||||||
(ta > fdc201[fdcnum].fdd[fddnum].maxcyl)
|
(ta > MAXTRK)
|
||||||
) {
|
)) {
|
||||||
// sim_printf("\n isbc201-%d: maxsec=%02X maxcyl=%02X",
|
fdc201[fdcnum].rtype = RERR;
|
||||||
// fdcnum, fdc201[fdcnum].fdd[fddnum].maxsec, fdc201[fdcnum].fdd[fddnum].maxcyl);
|
fdc201[fdcnum].rbyte0 = RB0ADR;
|
||||||
fdc201[fdcnum].rtype = RERR;
|
fdc201[fdcnum].intff = 1; //set interrupt FF
|
||||||
fdc201[fdcnum].rbyte0 = RB0ADR;
|
sim_printf("\n isbc201-%d: Address error on drive %d", fdcnum, fddnum);
|
||||||
fdc201[fdcnum].intff = 1; //set interrupt FF
|
return;
|
||||||
sim_printf("\n isbc201-%d: Address error on drive %d", fdcnum, fddnum);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
switch (di & 0x07) {
|
switch (di & 0x07) {
|
||||||
case DNOP:
|
case DNOP:
|
||||||
|
fdc201[fdcnum].rtype = ROK;
|
||||||
|
fdc201[fdcnum].intff = 1; //set interrupt FF
|
||||||
|
break;
|
||||||
case DSEEK:
|
case DSEEK:
|
||||||
|
fdc201[fdcnum].fdd[fddnum].sec = sa;
|
||||||
|
fdc201[fdcnum].fdd[fddnum].cyl = ta;
|
||||||
|
fdc201[fdcnum].rtype = ROK;
|
||||||
|
fdc201[fdcnum].intff = 1; //set interrupt FF
|
||||||
|
break;
|
||||||
case DHOME:
|
case DHOME:
|
||||||
|
fdc201[fdcnum].fdd[fddnum].sec = sa;
|
||||||
|
fdc201[fdcnum].fdd[fddnum].cyl = 0;
|
||||||
|
fdc201[fdcnum].rtype = ROK;
|
||||||
|
fdc201[fdcnum].intff = 1; //set interrupt FF
|
||||||
|
break;
|
||||||
case DVCRC:
|
case DVCRC:
|
||||||
fdc201[fdcnum].rtype = ROK;
|
fdc201[fdcnum].rtype = ROK;
|
||||||
fdc201[fdcnum].intff = 1; //set interrupt FF
|
fdc201[fdcnum].intff = 1; //set interrupt FF
|
||||||
|
break;
|
||||||
|
case DFMT:
|
||||||
|
//check for WP
|
||||||
|
if(uptr->flags & UNIT_WPMODE) {
|
||||||
|
fdc201[fdcnum].rtype = RERR;
|
||||||
|
fdc201[fdcnum].rbyte0 = RB0WP;
|
||||||
|
fdc201[fdcnum].intff = 1; //set interrupt FF
|
||||||
|
sim_printf("\n isbc202-%d: Write protect error 1 on drive %d", fdcnum, fddnum);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
fmtb = multibus_get_mbyte(ba); //get the format byte
|
||||||
|
//calculate offset into disk image
|
||||||
|
dskoff = ((ta * MAXSECDD) + (sa - 1)) * 128;
|
||||||
|
for(i=0; i<=((uint32)(MAXSECDD) * 128); i++) {
|
||||||
|
*(fbuf + (dskoff + i)) = fmtb;
|
||||||
|
}
|
||||||
|
fdc201[fdcnum].rtype = ROK;
|
||||||
|
fdc201[fdcnum].intff = 1; //set interrupt FF
|
||||||
break;
|
break;
|
||||||
case DREAD:
|
case DREAD:
|
||||||
nrptr = 0;
|
nrptr = 0;
|
||||||
while(nrptr < nr) {
|
while(nrptr < nr) {
|
||||||
//calculate offset into disk image
|
//calculate offset into disk image
|
||||||
dskoff = ((ta * fdc201[fdcnum].fdd[fddnum].maxsec) + (sa - 1)) * 128;
|
dskoff = ((ta * MAXSECSD) + (sa - 1)) * 128;
|
||||||
if (DEBUG)
|
if (DEBUG)
|
||||||
sim_printf("\n isbc201-%d: cw=%02X di=%02X nr=%02X ta=%02X sa=%02X ba=%04X bn=%02X ni=%04X dskoff=%06X",
|
sim_printf("\n isbc201-%d: DREAD cw=%02X di=%02X nr=%02X ta=%02X sa=%02X ba=%04X bn=%02X ni=%04X dskoff=%06X",
|
||||||
fdcnum, cw, di, nr, ta, sa, ba, bn, ni, dskoff);
|
fdcnum, cw, di, nr, ta, sa, ba, bn, ni, dskoff);
|
||||||
for (i=0; i<128; i++) { //copy sector from image to RAM
|
//copy sector from image to RAM
|
||||||
data = *(fdc201[fdcnum].fdd[fddnum].buf + (dskoff + i));
|
for (i=0; i<128; i++) {
|
||||||
|
data = *(fbuf + (dskoff + i));
|
||||||
multibus_put_mbyte(ba + i, data);
|
multibus_put_mbyte(ba + i, data);
|
||||||
}
|
}
|
||||||
sa++;
|
sa++;
|
||||||
|
@ -661,41 +671,34 @@ void isbc201_diskio(uint8 fdcnum)
|
||||||
nrptr++;
|
nrptr++;
|
||||||
}
|
}
|
||||||
fdc201[fdcnum].rtype = ROK;
|
fdc201[fdcnum].rtype = ROK;
|
||||||
fdc201[fdcnum].intff = 1; //set interrupt FF
|
fdc201[fdcnum].intff = 1; //set interrupt FF
|
||||||
break;
|
break;
|
||||||
case DWRITE:
|
case DWRITE:
|
||||||
//check for WP
|
//check for WP
|
||||||
if(uptr->flags & UNIT_WPMODE) {
|
if(uptr->flags & UNIT_WPMODE) {
|
||||||
fdc201[fdcnum].rtype = RERR;
|
fdc201[fdcnum].rtype = RERR;
|
||||||
fdc201[fdcnum].rbyte0 = RB0WP;
|
fdc201[fdcnum].rbyte0 = RB0WP;
|
||||||
fdc201[fdcnum].intff = 1; //set interrupt FF
|
fdc201[fdcnum].intff = 1; //set interrupt FF
|
||||||
sim_printf("\n isbc201-%d: Write protect error on drive %d", fdcnum, fddnum);
|
sim_printf("\n isbc201-%d: Write protect error on drive %d", fdcnum, fddnum);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
nrptr = 0;
|
nrptr = 0;
|
||||||
while(nrptr < nr) {
|
while(nrptr < nr) {
|
||||||
//calculate offset into disk image
|
//calculate offset into disk image
|
||||||
dskoff = ((ta * fdc201[fdcnum].fdd[fddnum].maxsec) + (sa - 1)) * 128;
|
dskoff = ((ta * MAXSECSD) + (sa - 1)) * 128;
|
||||||
if (DEBUG)
|
if (DEBUG)
|
||||||
sim_printf("\n isbc201-%d: cw=%02X di=%02X nr=%02X ta=%02X sa=%02X ba=%04X bn=%02X ni=%04X dskoff=%06X",
|
sim_printf("\n isbc201-%d: DWRITE cw=%02X di=%02X nr=%02X ta=%02X sa=%02X ba=%04X bn=%02X ni=%04X dskoff=%06X",
|
||||||
fdcnum, cw, di, nr, ta, sa, ba, bn, ni, dskoff);
|
fdcnum, cw, di, nr, ta, sa, ba, bn, ni, dskoff);
|
||||||
for (i=0; i<128; i++) { //copy sector from image to RAM
|
for (i=0; i<128; i++) { //copy sector from image to RAM
|
||||||
data = multibus_get_mbyte(ba + i);
|
data = multibus_get_mbyte(ba + i);
|
||||||
*(fdc201[fdcnum].fdd[fddnum].buf + (dskoff + i)) = data;
|
*(fbuf + (dskoff + i)) = data;
|
||||||
}
|
}
|
||||||
sa++;
|
sa++;
|
||||||
ba+=0x80;
|
ba+=0x80;
|
||||||
nrptr++;
|
nrptr++;
|
||||||
}
|
}
|
||||||
//*** quick fix. Needs more thought!
|
|
||||||
fp = fopen(uptr->filename, "wb"); // write out modified image
|
|
||||||
for (i=0; i<uptr->capac; i++) {
|
|
||||||
c = *(fdc201[fdcnum].fdd[fddnum].buf + i);
|
|
||||||
fputc(c, fp);
|
|
||||||
}
|
|
||||||
fclose(fp);
|
|
||||||
fdc201[fdcnum].rtype = ROK;
|
fdc201[fdcnum].rtype = ROK;
|
||||||
fdc201[fdcnum].intff = 1; //set interrupt FF
|
fdc201[fdcnum].intff = 1; //set interrupt FF
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
sim_printf("\n isbc201-%d: isbc201_diskio bad di=%02X", fdcnum, di & 0x07);
|
sim_printf("\n isbc201-%d: isbc201_diskio bad di=%02X", fdcnum, di & 0x07);
|
||||||
|
|
|
@ -126,7 +126,7 @@
|
||||||
|
|
||||||
u3 -
|
u3 -
|
||||||
u4 -
|
u4 -
|
||||||
u5 - fdc number.
|
u5 - fdc number (board instance number).
|
||||||
u6 - fdd number.
|
u6 - fdd number.
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
@ -178,6 +178,13 @@
|
||||||
#define RB1RD0 0x40 //drive 0 ready
|
#define RB1RD0 0x40 //drive 0 ready
|
||||||
#define RB1RD1 0x80 //drive 1 ready
|
#define RB1RD1 0x80 //drive 1 ready
|
||||||
|
|
||||||
|
//disk geometry values
|
||||||
|
#define MDSSD 256256 //single density FDD size
|
||||||
|
#define MDSDD 512512 //double density FDD size
|
||||||
|
#define MAXSECSD 26 //single density last sector
|
||||||
|
#define MAXSECDD 52 //double density last sector
|
||||||
|
#define MAXTRK 76 //last track
|
||||||
|
|
||||||
/* external globals */
|
/* external globals */
|
||||||
|
|
||||||
extern uint16 port; //port called in dev_table[port]
|
extern uint16 port; //port called in dev_table[port]
|
||||||
|
@ -210,13 +217,10 @@ void isbc202_diskio(uint8 fdcnum); //do actual disk i/o
|
||||||
int32 isbc202_fdcnum = 0; //actual number of SBC-202 instances + 1
|
int32 isbc202_fdcnum = 0; //actual number of SBC-202 instances + 1
|
||||||
|
|
||||||
typedef struct { //FDD definition
|
typedef struct { //FDD definition
|
||||||
uint8 *buf;
|
|
||||||
int t0;
|
int t0;
|
||||||
int rdy;
|
int rdy;
|
||||||
uint8 sec;
|
uint8 sec;
|
||||||
uint8 cyl;
|
uint8 cyl;
|
||||||
uint8 maxsec;
|
|
||||||
uint8 maxcyl;
|
|
||||||
} FDDDEF;
|
} FDDDEF;
|
||||||
|
|
||||||
typedef struct { //FDC definition
|
typedef struct { //FDC definition
|
||||||
|
@ -234,10 +238,10 @@ typedef struct { //FDC definition
|
||||||
FDCDEF fdc202[4]; //indexed by the isbc-202 instance number
|
FDCDEF fdc202[4]; //indexed by the isbc-202 instance number
|
||||||
|
|
||||||
UNIT isbc202_unit[] = {
|
UNIT isbc202_unit[] = {
|
||||||
{ UDATA (0, UNIT_ATTABLE+UNIT_DISABLE, 0), 20 },
|
{ UDATA (0, UNIT_ATTABLE+UNIT_DISABLE+UNIT_BUFABLE+UNIT_MUSTBUF, MDSDD), 20 },
|
||||||
{ UDATA (0, UNIT_ATTABLE+UNIT_DISABLE, 0), 20 },
|
{ UDATA (0, UNIT_ATTABLE+UNIT_DISABLE+UNIT_BUFABLE+UNIT_MUSTBUF, MDSDD), 20 },
|
||||||
{ UDATA (0, UNIT_ATTABLE+UNIT_DISABLE, 0), 20 },
|
{ UDATA (0, UNIT_ATTABLE+UNIT_DISABLE+UNIT_BUFABLE+UNIT_MUSTBUF, MDSDD), 20 },
|
||||||
{ UDATA (0, UNIT_ATTABLE+UNIT_DISABLE, 0), 20 }
|
{ UDATA (0, UNIT_ATTABLE+UNIT_DISABLE+UNIT_BUFABLE+UNIT_MUSTBUF, MDSDD), 20 }
|
||||||
};
|
};
|
||||||
|
|
||||||
REG isbc202_reg[] = {
|
REG isbc202_reg[] = {
|
||||||
|
@ -254,13 +258,13 @@ REG isbc202_reg[] = {
|
||||||
{ HRDATA (STAT2, fdc202[2].stat, 8) }, /* isbc202 2 status */
|
{ HRDATA (STAT2, fdc202[2].stat, 8) }, /* isbc202 2 status */
|
||||||
{ HRDATA (RTYP2, fdc202[2].rtype, 8) }, /* isbc202 2 result type */
|
{ HRDATA (RTYP2, fdc202[2].rtype, 8) }, /* isbc202 2 result type */
|
||||||
{ HRDATA (RBYT2A, fdc202[2].rbyte0, 8) }, /* isbc202 2 result byte 0 */
|
{ HRDATA (RBYT2A, fdc202[2].rbyte0, 8) }, /* isbc202 2 result byte 0 */
|
||||||
{ HRDATA (RBYT2B, fdc202[0].rbyte1, 8) }, /* isbc202 2 result byte 1 */
|
{ HRDATA (RBYT2B, fdc202[2].rbyte1, 8) }, /* isbc202 2 result byte 1 */
|
||||||
{ HRDATA (INTFF2, fdc202[2].intff, 8) }, /* isbc202 2 interrupt f/f */
|
{ HRDATA (INTFF2, fdc202[2].intff, 8) }, /* isbc202 2 interrupt f/f */
|
||||||
{ HRDATA (STAT3, fdc202[3].stat, 8) }, /* isbc202 3 status */
|
{ HRDATA (STAT3, fdc202[3].stat, 8) }, /* isbc202 3 status */
|
||||||
{ HRDATA (RTYP3, fdc202[3].rtype, 8) }, /* isbc202 3 result type */
|
{ HRDATA (RTYP3, fdc202[3].rtype, 8) }, /* isbc202 3 result type */
|
||||||
{ HRDATA (RBYT3A, fdc202[3].rbyte0, 8) }, /* isbc202 3 result byte 0 */
|
{ HRDATA (RBYT3A, fdc202[3].rbyte0, 8) }, /* isbc202 3 result byte 0 */
|
||||||
{ HRDATA (RBYT3B, fdc202[3].rbyte1, 8) }, /* isbc202 3 result byte 1 */
|
{ HRDATA (RBYT3B, fdc202[3].rbyte1, 8) }, /* isbc202 3 result byte 1 */
|
||||||
{ HRDATA (INTFF3, fdc202[0].intff, 8) }, /* isbc202 3 interrupt f/f */
|
{ HRDATA (INTFF3, fdc202[3].intff, 8) }, /* isbc202 3 interrupt f/f */
|
||||||
{ NULL }
|
{ NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -312,17 +316,30 @@ DEVICE isbc202_dev = {
|
||||||
|
|
||||||
t_stat isbc202_reset(DEVICE *dptr, uint16 base)
|
t_stat isbc202_reset(DEVICE *dptr, uint16 base)
|
||||||
{
|
{
|
||||||
|
int32 i;
|
||||||
|
UNIT *uptr;
|
||||||
|
|
||||||
sim_printf(" iSBC-202 FDC Board");
|
sim_printf(" iSBC-202 FDC Board");
|
||||||
if (SBC202_NUM) {
|
if (SBC202_NUM) {
|
||||||
sim_printf(" - Found\n");
|
sim_printf(" - Found\n");
|
||||||
sim_printf(" isbc202-%d: Hardware Reset\n", isbc202_fdcnum);
|
sim_printf(" isbc202-%d: Hardware Reset\n", isbc202_fdcnum);
|
||||||
sim_printf(" isbc202-%d: Registered at %04X\n", isbc202_fdcnum, base);
|
sim_printf(" isbc202-%d: Registered at %04X\n", isbc202_fdcnum, base);
|
||||||
|
//register base port address for this FDC instance
|
||||||
fdc202[isbc202_fdcnum].baseport = base;
|
fdc202[isbc202_fdcnum].baseport = base;
|
||||||
|
//register I/O port addresses for each function
|
||||||
reg_dev(isbc2020, base, isbc202_fdcnum); //read status
|
reg_dev(isbc2020, base, isbc202_fdcnum); //read status
|
||||||
reg_dev(isbc2021, base + 1, isbc202_fdcnum); //read rslt type/write IOPB addr-l
|
reg_dev(isbc2021, base + 1, isbc202_fdcnum); //read rslt type/write IOPB addr-l
|
||||||
reg_dev(isbc2022, base + 2, isbc202_fdcnum); //write IOPB addr-h and start
|
reg_dev(isbc2022, base + 2, isbc202_fdcnum); //write IOPB addr-h and start
|
||||||
reg_dev(isbc2023, base + 3, isbc202_fdcnum); //read rstl byte
|
reg_dev(isbc2023, base + 3, isbc202_fdcnum); //read rstl byte
|
||||||
reg_dev(isbc2027, base + 7, isbc202_fdcnum); //write reset isbc202
|
reg_dev(isbc2027, base + 7, isbc202_fdcnum); //write reset isbc202
|
||||||
|
// one-time initialization for all FDDs for this FDC instance
|
||||||
|
for (i = 0; i < FDD_NUM; i++) {
|
||||||
|
uptr = isbc202_dev.units + i;
|
||||||
|
uptr->u5 = isbc202_fdcnum; //fdc device number
|
||||||
|
uptr->u6 = i; //fdd unit number
|
||||||
|
uptr->flags |= UNIT_WPMODE; //set WP in unit flags
|
||||||
|
}
|
||||||
|
isbc202_reset1(isbc202_fdcnum); //software reset
|
||||||
isbc202_reset1(isbc202_fdcnum);
|
isbc202_reset1(isbc202_fdcnum);
|
||||||
isbc202_fdcnum++;
|
isbc202_fdcnum++;
|
||||||
} else
|
} else
|
||||||
|
@ -344,33 +361,27 @@ void isbc202_reset1(uint8 fdcnum)
|
||||||
fdc202[fdcnum].stat |= FDCPRE | FDCDD; //set the FDC status
|
fdc202[fdcnum].stat |= FDCPRE | FDCDD; //set the FDC status
|
||||||
fdc202[fdcnum].rtype = ROK;
|
fdc202[fdcnum].rtype = ROK;
|
||||||
if (uptr->capac == 0) { /* if not configured */
|
if (uptr->capac == 0) { /* if not configured */
|
||||||
uptr->u5 = fdcnum; //fdc device number
|
|
||||||
uptr->u6 = i; //fdd unit number
|
|
||||||
uptr->flags |= UNIT_WPMODE; /* set WP in unit flags */
|
|
||||||
sim_printf(" SBC202%d: Configured, Status=%02X Not attached\n", i, fdc202[fdcnum].stat);
|
sim_printf(" SBC202%d: Configured, Status=%02X Not attached\n", i, fdc202[fdcnum].stat);
|
||||||
} else {
|
} else {
|
||||||
switch(i){
|
switch(i){
|
||||||
case 0:
|
case 0:
|
||||||
fdc202[fdcnum].stat |= RDY0; //set FDD 0 ready
|
fdc202[fdcnum].stat |= RDY0; //set FDD 0 ready
|
||||||
fdc202[fdcnum].rbyte1 |= RB1RD0;
|
fdc202[fdcnum].rbyte1 |= RB1RD0;
|
||||||
fdc202[fdcnum].rdychg = 0;
|
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
fdc202[fdcnum].stat |= RDY1; //set FDD 1 ready
|
fdc202[fdcnum].stat |= RDY1; //set FDD 1 ready
|
||||||
fdc202[fdcnum].rbyte1 |= RB1RD1;
|
fdc202[fdcnum].rbyte1 |= RB1RD1;
|
||||||
fdc202[fdcnum].rdychg = 0;
|
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
fdc202[fdcnum].stat |= RDY2; //set FDD 2 ready
|
fdc202[fdcnum].stat |= RDY2; //set FDD 2 ready
|
||||||
fdc202[fdcnum].rbyte1 |= RB1RD2;
|
fdc202[fdcnum].rbyte1 |= RB1RD2;
|
||||||
fdc202[fdcnum].rdychg = 0;
|
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
fdc202[fdcnum].stat |= RDY3; //set FDD 3 ready
|
fdc202[fdcnum].stat |= RDY3; //set FDD 3 ready
|
||||||
fdc202[fdcnum].rbyte1 |= RB1RD3;
|
fdc202[fdcnum].rbyte1 |= RB1RD3;
|
||||||
fdc202[fdcnum].rdychg = 0;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
fdc202[fdcnum].rdychg = 0;
|
||||||
sim_printf(" SBC202%d: Configured, Status=%02X Attached to %s\n",
|
sim_printf(" SBC202%d: Configured, Status=%02X Attached to %s\n",
|
||||||
i, fdc202[fdcnum].stat, uptr->filename);
|
i, fdc202[fdcnum].stat, uptr->filename);
|
||||||
}
|
}
|
||||||
|
@ -382,80 +393,37 @@ void isbc202_reset1(uint8 fdcnum)
|
||||||
t_stat isbc202_attach (UNIT *uptr, CONST char *cptr)
|
t_stat isbc202_attach (UNIT *uptr, CONST char *cptr)
|
||||||
{
|
{
|
||||||
t_stat r;
|
t_stat r;
|
||||||
FILE *fp;
|
|
||||||
int32 i, c = 0;
|
|
||||||
long flen;
|
|
||||||
uint8 fdcnum, fddnum;
|
uint8 fdcnum, fddnum;
|
||||||
|
|
||||||
sim_debug (DEBUG_flow, &isbc202_dev, " isbc202_attach: Entered with cptr=%s\n", cptr);
|
sim_debug (DEBUG_flow, &isbc202_dev, " isbc202_attach: Entered with cptr=%s\n", cptr);
|
||||||
|
// sim_printf(" isbc202_attach: Entered with cptr=%s\n", cptr);
|
||||||
if ((r = attach_unit (uptr, cptr)) != SCPE_OK) {
|
if ((r = attach_unit (uptr, cptr)) != SCPE_OK) {
|
||||||
sim_printf(" isbc202_attach: Attach error\n");
|
sim_printf(" isbc202_attach: Attach error\n");
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
fdcnum = uptr->u5;
|
fdcnum = uptr->u5;
|
||||||
fddnum = uptr->u6;
|
fddnum = uptr->u6;
|
||||||
fp = fopen(uptr->filename, "rb");
|
switch(fddnum){
|
||||||
if (fp == NULL) {
|
case 0:
|
||||||
sim_printf(" Unable to open disk image file %s\n", uptr->filename);
|
fdc202[fdcnum].stat |= RDY0; //set FDD 0 ready
|
||||||
sim_printf(" No disk image loaded!!!\n");
|
fdc202[fdcnum].rbyte1 |= RB1RD0;
|
||||||
} else {
|
break;
|
||||||
sim_printf("isbc202: Attach\n");
|
case 1:
|
||||||
fseek(fp, 0, SEEK_END); /* size disk image */
|
fdc202[fdcnum].stat |= RDY1; //set FDD 1 ready
|
||||||
flen = ftell(fp);
|
fdc202[fdcnum].rbyte1 |= RB1RD1;
|
||||||
fseek(fp, 0, SEEK_SET);
|
break;
|
||||||
if (flen == -1) {
|
case 2:
|
||||||
sim_printf(" isbc202_attach: File error\n");
|
fdc202[fdcnum].stat |= RDY2; //set FDD 2 ready
|
||||||
fclose(fp);
|
fdc202[fdcnum].rbyte1 |= RB1RD2;
|
||||||
return SCPE_IOERR;
|
break;
|
||||||
}
|
case 3:
|
||||||
if (fdc202[fdcnum].fdd[fddnum].buf == NULL) { /* no buffer allocated */
|
fdc202[fdcnum].stat |= RDY3; //set FDD 3 ready
|
||||||
fdc202[fdcnum].fdd[fddnum].buf = (uint8 *)malloc(flen);
|
fdc202[fdcnum].rbyte1 |= RB1RD3;
|
||||||
if (fdc202[fdcnum].fdd[fddnum].buf == NULL) {
|
break;
|
||||||
sim_printf(" isbc202_attach: Malloc error\n");
|
|
||||||
fclose(fp);
|
|
||||||
return SCPE_MEM;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
uptr->capac = flen;
|
|
||||||
i = 0;
|
|
||||||
c = fgetc(fp); // copy disk image into buffer
|
|
||||||
while (c != EOF) {
|
|
||||||
*(fdc202[fdcnum].fdd[fddnum].buf + i++) = c & 0xFF;
|
|
||||||
c = fgetc(fp);
|
|
||||||
}
|
|
||||||
fclose(fp);
|
|
||||||
switch(fddnum){
|
|
||||||
case 0:
|
|
||||||
fdc202[fdcnum].stat |= RDY0; //set FDD 0 ready
|
|
||||||
fdc202[fdcnum].rtype = ROK;
|
|
||||||
fdc202[fdcnum].rbyte1 |= RB1RD0;
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
fdc202[fdcnum].stat |= RDY1; //set FDD 1 ready
|
|
||||||
fdc202[fdcnum].rtype = ROK;
|
|
||||||
fdc202[fdcnum].rbyte1 |= RB1RD1;
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
fdc202[fdcnum].stat |= RDY2; //set FDD 2 ready
|
|
||||||
fdc202[fdcnum].rtype = ROK;
|
|
||||||
fdc202[fdcnum].rbyte1 |= RB1RD2;
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
fdc202[fdcnum].stat |= RDY3; //set FDD 3 ready
|
|
||||||
fdc202[fdcnum].rtype = ROK;
|
|
||||||
fdc202[fdcnum].rbyte1 |= RB1RD3;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (flen == 512512) { /* 8" 512K SSDD */
|
|
||||||
fdc202[fdcnum].fdd[fddnum].maxcyl = 77;
|
|
||||||
fdc202[fdcnum].fdd[fddnum].maxsec = 52;
|
|
||||||
fdc202[fdcnum].fdd[fddnum].sec = 1;
|
|
||||||
fdc202[fdcnum].fdd[fddnum].cyl = 0;
|
|
||||||
} else
|
|
||||||
sim_printf(" iSBC-202-%d: Not a DD disk image\n", fdcnum);
|
|
||||||
sim_printf(" iSBC-202%d: Configured %d bytes, Attached to %s\n",
|
|
||||||
fdcnum, uptr->capac, uptr->filename);
|
|
||||||
}
|
}
|
||||||
|
fdc202[fdcnum].rtype = ROK;
|
||||||
|
sim_printf(" iSBC-202%d: FDD %d Configured %d bytes, Attached to %s\n",
|
||||||
|
fdcnum, fddnum, uptr->capac, uptr->filename);
|
||||||
sim_debug (DEBUG_flow, &isbc202_dev, " isbc202_attach: Done\n");
|
sim_debug (DEBUG_flow, &isbc202_dev, " isbc202_attach: Done\n");
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
@ -594,13 +562,14 @@ uint8 isbc2027(t_bool io, uint8 data)
|
||||||
|
|
||||||
void isbc202_diskio(uint8 fdcnum)
|
void isbc202_diskio(uint8 fdcnum)
|
||||||
{
|
{
|
||||||
uint8 cw, di, nr, ta, sa, data, nrptr, c;
|
uint8 cw, di, nr, ta, sa, data, nrptr;
|
||||||
uint16 ba;
|
uint16 ba;
|
||||||
uint32 dskoff;
|
uint32 dskoff;
|
||||||
uint8 fddnum, fmtb;
|
uint8 fddnum, fmtb;
|
||||||
uint32 i;
|
uint32 i;
|
||||||
UNIT *uptr;
|
UNIT *uptr;
|
||||||
FILE *fp;
|
uint8 *fbuf;
|
||||||
|
|
||||||
//parse the IOPB
|
//parse the IOPB
|
||||||
cw = multibus_get_mbyte(fdc202[fdcnum].iopb);
|
cw = multibus_get_mbyte(fdc202[fdcnum].iopb);
|
||||||
di = multibus_get_mbyte(fdc202[fdcnum].iopb + 1);
|
di = multibus_get_mbyte(fdc202[fdcnum].iopb + 1);
|
||||||
|
@ -610,13 +579,12 @@ void isbc202_diskio(uint8 fdcnum)
|
||||||
ba = multibus_get_mword(fdc202[fdcnum].iopb + 5);
|
ba = multibus_get_mword(fdc202[fdcnum].iopb + 5);
|
||||||
fddnum = (di & 0x30) >> 4;
|
fddnum = (di & 0x30) >> 4;
|
||||||
uptr = isbc202_dev.units + fddnum;
|
uptr = isbc202_dev.units + fddnum;
|
||||||
|
fbuf = (uint8 *) (isbc202_dev.units + fddnum)->filebuf;
|
||||||
if (DEBUG) {
|
if (DEBUG) {
|
||||||
sim_printf("\n isbc202-%d: isbc202_diskio IOPB=%04X FDD=%02X STAT=%02X",
|
sim_printf("\n isbc202-%d: isbc202_diskio IOPB=%04X FDD=%02X STAT=%02X",
|
||||||
fdcnum, fdc202[fdcnum].iopb, fddnum, fdc202[fdcnum].stat);
|
fdcnum, fdc202[fdcnum].iopb, fddnum, fdc202[fdcnum].stat);
|
||||||
sim_printf("\n isbc202-%d: cw=%02X di=%02X nr=%02X ta=%02X sa=%02X ba=%04X",
|
sim_printf("\n isbc202-%d: cw=%02X di=%02X nr=%02X ta=%02X sa=%02X ba=%04X",
|
||||||
fdcnum, cw, di, nr, ta, sa, ba);
|
fdcnum, cw, di, nr, ta, sa, ba);
|
||||||
// sim_printf("\n isbc202-%d: maxsec=%02X maxcyl=%02X",
|
|
||||||
// fdcnum, fdc202[fdcnum].fdd[fddnum].maxsec, fdc202[fdcnum].fdd[fddnum].maxcyl);
|
|
||||||
}
|
}
|
||||||
//check for not ready
|
//check for not ready
|
||||||
switch(fddnum) {
|
switch(fddnum) {
|
||||||
|
@ -659,20 +627,17 @@ void isbc202_diskio(uint8 fdcnum)
|
||||||
}
|
}
|
||||||
//check for address error
|
//check for address error
|
||||||
if (
|
if (
|
||||||
((di & 0x07) != 0x03) && (
|
((di & 0x07) != DHOME) && (
|
||||||
(sa > fdc202[fdcnum].fdd[fddnum].maxsec) ||
|
(sa > MAXSECDD) ||
|
||||||
((sa + nr) > (fdc202[fdcnum].fdd[fddnum].maxsec + 1)) ||
|
((sa + nr) > (MAXSECDD + 1)) ||
|
||||||
(sa == 0) ||
|
(sa == 0) ||
|
||||||
(ta > fdc202[fdcnum].fdd[fddnum].maxcyl)
|
(ta > MAXTRK)
|
||||||
)) {
|
)) {
|
||||||
if (DEBUG)
|
fdc202[fdcnum].rtype = RERR;
|
||||||
sim_printf("\n isbc202-%d: maxsec=%02X maxcyl=%02X",
|
fdc202[fdcnum].rbyte0 = RB0ADR;
|
||||||
fdcnum, fdc202[fdcnum].fdd[fddnum].maxsec, fdc202[fdcnum].fdd[fddnum].maxcyl);
|
fdc202[fdcnum].intff = 1; //set interrupt FF
|
||||||
fdc202[fdcnum].rtype = RERR;
|
sim_printf("\n isbc202-%d: Address error on drive %d", fdcnum, fddnum);
|
||||||
fdc202[fdcnum].rbyte0 = RB0ADR;
|
return;
|
||||||
fdc202[fdcnum].intff = 1; //set interrupt FF
|
|
||||||
sim_printf("\n isbc202-%d: Address error on drive %d", fdcnum, fddnum);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
switch (di & 0x07) {
|
switch (di & 0x07) {
|
||||||
case DNOP:
|
case DNOP:
|
||||||
|
@ -706,17 +671,10 @@ void isbc202_diskio(uint8 fdcnum)
|
||||||
}
|
}
|
||||||
fmtb = multibus_get_mbyte(ba); //get the format byte
|
fmtb = multibus_get_mbyte(ba); //get the format byte
|
||||||
//calculate offset into disk image
|
//calculate offset into disk image
|
||||||
dskoff = ((ta * (uint32)(fdc202[fdcnum].fdd[fddnum].maxsec)) + (sa - 1)) * 128;
|
dskoff = ((ta * MAXSECDD) + (sa - 1)) * 128;
|
||||||
for(i=0; i<=((uint32)(fdc202[fdcnum].fdd[fddnum].maxsec) * 128); i++) {
|
for(i=0; i<=((uint32)(MAXSECDD) * 128); i++) {
|
||||||
*(fdc202[fdcnum].fdd[fddnum].buf + (dskoff + i)) = fmtb;
|
*(fbuf + (dskoff + i)) = fmtb;
|
||||||
}
|
}
|
||||||
//*** quick fix. Needs more thought!
|
|
||||||
fp = fopen(uptr->filename, "wb"); // write out modified image
|
|
||||||
for (i=0; i<uptr->capac; i++) {
|
|
||||||
c = *(fdc202[fdcnum].fdd[fddnum].buf + i);
|
|
||||||
fputc(c, fp);
|
|
||||||
}
|
|
||||||
fclose(fp);
|
|
||||||
fdc202[fdcnum].rtype = ROK;
|
fdc202[fdcnum].rtype = ROK;
|
||||||
fdc202[fdcnum].intff = 1; //set interrupt FF
|
fdc202[fdcnum].intff = 1; //set interrupt FF
|
||||||
break;
|
break;
|
||||||
|
@ -724,11 +682,13 @@ void isbc202_diskio(uint8 fdcnum)
|
||||||
nrptr = 0;
|
nrptr = 0;
|
||||||
while(nrptr < nr) {
|
while(nrptr < nr) {
|
||||||
//calculate offset into disk image
|
//calculate offset into disk image
|
||||||
dskoff = ((ta * fdc202[fdcnum].fdd[fddnum].maxsec) + (sa - 1)) * 128;
|
dskoff = ((ta * MAXSECDD) + (sa - 1)) * 128;
|
||||||
// sim_printf("\n isbc202-%d: cw=%02X di=%02X nr=%02X ta=%02X sa=%02X ba=%04X dskoff=%06X",
|
if (DEBUG)
|
||||||
// fdcnum, cw, di, nr, ta, sa, ba, dskoff);
|
sim_printf("\n isbc202-%d: cw=%02X di=%02X nr=%02X ta=%02X sa=%02X ba=%04X dskoff=%06X",
|
||||||
for (i=0; i<128; i++) { //copy sector from image to RAM
|
fdcnum, cw, di, nr, ta, sa, ba, dskoff);
|
||||||
data = *(fdc202[fdcnum].fdd[fddnum].buf + (dskoff + i));
|
//copy sector from image to RAM
|
||||||
|
for (i=0; i<128; i++) {
|
||||||
|
data = *(fbuf + (dskoff + i));
|
||||||
multibus_put_mbyte(ba + i, data);
|
multibus_put_mbyte(ba + i, data);
|
||||||
}
|
}
|
||||||
sa++;
|
sa++;
|
||||||
|
@ -750,24 +710,18 @@ void isbc202_diskio(uint8 fdcnum)
|
||||||
nrptr = 0;
|
nrptr = 0;
|
||||||
while(nrptr < nr) {
|
while(nrptr < nr) {
|
||||||
//calculate offset into disk image
|
//calculate offset into disk image
|
||||||
dskoff = ((ta * fdc202[fdcnum].fdd[fddnum].maxsec) + (sa - 1)) * 128;
|
dskoff = ((ta * MAXSECDD) + (sa - 1)) * 128;
|
||||||
// sim_printf("\n isbc202-%d: cw=%02X di=%02X nr=%02X ta=%02X sa=%02X ba=%04X dskoff=%06X",
|
if (DEBUG)
|
||||||
// fdcnum, cw, di, nr, ta, sa, ba, dskoff);
|
sim_printf("\n isbc202-%d: cw=%02X di=%02X nr=%02X ta=%02X sa=%02X ba=%04X dskoff=%06X",
|
||||||
for (i=0; i<128; i++) { //copy sector from image to RAM
|
fdcnum, cw, di, nr, ta, sa, ba, dskoff);
|
||||||
|
for (i=0; i<128; i++) { //copy sector from image to RAM
|
||||||
data = multibus_get_mbyte(ba + i);
|
data = multibus_get_mbyte(ba + i);
|
||||||
*(fdc202[fdcnum].fdd[fddnum].buf + (dskoff + i)) = data;
|
*(fbuf + (dskoff + i)) = data;
|
||||||
}
|
}
|
||||||
sa++;
|
sa++;
|
||||||
ba+=0x80;
|
ba+=0x80;
|
||||||
nrptr++;
|
nrptr++;
|
||||||
}
|
}
|
||||||
//*** quick fix. Needs more thought!
|
|
||||||
fp = fopen(uptr->filename, "wb"); // write out modified image
|
|
||||||
for (i=0; i<uptr->capac; i++) {
|
|
||||||
c = *(fdc202[fdcnum].fdd[fddnum].buf + i);
|
|
||||||
fputc(c, fp);
|
|
||||||
}
|
|
||||||
fclose(fp);
|
|
||||||
fdc202[fdcnum].rtype = ROK;
|
fdc202[fdcnum].rtype = ROK;
|
||||||
fdc202[fdcnum].intff = 1; //set interrupt FF
|
fdc202[fdcnum].intff = 1; //set interrupt FF
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -1,736 +0,0 @@
|
||||||
/* isbc202.c: Intel double density disk adapter adapter
|
|
||||||
|
|
||||||
Copyright (c) 2010, William A. Beech
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a
|
|
||||||
copy of this software and associated documentation files (the "Software"),
|
|
||||||
to deal in the Software without restriction, including without limitation
|
|
||||||
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
||||||
and/or sell copies of the Software, and to permit persons to whom the
|
|
||||||
Software is furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in
|
|
||||||
all copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
|
||||||
WILLIAM A. BEECH BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
|
||||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
|
||||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
|
|
||||||
Except as contained in this notice, the name of William A. Beech shall not be
|
|
||||||
used in advertising or otherwise to promote the sale, use or other dealings
|
|
||||||
in this Software without prior written authorization from William A. Beech.
|
|
||||||
|
|
||||||
MODIFICATIONS:
|
|
||||||
|
|
||||||
27 Jun 16 - Original file.
|
|
||||||
|
|
||||||
NOTES:
|
|
||||||
|
|
||||||
This controller will mount 4 DD disk images on drives :F0: thru :F3: addressed
|
|
||||||
at ports 078H to 07FH.
|
|
||||||
|
|
||||||
Registers:
|
|
||||||
|
|
||||||
078H - Read - Subsystem status
|
|
||||||
bit 0 - ready status of drive 0
|
|
||||||
bit 1 - ready status of drive 1
|
|
||||||
bit 2 - state of channel's interrupt FF
|
|
||||||
bit 3 - controller presence indicator
|
|
||||||
bit 4 - DD controller presence indicator
|
|
||||||
bit 5 - ready status of drive 2
|
|
||||||
bit 6 - ready status of drive 3
|
|
||||||
bit 7 - zero
|
|
||||||
|
|
||||||
079H - Read - Read result type (bits 2-7 are zero)
|
|
||||||
00 - I/O complete with error
|
|
||||||
01 - Reserved
|
|
||||||
10 - Result byte contains diskette ready status
|
|
||||||
11 - Reserved
|
|
||||||
079H - Write - IOPB address low byte.
|
|
||||||
|
|
||||||
07AH - Write - IOPB address high byte and start operation.
|
|
||||||
|
|
||||||
07BH - Read - Read result byte
|
|
||||||
If result type is 00H
|
|
||||||
bit 0 - deleted record
|
|
||||||
bit 1 - CRC error
|
|
||||||
bit 2 - seek error
|
|
||||||
bit 3 - address error
|
|
||||||
bit 4 - data overrun/underrun
|
|
||||||
bit 5 - write protect
|
|
||||||
bit 6 - write error
|
|
||||||
bit 7 - not ready
|
|
||||||
If result type is 02H and ready has changed
|
|
||||||
bit 0 - zero
|
|
||||||
bit 1 - zero
|
|
||||||
bit 2 - zero
|
|
||||||
bit 3 - zero
|
|
||||||
bit 4 - drive 2 ready
|
|
||||||
bit 5 - drive 3 ready
|
|
||||||
bit 6 - drive 0 ready
|
|
||||||
bit 7 - drive 1 ready
|
|
||||||
else return 0
|
|
||||||
|
|
||||||
07FH - Write - Reset diskette system.
|
|
||||||
|
|
||||||
Operations:
|
|
||||||
NOP - 0x00
|
|
||||||
Seek - 0x01
|
|
||||||
Format Track - 0x02
|
|
||||||
Recalibrate - 0x03
|
|
||||||
Read Data - 0x04
|
|
||||||
Verify CRC - 0x05
|
|
||||||
Write Data - 0x06
|
|
||||||
Write Deleted Data - 0x07
|
|
||||||
|
|
||||||
IOPB - I/O Parameter Block
|
|
||||||
Byte 0 - Channel Word
|
|
||||||
bit 3 - data word length (=8-bit, 1=16-bit)
|
|
||||||
bit 4-5 - interrupt control
|
|
||||||
00 - I/O complete interrupt to be issued
|
|
||||||
01 - I/O complete interrupts are disabled
|
|
||||||
10 - illegal code
|
|
||||||
11 - illegal code
|
|
||||||
bit 6- randon format sequence
|
|
||||||
|
|
||||||
Byte 1 - Diskette Instruction
|
|
||||||
bit 0-2 - operation code
|
|
||||||
000 - no operation
|
|
||||||
001 - seek
|
|
||||||
010 - format track
|
|
||||||
011 - recalibrate
|
|
||||||
100 - read data
|
|
||||||
101 - verify CRC
|
|
||||||
110 - write data
|
|
||||||
111 - write deleted data
|
|
||||||
bit 3 - data word length ( same as byte-0, bit-3)
|
|
||||||
bit 4-5 - unit select
|
|
||||||
00 - drive 0
|
|
||||||
01 - drive 1
|
|
||||||
10 - drive 2
|
|
||||||
11 - drive 3
|
|
||||||
bit 6-7 - reserved (zero)
|
|
||||||
|
|
||||||
Byte 2 - Number of Records
|
|
||||||
|
|
||||||
Byte 4 - Track Address
|
|
||||||
|
|
||||||
Byte 5 - Sector Address
|
|
||||||
|
|
||||||
Byte 6 - Buffer Low Address
|
|
||||||
|
|
||||||
Byte 7 - Buffer High Address
|
|
||||||
|
|
||||||
u3 -
|
|
||||||
u4 -
|
|
||||||
u5 - fdc number (board instance number).
|
|
||||||
u6 - fdd number.
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "system_defs.h" /* system header in system dir */
|
|
||||||
|
|
||||||
#define DEBUG 0
|
|
||||||
|
|
||||||
#define UNIT_V_WPMODE (UNIT_V_UF) /* Write protect */
|
|
||||||
#define UNIT_WPMODE (1 << UNIT_V_WPMODE)
|
|
||||||
|
|
||||||
#define FDD_NUM 4
|
|
||||||
|
|
||||||
//disk controoler operations
|
|
||||||
#define DNOP 0x00 //disk no operation
|
|
||||||
#define DSEEK 0x01 //disk seek
|
|
||||||
#define DFMT 0x02 //disk format
|
|
||||||
#define DHOME 0x03 //disk home
|
|
||||||
#define DREAD 0x04 //disk read
|
|
||||||
#define DVCRC 0x05 //disk verify CRC
|
|
||||||
#define DWRITE 0x06 //disk write
|
|
||||||
|
|
||||||
//status
|
|
||||||
#define RDY0 0x01 //FDD 0 ready
|
|
||||||
#define RDY1 0x02 //FDD 1 ready
|
|
||||||
#define FDCINT 0x04 //FDC interrupt flag
|
|
||||||
#define FDCPRE 0x08 //FDC board present
|
|
||||||
#define FDCDD 0x10 //fdc is DD
|
|
||||||
#define RDY2 0x20 //FDD 2 ready
|
|
||||||
#define RDY3 0x40 //FDD 3 ready
|
|
||||||
|
|
||||||
//result type
|
|
||||||
#define RERR 0x00 //FDC returned error
|
|
||||||
#define ROK 0x02 //FDC returned ok
|
|
||||||
|
|
||||||
// If result type is RERR then rbyte is
|
|
||||||
#define RB0DR 0x01 //deleted record
|
|
||||||
#define RB0CRC 0x02 //CRC error
|
|
||||||
#define RB0SEK 0x04 //seek error
|
|
||||||
#define RB0ADR 0x08 //address error
|
|
||||||
#define RB0OU 0x10 //data overrun/underrun
|
|
||||||
#define RB0WP 0x20 //write protect
|
|
||||||
#define RB0WE 0x40 //write error
|
|
||||||
#define RB0NR 0x80 //not ready
|
|
||||||
|
|
||||||
// If result type is ROK then rbyte is
|
|
||||||
#define RB1RD2 0x10 //drive 2 ready
|
|
||||||
#define RB1RD3 0x20 //drive 3 ready
|
|
||||||
#define RB1RD0 0x40 //drive 0 ready
|
|
||||||
#define RB1RD1 0x80 //drive 1 ready
|
|
||||||
|
|
||||||
#define MDSSD 256256 //single density FDD size
|
|
||||||
#define MDSDD 512512 //double density FDD size
|
|
||||||
#define MAXSECSD 26 //single density last sector
|
|
||||||
#define MAXSECDD 52 //double density last sector
|
|
||||||
#define MAXTRK 76 //last track
|
|
||||||
|
|
||||||
/* external globals */
|
|
||||||
|
|
||||||
extern uint16 port; //port called in dev_table[port]
|
|
||||||
extern int32 PCX;
|
|
||||||
|
|
||||||
/* external function prototypes */
|
|
||||||
|
|
||||||
extern uint16 reg_dev(uint8 (*routine)(t_bool, uint8), uint16, uint8);
|
|
||||||
extern uint8 multibus_get_mbyte(uint16 addr);
|
|
||||||
extern uint16 multibus_get_mword(uint16 addr);
|
|
||||||
extern void multibus_put_mbyte(uint16 addr, uint8 val);
|
|
||||||
extern uint8 multibus_put_mword(uint16 addr, uint16 val);
|
|
||||||
|
|
||||||
/* function prototypes */
|
|
||||||
|
|
||||||
t_stat isbc202_reset(DEVICE *dptr, uint16 base);
|
|
||||||
void isbc202_reset1(uint8 fdcnum);
|
|
||||||
t_stat isbc202_attach (UNIT *uptr, CONST char *cptr);
|
|
||||||
t_stat isbc202_set_mode (UNIT *uptr, int32 val, CONST char *cptr, void *desc);
|
|
||||||
uint8 isbc202_get_dn(void);
|
|
||||||
uint8 isbc2020(t_bool io, uint8 data); /* isbc202 0 */
|
|
||||||
uint8 isbc2021(t_bool io, uint8 data); /* isbc202 1 */
|
|
||||||
uint8 isbc2022(t_bool io, uint8 data); /* isbc202 2 */
|
|
||||||
uint8 isbc2023(t_bool io, uint8 data); /* isbc202 3 */
|
|
||||||
uint8 isbc2027(t_bool io, uint8 data); /* isbc202 7 */
|
|
||||||
void isbc202_diskio(uint8 fdcnum); //do actual disk i/o
|
|
||||||
|
|
||||||
/* globals */
|
|
||||||
|
|
||||||
int32 isbc202_fdcnum = 0; //actual number of SBC-202 instances + 1
|
|
||||||
|
|
||||||
typedef struct { //FDD definition
|
|
||||||
int t0;
|
|
||||||
int rdy;
|
|
||||||
uint8 sec;
|
|
||||||
uint8 cyl;
|
|
||||||
} FDDDEF;
|
|
||||||
|
|
||||||
typedef struct { //FDC definition
|
|
||||||
uint16 baseport; //FDC base port
|
|
||||||
uint16 iopb; //FDC IOPB
|
|
||||||
uint8 stat; //FDC status
|
|
||||||
uint8 rdychg; //FDC ready change
|
|
||||||
uint8 rtype; //FDC result type
|
|
||||||
uint8 rbyte0; //FDC result byte for type 00
|
|
||||||
uint8 rbyte1; //FDC result byte for type 10
|
|
||||||
uint8 intff; //fdc interrupt FF
|
|
||||||
FDDDEF fdd[FDD_NUM]; //indexed by the FDD number
|
|
||||||
} FDCDEF;
|
|
||||||
|
|
||||||
FDCDEF fdc202[4]; //indexed by the isbc-202 instance number
|
|
||||||
|
|
||||||
UNIT isbc202_unit[] = {
|
|
||||||
{ UDATA (0, UNIT_ATTABLE+UNIT_DISABLE+UNIT_BUFABLE+UNIT_MUSTBUF, 0), 20 },
|
|
||||||
{ UDATA (0, UNIT_ATTABLE+UNIT_DISABLE+UNIT_BUFABLE+UNIT_MUSTBUF, 0), 20 },
|
|
||||||
{ UDATA (0, UNIT_ATTABLE+UNIT_DISABLE+UNIT_BUFABLE+UNIT_MUSTBUF, 0), 20 },
|
|
||||||
{ UDATA (0, UNIT_ATTABLE+UNIT_DISABLE+UNIT_BUFABLE+UNIT_MUSTBUF, 0), 20 }
|
|
||||||
};
|
|
||||||
|
|
||||||
REG isbc202_reg[] = {
|
|
||||||
{ HRDATA (STAT0, fdc202[0].stat, 8) }, /* isbc202 0 status */
|
|
||||||
{ HRDATA (RTYP0, fdc202[0].rtype, 8) }, /* isbc202 0 result type */
|
|
||||||
{ HRDATA (RBYT0A, fdc202[0].rbyte0, 8) }, /* isbc202 0 result byte 0 */
|
|
||||||
{ HRDATA (RBYT0B, fdc202[0].rbyte1, 8) }, /* isbc202 0 result byte 1 */
|
|
||||||
{ HRDATA (INTFF0, fdc202[0].intff, 8) }, /* isbc202 0 interrupt f/f */
|
|
||||||
{ HRDATA (STAT1, fdc202[1].stat, 8) }, /* isbc202 1 status */
|
|
||||||
{ HRDATA (RTYP1, fdc202[1].rtype, 8) }, /* isbc202 1 result type */
|
|
||||||
{ HRDATA (RBYT1A, fdc202[1].rbyte0, 8) }, /* isbc202 1 result byte 0 */
|
|
||||||
{ HRDATA (RBYT1B, fdc202[1].rbyte1, 8) }, /* isbc202 1 result byte 1 */
|
|
||||||
{ HRDATA (INTFF1, fdc202[1].intff, 8) }, /* isbc202 1 interrupt f/f */
|
|
||||||
{ HRDATA (STAT2, fdc202[2].stat, 8) }, /* isbc202 2 status */
|
|
||||||
{ HRDATA (RTYP2, fdc202[2].rtype, 8) }, /* isbc202 2 result type */
|
|
||||||
{ HRDATA (RBYT2A, fdc202[2].rbyte0, 8) }, /* isbc202 2 result byte 0 */
|
|
||||||
{ HRDATA (RBYT2B, fdc202[2].rbyte1, 8) }, /* isbc202 2 result byte 1 */
|
|
||||||
{ HRDATA (INTFF2, fdc202[2].intff, 8) }, /* isbc202 2 interrupt f/f */
|
|
||||||
{ HRDATA (STAT3, fdc202[3].stat, 8) }, /* isbc202 3 status */
|
|
||||||
{ HRDATA (RTYP3, fdc202[3].rtype, 8) }, /* isbc202 3 result type */
|
|
||||||
{ HRDATA (RBYT3A, fdc202[3].rbyte0, 8) }, /* isbc202 3 result byte 0 */
|
|
||||||
{ HRDATA (RBYT3B, fdc202[3].rbyte1, 8) }, /* isbc202 3 result byte 1 */
|
|
||||||
{ HRDATA (INTFF3, fdc202[3].intff, 8) }, /* isbc202 3 interrupt f/f */
|
|
||||||
{ NULL }
|
|
||||||
};
|
|
||||||
|
|
||||||
MTAB isbc202_mod[] = {
|
|
||||||
{ UNIT_WPMODE, 0, "RW", "RW", &isbc202_set_mode },
|
|
||||||
{ UNIT_WPMODE, UNIT_WPMODE, "WP", "WP", &isbc202_set_mode },
|
|
||||||
{ 0 }
|
|
||||||
};
|
|
||||||
|
|
||||||
DEBTAB isbc202_debug[] = {
|
|
||||||
{ "ALL", DEBUG_all },
|
|
||||||
{ "FLOW", DEBUG_flow },
|
|
||||||
{ "READ", DEBUG_read },
|
|
||||||
{ "WRITE", DEBUG_write },
|
|
||||||
{ "XACK", DEBUG_xack },
|
|
||||||
{ "LEV1", DEBUG_level1 },
|
|
||||||
{ "LEV2", DEBUG_level2 },
|
|
||||||
{ NULL }
|
|
||||||
};
|
|
||||||
|
|
||||||
/* address width is set to 16 bits to use devices in 8086/8088 implementations */
|
|
||||||
|
|
||||||
DEVICE isbc202_dev = {
|
|
||||||
"SBC202", //name
|
|
||||||
isbc202_unit, //units
|
|
||||||
isbc202_reg, //registers
|
|
||||||
isbc202_mod, //modifiers
|
|
||||||
FDD_NUM, //numunits
|
|
||||||
16, //aradix
|
|
||||||
16, //awidth
|
|
||||||
1, //aincr
|
|
||||||
16, //dradix
|
|
||||||
8, //dwidth
|
|
||||||
NULL, //examine
|
|
||||||
NULL, //deposit
|
|
||||||
NULL, //reset
|
|
||||||
NULL, //boot
|
|
||||||
&isbc202_attach, //attach
|
|
||||||
NULL, //detach
|
|
||||||
NULL, //ctxt
|
|
||||||
DEV_DEBUG+DEV_DISABLE+DEV_DIS, //flags
|
|
||||||
DEBUG_flow + DEBUG_read + DEBUG_write, //dctrl
|
|
||||||
isbc202_debug, //debflags
|
|
||||||
NULL, //msize
|
|
||||||
NULL //lname
|
|
||||||
};
|
|
||||||
|
|
||||||
/* Hardware reset routine */
|
|
||||||
|
|
||||||
t_stat isbc202_reset(DEVICE *dptr, uint16 base)
|
|
||||||
{
|
|
||||||
int32 i;
|
|
||||||
UNIT *uptr;
|
|
||||||
|
|
||||||
sim_printf(" iSBC-202 FDC Board");
|
|
||||||
if (SBC202_NUM) {
|
|
||||||
sim_printf(" - Found\n");
|
|
||||||
sim_printf(" isbc202-%d: Hardware Reset\n", isbc202_fdcnum);
|
|
||||||
sim_printf(" isbc202-%d: Registered at %04X\n", isbc202_fdcnum, base);
|
|
||||||
//register base port address for this FDC instance
|
|
||||||
fdc202[isbc202_fdcnum].baseport = base;
|
|
||||||
//register I/O port addresses for each function
|
|
||||||
reg_dev(isbc2020, base, isbc202_fdcnum); //read status
|
|
||||||
reg_dev(isbc2021, base + 1, isbc202_fdcnum); //read rslt type/write IOPB addr-l
|
|
||||||
reg_dev(isbc2022, base + 2, isbc202_fdcnum); //write IOPB addr-h and start
|
|
||||||
reg_dev(isbc2023, base + 3, isbc202_fdcnum); //read rstl byte
|
|
||||||
reg_dev(isbc2027, base + 7, isbc202_fdcnum); //write reset isbc202
|
|
||||||
// one-time initialization for all FDDs for this FDC instance
|
|
||||||
for (i = 0; i < FDD_NUM; i++) {
|
|
||||||
uptr = isbc202_dev.units + i;
|
|
||||||
uptr->u5 = isbc202_fdcnum; //fdc device number
|
|
||||||
uptr->u6 = i; //fdd unit number
|
|
||||||
uptr->flags |= UNIT_WPMODE; //set WP in unit flags
|
|
||||||
}
|
|
||||||
isbc202_reset1(isbc202_fdcnum); //software reset
|
|
||||||
isbc202_fdcnum++; //next FDC instance
|
|
||||||
} else
|
|
||||||
sim_printf(" - Not Found\n");
|
|
||||||
return SCPE_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Software reset routine */
|
|
||||||
|
|
||||||
void isbc202_reset1(uint8 fdcnum)
|
|
||||||
{
|
|
||||||
int32 i;
|
|
||||||
UNIT *uptr;
|
|
||||||
|
|
||||||
sim_printf(" isbc202-%d: Software Reset\n", fdcnum);
|
|
||||||
fdc202[fdcnum].stat = 0; //clear status
|
|
||||||
for (i = 0; i < FDD_NUM; i++) { /* handle all FDDs */
|
|
||||||
uptr = isbc202_dev.units + i;
|
|
||||||
fdc202[fdcnum].stat |= FDCPRE | FDCDD; //set the FDC status
|
|
||||||
fdc202[fdcnum].rtype = ROK;
|
|
||||||
// sim_printf("FDD %d uptr->capac=%d\n", i, uptr->capac);
|
|
||||||
if (uptr->capac == 0) { /* if not configured */
|
|
||||||
sim_printf(" SBC202%d: Configured, FDC Status=%02X Not attached\n", i, fdc202[fdcnum].stat);
|
|
||||||
} else {
|
|
||||||
switch(i){
|
|
||||||
case 0:
|
|
||||||
fdc202[fdcnum].stat |= RDY0; //set FDD 0 ready
|
|
||||||
fdc202[fdcnum].rbyte1 |= RB1RD0;
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
fdc202[fdcnum].stat |= RDY1; //set FDD 1 ready
|
|
||||||
fdc202[fdcnum].rbyte1 |= RB1RD1;
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
fdc202[fdcnum].stat |= RDY2; //set FDD 2 ready
|
|
||||||
fdc202[fdcnum].rbyte1 |= RB1RD2;
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
fdc202[fdcnum].stat |= RDY3; //set FDD 3 ready
|
|
||||||
fdc202[fdcnum].rbyte1 |= RB1RD3;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
fdc202[fdcnum].rdychg = 0;
|
|
||||||
sim_printf(" SBC202%d: Configured, FDC Status=%02X Attached to %s\n",
|
|
||||||
i, fdc202[fdcnum].stat, uptr->filename);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* isbc202 attach - attach an .IMG file to a FDD */
|
|
||||||
|
|
||||||
t_stat isbc202_attach (UNIT *uptr, CONST char *cptr)
|
|
||||||
{
|
|
||||||
t_stat r;
|
|
||||||
uint8 fdcnum, fddnum;
|
|
||||||
|
|
||||||
sim_debug (DEBUG_flow, &isbc202_dev, " isbc202_attach: Entered with cptr=%s\n", cptr);
|
|
||||||
if ((r = attach_unit (uptr, cptr)) != SCPE_OK) {
|
|
||||||
sim_printf(" isbc202_attach: Attach error\n");
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
fdcnum = uptr->u5;
|
|
||||||
fddnum = uptr->u6;
|
|
||||||
uptr->capac = MDSDD;
|
|
||||||
switch(fddnum){
|
|
||||||
case 0:
|
|
||||||
fdc202[fdcnum].stat |= RDY0; //set FDD 0 ready
|
|
||||||
fdc202[fdcnum].rbyte1 |= RB1RD0;
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
fdc202[fdcnum].stat |= RDY1; //set FDD 1 ready
|
|
||||||
fdc202[fdcnum].rbyte1 |= RB1RD1;
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
fdc202[fdcnum].stat |= RDY2; //set FDD 2 ready
|
|
||||||
fdc202[fdcnum].rbyte1 |= RB1RD2;
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
fdc202[fdcnum].stat |= RDY3; //set FDD 3 ready
|
|
||||||
fdc202[fdcnum].rbyte1 |= RB1RD3;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
fdc202[fdcnum].rtype = ROK;
|
|
||||||
sim_printf(" iSBC-202%d: FDD: %d Configured %d bytes, Attached to %s\n",
|
|
||||||
fdcnum, fddnum, uptr->capac, uptr->filename);
|
|
||||||
sim_debug (DEBUG_flow, &isbc202_dev, " isbc202_attach: Done\n");
|
|
||||||
return SCPE_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* isbc202 set mode = Write protect */
|
|
||||||
|
|
||||||
t_stat isbc202_set_mode (UNIT *uptr, int32 val, CONST char *cptr, void *desc)
|
|
||||||
{
|
|
||||||
sim_debug (DEBUG_flow, &isbc202_dev, " isbc202_set_mode: Entered with val=%08XH uptr->flags=%08X\n",
|
|
||||||
val, uptr->flags);
|
|
||||||
if (val & UNIT_WPMODE) { /* write protect */
|
|
||||||
uptr->flags |= val;
|
|
||||||
} else { /* read write */
|
|
||||||
uptr->flags &= ~val;
|
|
||||||
}
|
|
||||||
sim_debug (DEBUG_flow, &isbc202_dev, " isbc202_set_mode: Done\n");
|
|
||||||
return SCPE_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8 isbc202_get_dn(void)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i=0; i<SBC202_NUM; i++)
|
|
||||||
if (port >= fdc202[i].baseport && port <= fdc202[i].baseport + 7)
|
|
||||||
return i;
|
|
||||||
sim_printf("isbc202_get_dn: port %04X not in isbc202 device table\n", port);
|
|
||||||
return 0xFF;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ISBC202 control port functions */
|
|
||||||
|
|
||||||
uint8 isbc2020(t_bool io, uint8 data)
|
|
||||||
{
|
|
||||||
uint8 fdcnum;
|
|
||||||
|
|
||||||
if ((fdcnum = isbc202_get_dn()) != 0xFF) {
|
|
||||||
if (io == 0) { /* read ststus*/
|
|
||||||
if (DEBUG)
|
|
||||||
sim_printf("\n isbc202-%d: 0x78 returned status=%02X PCX=%04X",
|
|
||||||
fdcnum, fdc202[fdcnum].stat, PCX);
|
|
||||||
return fdc202[fdcnum].stat;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8 isbc2021(t_bool io, uint8 data)
|
|
||||||
{
|
|
||||||
uint8 fdcnum;
|
|
||||||
|
|
||||||
if ((fdcnum = isbc202_get_dn()) != 0xFF) {
|
|
||||||
if (io == 0) { /* read data port */
|
|
||||||
fdc202[fdcnum].intff = 0; //clear interrupt FF
|
|
||||||
fdc202[fdcnum].stat &= ~FDCINT;
|
|
||||||
if (DEBUG)
|
|
||||||
sim_printf("\n isbc202-%d: 0x79 returned rtype=%02X intff=%02X status=%02X PCX=%04X",
|
|
||||||
fdcnum, fdc202[fdcnum].rtype, fdc202[fdcnum].intff, fdc202[fdcnum].stat, PCX);
|
|
||||||
return fdc202[fdcnum].rtype;
|
|
||||||
} else { /* write data port */
|
|
||||||
fdc202[fdcnum].iopb = data;
|
|
||||||
if (DEBUG)
|
|
||||||
sim_printf("\n isbc202-%d: 0x79 IOPB low=%02X PCX=%04X",
|
|
||||||
fdcnum, data, PCX);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8 isbc2022(t_bool io, uint8 data)
|
|
||||||
{
|
|
||||||
uint8 fdcnum;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
if ((fdcnum = isbc202_get_dn()) != 0xFF) {
|
|
||||||
if (io == 0) { /* read data port */
|
|
||||||
;
|
|
||||||
} else { /* write data port */
|
|
||||||
fdc202[fdcnum].iopb |= (data << 8);
|
|
||||||
// if (DEBUG)
|
|
||||||
sim_printf("\n isbc202-%d: 0x7A IOPB=%04X PCX=%04X",
|
|
||||||
fdcnum, fdc202[fdcnum].iopb, PCX);
|
|
||||||
sim_printf("\nIOPB: ");
|
|
||||||
for (i=0; i<7; i++)
|
|
||||||
sim_printf("%02X ", multibus_get_mbyte(fdc202[fdcnum].iopb + i));
|
|
||||||
sim_printf("\n");
|
|
||||||
isbc202_diskio(fdcnum);
|
|
||||||
if (fdc202[fdcnum].intff)
|
|
||||||
fdc202[fdcnum].stat |= FDCINT;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8 isbc2023(t_bool io, uint8 data)
|
|
||||||
{
|
|
||||||
uint8 fdcnum;
|
|
||||||
|
|
||||||
if ((fdcnum = isbc202_get_dn()) != 0xFF) {
|
|
||||||
if (io == 0) { /* read data port */
|
|
||||||
if (fdc202[fdcnum].rtype == 0) {
|
|
||||||
if (DEBUG)
|
|
||||||
sim_printf("\n isbc202-%d: 0x7B returned rbyte0=%02X PCX=%04X",
|
|
||||||
fdcnum, fdc202[fdcnum].rbyte0, PCX);
|
|
||||||
return fdc202[fdcnum].rbyte0;
|
|
||||||
} else {
|
|
||||||
if (fdc202[fdcnum].rdychg) {
|
|
||||||
if (DEBUG)
|
|
||||||
sim_printf("\n isbc202-%d: 0x7B returned rbyte1=%02X PCX=%04X",
|
|
||||||
fdcnum, fdc202[fdcnum].rbyte1, PCX);
|
|
||||||
return fdc202[fdcnum].rbyte1;
|
|
||||||
} else {
|
|
||||||
if (DEBUG)
|
|
||||||
sim_printf("\n isbc202-%d: 0x7B returned rbytex=%02X PCX=%04X",
|
|
||||||
fdcnum, 0, PCX);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else { /* write data port */
|
|
||||||
; //stop diskette operation
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8 isbc2027(t_bool io, uint8 data)
|
|
||||||
{
|
|
||||||
uint8 fdcnum;
|
|
||||||
|
|
||||||
if ((fdcnum = isbc202_get_dn()) != 0xFF) {
|
|
||||||
if (io == 0) { /* read data port */
|
|
||||||
;
|
|
||||||
} else { /* write data port */
|
|
||||||
isbc202_reset1(fdcnum);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// perform the actual disk I/O operation
|
|
||||||
|
|
||||||
void isbc202_diskio(uint8 fdcnum)
|
|
||||||
{
|
|
||||||
uint8 cw, di, nr, ta, sa, data, nrptr;
|
|
||||||
uint16 ba;
|
|
||||||
uint32 dskoff;
|
|
||||||
uint8 fddnum, fmtb;
|
|
||||||
uint32 i;
|
|
||||||
UNIT *uptr;
|
|
||||||
uint8 *fbuf = (uint8 *) (isbc202_dev.units + fddnum)->filebuf;
|
|
||||||
|
|
||||||
//parse the IOPB
|
|
||||||
cw = multibus_get_mbyte(fdc202[fdcnum].iopb);
|
|
||||||
di = multibus_get_mbyte(fdc202[fdcnum].iopb + 1);
|
|
||||||
nr = multibus_get_mbyte(fdc202[fdcnum].iopb + 2);
|
|
||||||
ta = multibus_get_mbyte(fdc202[fdcnum].iopb + 3);
|
|
||||||
sa = multibus_get_mbyte(fdc202[fdcnum].iopb + 4);
|
|
||||||
ba = multibus_get_mword(fdc202[fdcnum].iopb + 5);
|
|
||||||
fddnum = (di & 0x30) >> 4;
|
|
||||||
uptr = isbc202_dev.units + fddnum;
|
|
||||||
if (DEBUG) {
|
|
||||||
sim_printf("\n isbc202-%d: isbc202_diskio IOPB=%04X FDD=%02X STAT=%02X",
|
|
||||||
fdcnum, fdc202[fdcnum].iopb, fddnum, fdc202[fdcnum].stat);
|
|
||||||
sim_printf("\n isbc202-%d: cw=%02X di=%02X nr=%02X ta=%02X sa=%02X ba=%04X",
|
|
||||||
fdcnum, cw, di, nr, ta, sa, ba);
|
|
||||||
}
|
|
||||||
//check for not ready
|
|
||||||
switch(fddnum) {
|
|
||||||
case 0:
|
|
||||||
if ((fdc202[fdcnum].stat & RDY0) == 0) {
|
|
||||||
fdc202[fdcnum].rtype = RERR;
|
|
||||||
fdc202[fdcnum].rbyte0 = RB0NR;
|
|
||||||
fdc202[fdcnum].intff = 1; //set interrupt FF
|
|
||||||
sim_printf("\n isbc202-%d: Ready error on drive %d", fdcnum, fddnum);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
if ((fdc202[fdcnum].stat & RDY1) == 0) {
|
|
||||||
fdc202[fdcnum].rtype = RERR;
|
|
||||||
fdc202[fdcnum].rbyte0 = RB0NR;
|
|
||||||
fdc202[fdcnum].intff = 1; //set interrupt FF
|
|
||||||
sim_printf("\n isbc202-%d: Ready error on drive %d", fdcnum, fddnum);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
if ((fdc202[fdcnum].stat & RDY2) == 0) {
|
|
||||||
fdc202[fdcnum].rtype = RERR;
|
|
||||||
fdc202[fdcnum].rbyte0 = RB0NR;
|
|
||||||
fdc202[fdcnum].intff = 1; //set interrupt FF
|
|
||||||
sim_printf("\n isbc202-%d: Ready error on drive %d", fdcnum, fddnum);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
if ((fdc202[fdcnum].stat & RDY3) == 0) {
|
|
||||||
fdc202[fdcnum].rtype = RERR;
|
|
||||||
fdc202[fdcnum].rbyte0 = RB0NR;
|
|
||||||
fdc202[fdcnum].intff = 1; //set interrupt FF
|
|
||||||
sim_printf("\n isbc202-%d: Ready error on drive %d", fdcnum, fddnum);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
//check for address error
|
|
||||||
if (
|
|
||||||
((di & 0x07) != DHOME) && (
|
|
||||||
(sa > MAXSECDD) ||
|
|
||||||
((sa + nr) > (MAXSECDD + 1)) ||
|
|
||||||
(sa == 0) ||
|
|
||||||
(ta > MAXTRK)
|
|
||||||
)) {
|
|
||||||
fdc202[fdcnum].rtype = RERR;
|
|
||||||
fdc202[fdcnum].rbyte0 = RB0ADR;
|
|
||||||
fdc202[fdcnum].intff = 1; //set interrupt FF
|
|
||||||
sim_printf("\n isbc202-%d: Address error on drive %d", fdcnum, fddnum);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
switch (di & 0x07) { //decode disk command
|
|
||||||
case DNOP:
|
|
||||||
fdc202[fdcnum].rtype = ROK;
|
|
||||||
fdc202[fdcnum].intff = 1; //set interrupt FF
|
|
||||||
break;
|
|
||||||
case DSEEK:
|
|
||||||
fdc202[fdcnum].fdd[fddnum].sec = sa;
|
|
||||||
fdc202[fdcnum].fdd[fddnum].cyl = ta;
|
|
||||||
fdc202[fdcnum].rtype = ROK;
|
|
||||||
fdc202[fdcnum].intff = 1; //set interrupt FF
|
|
||||||
break;
|
|
||||||
case DHOME:
|
|
||||||
fdc202[fdcnum].fdd[fddnum].sec = sa;
|
|
||||||
fdc202[fdcnum].fdd[fddnum].cyl = 0;
|
|
||||||
fdc202[fdcnum].rtype = ROK;
|
|
||||||
fdc202[fdcnum].intff = 1; //set interrupt FF
|
|
||||||
break;
|
|
||||||
case DVCRC:
|
|
||||||
fdc202[fdcnum].rtype = ROK;
|
|
||||||
fdc202[fdcnum].intff = 1; //set interrupt FF
|
|
||||||
break;
|
|
||||||
case DFMT:
|
|
||||||
//check for WP
|
|
||||||
if(uptr->flags & UNIT_WPMODE) {
|
|
||||||
fdc202[fdcnum].rtype = RERR;
|
|
||||||
fdc202[fdcnum].rbyte0 = RB0WP;
|
|
||||||
fdc202[fdcnum].intff = 1; //set interrupt FF
|
|
||||||
sim_printf("\n isbc202-%d: Write protect error 1 on drive %d", fdcnum, fddnum);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
fmtb = multibus_get_mbyte(ba); //get the format byte
|
|
||||||
//calculate offset into disk image
|
|
||||||
dskoff = ((ta * MAXSECDD) + (sa - 1)) * 128;
|
|
||||||
for(i=0; i<=((uint32)(MAXSECDD) * 128); i++) {
|
|
||||||
*(fbuf + (dskoff + i)) = fmtb;
|
|
||||||
}
|
|
||||||
fdc202[fdcnum].rtype = ROK;
|
|
||||||
fdc202[fdcnum].intff = 1; //set interrupt FF
|
|
||||||
break;
|
|
||||||
case DREAD:
|
|
||||||
nrptr = 0;
|
|
||||||
while(nrptr < nr) {
|
|
||||||
//calculate offset into disk image
|
|
||||||
dskoff = ((ta * MAXSECDD) + (sa - 1)) * 128;
|
|
||||||
// if (DEBUG)
|
|
||||||
sim_printf("\n isbc202-%d: cw=%02X di=%02X nr=%02X ta=%02X sa=%02X ba=%04X dskoff=%06X",
|
|
||||||
fdcnum, cw, di, nr, ta, sa, ba, dskoff);
|
|
||||||
for (i=0; i<128; i++) { //copy sector from image to RAM
|
|
||||||
data = *(fbuf + (dskoff + i));
|
|
||||||
multibus_put_mbyte(ba + i, data);
|
|
||||||
}
|
|
||||||
sa++;
|
|
||||||
ba+=0x80;
|
|
||||||
nrptr++;
|
|
||||||
}
|
|
||||||
fdc202[fdcnum].rtype = ROK;
|
|
||||||
fdc202[fdcnum].intff = 1; //set interrupt FF
|
|
||||||
break;
|
|
||||||
case DWRITE:
|
|
||||||
//check for WP
|
|
||||||
if(uptr->flags & UNIT_WPMODE) {
|
|
||||||
fdc202[fdcnum].rtype = RERR;
|
|
||||||
fdc202[fdcnum].rbyte0 = RB0WP;
|
|
||||||
fdc202[fdcnum].intff = 1; //set interrupt FF
|
|
||||||
sim_printf("\n isbc202-%d: Write protect error 2 on drive %d", fdcnum, fddnum);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
nrptr = 0;
|
|
||||||
while(nrptr < nr) {
|
|
||||||
//calculate offset into disk image
|
|
||||||
dskoff = ((ta * MAXSECDD) + (sa - 1)) * 128;
|
|
||||||
// if (DEBUG)
|
|
||||||
// sim_printf("\n isbc202-%d: cw=%02X di=%02X nr=%02X ta=%02X sa=%02X ba=%04X dskoff=%06X",
|
|
||||||
// fdcnum, cw, di, nr, ta, sa, ba, dskoff);
|
|
||||||
for (i=0; i<128; i++) { //copy sector from image to RAM
|
|
||||||
data = multibus_get_mbyte(ba + i);
|
|
||||||
*(fbuf + (dskoff + i)) = data;
|
|
||||||
}
|
|
||||||
sa++;
|
|
||||||
ba+=0x80;
|
|
||||||
nrptr++;
|
|
||||||
}
|
|
||||||
fdc202[fdcnum].rtype = ROK;
|
|
||||||
fdc202[fdcnum].intff = 1; //set interrupt FF
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
sim_printf("\n isbc202-%d: isbc202_diskio bad di=%02X", fdcnum, di & 0x07);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* end of isbc202.c */
|
|
|
@ -143,7 +143,7 @@ t_stat multibus_svc(UNIT *uptr)
|
||||||
t_stat multibus_reset(DEVICE *dptr)
|
t_stat multibus_reset(DEVICE *dptr)
|
||||||
{
|
{
|
||||||
SBC_reset(NULL);
|
SBC_reset(NULL);
|
||||||
sim_printf("Initializing The Multibus\n Multibus Boards:\n");
|
sim_printf(" Multibus: Reset\n");
|
||||||
isbc064_reset(NULL);
|
isbc064_reset(NULL);
|
||||||
isbc201_fdcnum = 0;
|
isbc201_fdcnum = 0;
|
||||||
isbc201_reset(NULL, SBC201_BASE);
|
isbc201_reset(NULL, SBC201_BASE);
|
||||||
|
|
|
@ -127,7 +127,7 @@
|
||||||
|
|
||||||
u3 -
|
u3 -
|
||||||
u4 -
|
u4 -
|
||||||
u5 - fdc number.
|
u5 - fdc number (board instance number).
|
||||||
u6 - fdd number.
|
u6 - fdd number.
|
||||||
|
|
||||||
The ZX-200A appears to the multibus system as if there were an iSBC-201
|
The ZX-200A appears to the multibus system as if there were an iSBC-201
|
||||||
|
@ -184,6 +184,13 @@
|
||||||
#define RB1RD0 0x40 //drive 0 ready
|
#define RB1RD0 0x40 //drive 0 ready
|
||||||
#define RB1RD1 0x80 //drive 1 ready
|
#define RB1RD1 0x80 //drive 1 ready
|
||||||
|
|
||||||
|
//disk geometry values
|
||||||
|
#define MDSSD 256256 //single density FDD size
|
||||||
|
#define MDSDD 512512 //double density FDD size
|
||||||
|
#define MAXSECSD 26 //single density last sector
|
||||||
|
#define MAXSECDD 52 //double density last sector
|
||||||
|
#define MAXTRK 76 //last track
|
||||||
|
|
||||||
/* external function prototypes */
|
/* external function prototypes */
|
||||||
|
|
||||||
extern uint16 reg_dev(uint8 (*routine)(t_bool, uint8), uint16, uint8);
|
extern uint16 reg_dev(uint8 (*routine)(t_bool, uint8), uint16, uint8);
|
||||||
|
@ -215,13 +222,14 @@ void zx200a_diskio(uint8 fdcnum);
|
||||||
int32 zx200a_fdcnum = 0; //actual number of ZX-200A instances + 1
|
int32 zx200a_fdcnum = 0; //actual number of ZX-200A instances + 1
|
||||||
|
|
||||||
typedef struct { //FDD definition
|
typedef struct { //FDD definition
|
||||||
uint8 *buf;
|
// uint8 *buf;
|
||||||
int t0;
|
int t0;
|
||||||
int rdy;
|
int rdy;
|
||||||
uint8 sec;
|
uint8 sec;
|
||||||
uint8 cyl;
|
uint8 cyl;
|
||||||
uint8 maxsec;
|
uint8 dd;
|
||||||
uint8 maxcyl;
|
// uint8 maxsec;
|
||||||
|
// uint8 maxcyl;
|
||||||
} FDDDEF;
|
} FDDDEF;
|
||||||
|
|
||||||
typedef struct { //FDC definition
|
typedef struct { //FDC definition
|
||||||
|
@ -236,13 +244,13 @@ typedef struct { //FDC definition
|
||||||
FDDDEF fdd[FDD_NUM]; //indexed by the FDD number
|
FDDDEF fdd[FDD_NUM]; //indexed by the FDD number
|
||||||
} FDCDEF;
|
} FDCDEF;
|
||||||
|
|
||||||
FDCDEF zx200a[4]; //indexed by the isbc-202 instance number
|
FDCDEF zx200a[4]; //indexed by the zx200a instance number
|
||||||
|
|
||||||
UNIT zx200a_unit[] = {
|
UNIT zx200a_unit[] = {
|
||||||
{ UDATA (0, UNIT_ATTABLE+UNIT_DISABLE, 0), 20 },
|
{ UDATA (0, UNIT_ATTABLE+UNIT_DISABLE+UNIT_BUFABLE+UNIT_MUSTBUF, MDSDD), 20 },
|
||||||
{ UDATA (0, UNIT_ATTABLE+UNIT_DISABLE, 0), 20 },
|
{ UDATA (0, UNIT_ATTABLE+UNIT_DISABLE+UNIT_BUFABLE+UNIT_MUSTBUF, MDSDD), 20 },
|
||||||
{ UDATA (0, UNIT_ATTABLE+UNIT_DISABLE, 0), 20 },
|
{ UDATA (0, UNIT_ATTABLE+UNIT_DISABLE+UNIT_BUFABLE+UNIT_MUSTBUF, MDSDD), 20 },
|
||||||
{ UDATA (0, UNIT_ATTABLE+UNIT_DISABLE, 0), 20 }
|
{ UDATA (0, UNIT_ATTABLE+UNIT_DISABLE+UNIT_BUFABLE+UNIT_MUSTBUF, MDSDD), 20 }
|
||||||
};
|
};
|
||||||
|
|
||||||
REG zx200a_reg[] = {
|
REG zx200a_reg[] = {
|
||||||
|
@ -259,13 +267,13 @@ REG zx200a_reg[] = {
|
||||||
{ HRDATA (STAT2, zx200a[2].stat, 8) }, /* zx200a 2 status */
|
{ HRDATA (STAT2, zx200a[2].stat, 8) }, /* zx200a 2 status */
|
||||||
{ HRDATA (RTYP2, zx200a[2].rtype, 8) }, /* zx200a 2 result type */
|
{ HRDATA (RTYP2, zx200a[2].rtype, 8) }, /* zx200a 2 result type */
|
||||||
{ HRDATA (RBYT2A, zx200a[2].rbyte0, 8) }, /* zx200a 2 result byte 0 */
|
{ HRDATA (RBYT2A, zx200a[2].rbyte0, 8) }, /* zx200a 2 result byte 0 */
|
||||||
{ HRDATA (RBYT2B, zx200a[0].rbyte1, 8) }, /* zx200a 2 result byte 1 */
|
{ HRDATA (RBYT2B, zx200a[2].rbyte1, 8) }, /* zx200a 2 result byte 1 */
|
||||||
{ HRDATA (INTFF2, zx200a[2].intff, 8) }, /* zx200a 2 interrupt f/f */
|
{ HRDATA (INTFF2, zx200a[2].intff, 8) }, /* zx200a 2 interrupt f/f */
|
||||||
{ HRDATA (STAT3, zx200a[3].stat, 8) }, /* zx200a 3 status */
|
{ HRDATA (STAT3, zx200a[3].stat, 8) }, /* zx200a 3 status */
|
||||||
{ HRDATA (RTYP3, zx200a[3].rtype, 8) }, /* zx200a 3 result type */
|
{ HRDATA (RTYP3, zx200a[3].rtype, 8) }, /* zx200a 3 result type */
|
||||||
{ HRDATA (RBYT3A, zx200a[3].rbyte0, 8) }, /* zx200a 3 result byte 0 */
|
{ HRDATA (RBYT3A, zx200a[3].rbyte0, 8) }, /* zx200a 3 result byte 0 */
|
||||||
{ HRDATA (RBYT3B, zx200a[3].rbyte1, 8) }, /* zx200a 3 result byte 1 */
|
{ HRDATA (RBYT3B, zx200a[3].rbyte1, 8) }, /* zx200a 3 result byte 1 */
|
||||||
{ HRDATA (INTFF3, zx200a[0].intff, 8) }, /* zx200a 3 interrupt f/f */
|
{ HRDATA (INTFF3, zx200a[3].intff, 8) }, /* zx200a 3 interrupt f/f */
|
||||||
{ NULL }
|
{ NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -323,12 +331,17 @@ DEVICE zx200a_dev = {
|
||||||
|
|
||||||
t_stat zx200a_reset(DEVICE *dptr, uint16 base)
|
t_stat zx200a_reset(DEVICE *dptr, uint16 base)
|
||||||
{
|
{
|
||||||
|
int32 i;
|
||||||
|
UNIT *uptr;
|
||||||
|
|
||||||
sim_printf(" ZX-200A FDC Board");
|
sim_printf(" ZX-200A FDC Board");
|
||||||
if (ZX200A_NUM) {
|
if (ZX200A_NUM) {
|
||||||
sim_printf(" - Found on Port %02X\n", base);
|
sim_printf(" - Found on Port %02X\n", base);
|
||||||
sim_printf(" ZX200A-%d: Hardware Reset\n", zx200a_fdcnum);
|
sim_printf(" ZX200A-%d: Hardware Reset\n", zx200a_fdcnum);
|
||||||
sim_printf(" ZX200A-%d: Registered at %04X\n", zx200a_fdcnum, base);
|
sim_printf(" ZX200A-%d: Registered at %04X\n", zx200a_fdcnum, base);
|
||||||
|
//register base port address for this FDC instance
|
||||||
zx200a[zx200a_fdcnum].baseport = base;
|
zx200a[zx200a_fdcnum].baseport = base;
|
||||||
|
//register I/O port addresses for each function
|
||||||
reg_dev(zx200a0, base, zx200a_fdcnum);
|
reg_dev(zx200a0, base, zx200a_fdcnum);
|
||||||
reg_dev(zx200a1, base + 1, zx200a_fdcnum);
|
reg_dev(zx200a1, base + 1, zx200a_fdcnum);
|
||||||
reg_dev(zx200a2, base + 2, zx200a_fdcnum);
|
reg_dev(zx200a2, base + 2, zx200a_fdcnum);
|
||||||
|
@ -339,10 +352,17 @@ t_stat zx200a_reset(DEVICE *dptr, uint16 base)
|
||||||
reg_dev(zx200a2, base+16 + 2, zx200a_fdcnum);
|
reg_dev(zx200a2, base+16 + 2, zx200a_fdcnum);
|
||||||
reg_dev(zx200a3, base+16 + 3, zx200a_fdcnum);
|
reg_dev(zx200a3, base+16 + 3, zx200a_fdcnum);
|
||||||
reg_dev(zx200a7, base+16 + 7, zx200a_fdcnum);
|
reg_dev(zx200a7, base+16 + 7, zx200a_fdcnum);
|
||||||
|
// one-time initialization for all FDDs for this FDC instance
|
||||||
|
for (i = 0; i < FDD_NUM; i++) {
|
||||||
|
uptr = zx200a_dev.units + i;
|
||||||
|
uptr->u5 = zx200a_fdcnum; //fdc device number
|
||||||
|
uptr->u6 = i; //fdd unit number
|
||||||
|
uptr->flags |= UNIT_WPMODE; //set WP in unit flags
|
||||||
|
}
|
||||||
zx200a_reset1(zx200a_fdcnum);
|
zx200a_reset1(zx200a_fdcnum);
|
||||||
zx200a_fdcnum++;
|
zx200a_fdcnum++;
|
||||||
} else
|
} else
|
||||||
sim_printf(" - Not Found on Port %02X\n", base);
|
sim_printf(" - Not Found\n");
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
/* Software reset routine */
|
/* Software reset routine */
|
||||||
|
@ -359,33 +379,27 @@ void zx200a_reset1(uint8 fdcnum)
|
||||||
zx200a[fdcnum].stat |= FDCPRE | FDCDD; //set the FDC status
|
zx200a[fdcnum].stat |= FDCPRE | FDCDD; //set the FDC status
|
||||||
zx200a[fdcnum].rtype = ROK;
|
zx200a[fdcnum].rtype = ROK;
|
||||||
if (uptr->capac == 0) { /* if not configured */
|
if (uptr->capac == 0) { /* if not configured */
|
||||||
uptr->u5 = fdcnum; //fdc device number
|
|
||||||
uptr->u6 = i; /* unit number - only set here! */
|
|
||||||
uptr->flags |= UNIT_WPMODE; /* set WP in unit flags */
|
|
||||||
sim_printf(" ZX-200A%d: Configured, Status=%02X Not attached\n", i, zx200a[fdcnum].stat);
|
sim_printf(" ZX-200A%d: Configured, Status=%02X Not attached\n", i, zx200a[fdcnum].stat);
|
||||||
} else {
|
} else {
|
||||||
switch(i){
|
switch(i){
|
||||||
case 0:
|
case 0:
|
||||||
zx200a[fdcnum].stat |= RDY0; //set FDD 0 ready
|
zx200a[fdcnum].stat |= RDY0; //set FDD 0 ready
|
||||||
zx200a[fdcnum].rbyte1 |= RB1RD0;
|
zx200a[fdcnum].rbyte1 |= RB1RD0;
|
||||||
zx200a[fdcnum].rdychg = 0;
|
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
zx200a[fdcnum].stat |= RDY1; //set FDD 1 ready
|
zx200a[fdcnum].stat |= RDY1; //set FDD 1 ready
|
||||||
zx200a[fdcnum].rbyte1 |= RB1RD1;
|
zx200a[fdcnum].rbyte1 |= RB1RD1;
|
||||||
zx200a[fdcnum].rdychg = 0;
|
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
zx200a[fdcnum].stat |= RDY2; //set FDD 2 ready
|
zx200a[fdcnum].stat |= RDY2; //set FDD 2 ready
|
||||||
zx200a[fdcnum].rbyte1 |= RB1RD2;
|
zx200a[fdcnum].rbyte1 |= RB1RD2;
|
||||||
zx200a[fdcnum].rdychg = 0;
|
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
zx200a[fdcnum].stat |= RDY3; //set FDD 3 ready
|
zx200a[fdcnum].stat |= RDY3; //set FDD 3 ready
|
||||||
zx200a[fdcnum].rbyte1 |= RB1RD3;
|
zx200a[fdcnum].rbyte1 |= RB1RD3;
|
||||||
zx200a[fdcnum].rdychg = 0;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
zx200a[fdcnum].rdychg = 0;
|
||||||
sim_printf(" ZX-200A%d: Configured, Status=%02X Attached to %s\n",
|
sim_printf(" ZX-200A%d: Configured, Status=%02X Attached to %s\n",
|
||||||
i, zx200a[fdcnum].stat, uptr->filename);
|
i, zx200a[fdcnum].stat, uptr->filename);
|
||||||
}
|
}
|
||||||
|
@ -397,9 +411,6 @@ void zx200a_reset1(uint8 fdcnum)
|
||||||
t_stat zx200a_attach (UNIT *uptr, CONST char *cptr)
|
t_stat zx200a_attach (UNIT *uptr, CONST char *cptr)
|
||||||
{
|
{
|
||||||
t_stat r;
|
t_stat r;
|
||||||
FILE *fp;
|
|
||||||
int32 i, c = 0;
|
|
||||||
long flen;
|
|
||||||
uint8 fdcnum, fddnum;
|
uint8 fdcnum, fddnum;
|
||||||
|
|
||||||
sim_debug (DEBUG_flow, &zx200a_dev, " zx200a_attach: Entered with cptr=%s\n", cptr);
|
sim_debug (DEBUG_flow, &zx200a_dev, " zx200a_attach: Entered with cptr=%s\n", cptr);
|
||||||
|
@ -409,74 +420,42 @@ t_stat zx200a_attach (UNIT *uptr, CONST char *cptr)
|
||||||
}
|
}
|
||||||
fdcnum = uptr->u5;
|
fdcnum = uptr->u5;
|
||||||
fddnum = uptr->u6;
|
fddnum = uptr->u6;
|
||||||
fp = fopen(uptr->filename, "rb");
|
switch(fddnum){
|
||||||
if (fp == NULL) {
|
case 0:
|
||||||
sim_printf(" Unable to open disk image file %s\n", uptr->filename);
|
zx200a[fdcnum].stat |= RDY0; //set FDD 0 ready
|
||||||
sim_printf(" No disk image loaded!!!\n");
|
zx200a[fdcnum].rbyte1 |= RB1RD0;
|
||||||
} else {
|
break;
|
||||||
sim_printf("zx200a: Attach\n");
|
case 1:
|
||||||
fseek(fp, 0, SEEK_END); /* size disk image */
|
zx200a[fdcnum].stat |= RDY1; //set FDD 1 ready
|
||||||
flen = ftell(fp);
|
zx200a[fdcnum].rbyte1 |= RB1RD1;
|
||||||
fseek(fp, 0, SEEK_SET);
|
break;
|
||||||
if (flen == -1) {
|
case 2:
|
||||||
sim_printf(" zx200a_attach: File error\n");
|
zx200a[fdcnum].stat |= RDY2; //set FDD 2 ready
|
||||||
fclose(fp);
|
zx200a[fdcnum].rbyte1 |= RB1RD2;
|
||||||
return SCPE_IOERR;
|
break;
|
||||||
|
case 3:
|
||||||
|
zx200a[fdcnum].stat |= RDY3; //set FDD 3 ready
|
||||||
|
zx200a[fdcnum].rbyte1 |= RB1RD3;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
if (zx200a[fdcnum].fdd[fddnum].buf == NULL) { /* no buffer allocated */
|
zx200a[fdcnum].rtype = ROK;
|
||||||
zx200a[fdcnum].fdd[fddnum].buf = (uint8 *)malloc(flen);
|
if (uptr->capac == 256256 && (fddnum == 2 || fddnum == 3)) { /* 8" 256K SSSD */
|
||||||
if (zx200a[fdcnum].fdd[fddnum].buf == NULL) {
|
zx200a[fdcnum].fdd[fddnum].dd = 0;
|
||||||
sim_printf(" zx200a_attach: Malloc error\n");
|
// zx200a[fdcnum].fdd[fddnum].maxcyl = 77;
|
||||||
fclose(fp);
|
// zx200a[fdcnum].fdd[fddnum].maxsec = 26;
|
||||||
return SCPE_MEM;
|
zx200a[fdcnum].fdd[fddnum].sec = 1;
|
||||||
}
|
zx200a[fdcnum].fdd[fddnum].cyl = 0;
|
||||||
}
|
|
||||||
uptr->capac = flen;
|
|
||||||
i = 0;
|
|
||||||
c = fgetc(fp); // copy disk image into buffer
|
|
||||||
while (c != EOF) {
|
|
||||||
*(zx200a[fdcnum].fdd[fddnum].buf + i++) = c & 0xFF;
|
|
||||||
c = fgetc(fp);
|
|
||||||
}
|
|
||||||
fclose(fp);
|
|
||||||
switch(fddnum){
|
|
||||||
case 0:
|
|
||||||
zx200a[fdcnum].stat |= RDY0; //set FDD 0 ready
|
|
||||||
zx200a[fdcnum].rtype = ROK;
|
|
||||||
zx200a[fdcnum].rbyte1 |= RB1RD0;
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
zx200a[fdcnum].stat |= RDY1; //set FDD 1 ready
|
|
||||||
zx200a[fdcnum].rtype = ROK;
|
|
||||||
zx200a[fdcnum].rbyte1 |= RB1RD1;
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
zx200a[fdcnum].stat |= RDY2; //set FDD 2 ready
|
|
||||||
zx200a[fdcnum].rtype = ROK;
|
|
||||||
zx200a[fdcnum].rbyte1 |= RB1RD2;
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
zx200a[fdcnum].stat |= RDY3; //set FDD 3 ready
|
|
||||||
zx200a[fdcnum].rtype = ROK;
|
|
||||||
zx200a[fdcnum].rbyte1 |= RB1RD3;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (flen == 256256) { /* 8" 256K SSSD */
|
|
||||||
zx200a[fdcnum].fdd[fddnum].maxcyl = 77;
|
|
||||||
zx200a[fdcnum].fdd[fddnum].maxsec = 26;
|
|
||||||
zx200a[fdcnum].fdd[fddnum].sec = 1;
|
|
||||||
zx200a[fdcnum].fdd[fddnum].cyl = 0;
|
|
||||||
}
|
|
||||||
else if (flen == 512512) { /* 8" 512K SSDD */
|
|
||||||
zx200a[fdcnum].fdd[fddnum].maxcyl = 77;
|
|
||||||
zx200a[fdcnum].fdd[fddnum].maxsec = 52;
|
|
||||||
zx200a[fdcnum].fdd[fddnum].sec = 1;
|
|
||||||
zx200a[fdcnum].fdd[fddnum].cyl = 0;
|
|
||||||
} else
|
|
||||||
sim_printf(" ZX-200A-%d: Not a known disk image\n", fdcnum);
|
|
||||||
sim_printf(" ZX-200A-%d: Configured %d bytes, Attached to %s\n",
|
|
||||||
fdcnum, uptr->capac, uptr->filename);
|
|
||||||
}
|
}
|
||||||
|
else if (uptr->capac == 512512) { /* 8" 512K SSDD */
|
||||||
|
zx200a[fdcnum].fdd[fddnum].dd = 1;
|
||||||
|
// zx200a[fdcnum].fdd[fddnum].maxcyl = 77;
|
||||||
|
// zx200a[fdcnum].fdd[fddnum].maxsec = 52;
|
||||||
|
zx200a[fdcnum].fdd[fddnum].sec = 1;
|
||||||
|
zx200a[fdcnum].fdd[fddnum].cyl = 0;
|
||||||
|
} else
|
||||||
|
sim_printf(" ZX-200A-%d: Invalid disk image or SD on drive 0 or 1\n", fdcnum);
|
||||||
|
sim_printf(" ZX-200A-%d: Configured %d bytes, Attached to %s\n",
|
||||||
|
fdcnum, uptr->capac, uptr->filename);
|
||||||
sim_debug (DEBUG_flow, &zx200a_dev, " ZX-200A_attach: Done\n");
|
sim_debug (DEBUG_flow, &zx200a_dev, " ZX-200A_attach: Done\n");
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
@ -621,13 +600,14 @@ uint8 zx200a7(t_bool io, uint8 data)
|
||||||
|
|
||||||
void zx200a_diskio(uint8 fdcnum)
|
void zx200a_diskio(uint8 fdcnum)
|
||||||
{
|
{
|
||||||
uint8 cw, di, nr, ta, sa, data, nrptr, c;
|
uint8 cw, di, nr, ta, sa, data, nrptr;
|
||||||
uint16 ba;
|
uint16 ba;
|
||||||
uint32 dskoff;
|
uint32 dskoff;
|
||||||
uint8 fddnum, fmtb;
|
uint8 fddnum, fmtb;
|
||||||
uint32 i;
|
uint32 i;
|
||||||
UNIT *uptr;
|
UNIT *uptr;
|
||||||
FILE *fp;
|
uint8 *fbuf;
|
||||||
|
|
||||||
//parse the IOPB
|
//parse the IOPB
|
||||||
cw = multibus_get_mbyte(zx200a[fdcnum].iopb);
|
cw = multibus_get_mbyte(zx200a[fdcnum].iopb);
|
||||||
di = multibus_get_mbyte(zx200a[fdcnum].iopb + 1);
|
di = multibus_get_mbyte(zx200a[fdcnum].iopb + 1);
|
||||||
|
@ -637,13 +617,12 @@ void zx200a_diskio(uint8 fdcnum)
|
||||||
ba = multibus_get_mword(zx200a[fdcnum].iopb + 5);
|
ba = multibus_get_mword(zx200a[fdcnum].iopb + 5);
|
||||||
fddnum = (di & 0x30) >> 4;
|
fddnum = (di & 0x30) >> 4;
|
||||||
uptr = zx200a_dev.units + fddnum;
|
uptr = zx200a_dev.units + fddnum;
|
||||||
|
fbuf = (uint8 *) (zx200a_dev.units + fddnum)->filebuf;
|
||||||
if (DEBUG) {
|
if (DEBUG) {
|
||||||
sim_printf("\n zx200a-%d: zx200a_diskio IOPB=%04X FDD=%02X STAT=%02X",
|
sim_printf("\n zx200a-%d: zx200a_diskio IOPB=%04X FDD=%02X STAT=%02X",
|
||||||
fdcnum, zx200a[fdcnum].iopb, fddnum, zx200a[fdcnum].stat);
|
fdcnum, zx200a[fdcnum].iopb, fddnum, zx200a[fdcnum].stat);
|
||||||
sim_printf("\n zx200a-%d: cw=%02X di=%02X nr=%02X ta=%02X sa=%02X ba=%04X",
|
sim_printf("\n zx200a-%d: cw=%02X di=%02X nr=%02X ta=%02X sa=%02X ba=%04X",
|
||||||
fdcnum, cw, di, nr, ta, sa, ba);
|
fdcnum, cw, di, nr, ta, sa, ba);
|
||||||
// sim_printf("\n zx200a-%d: maxsec=%02X maxcyl=%02X",
|
|
||||||
// fdcnum, zx200a[fdcnum].fdd[fddnum].maxsec, zx200a[fdcnum].fdd[fddnum].maxcyl);
|
|
||||||
}
|
}
|
||||||
//check for not ready
|
//check for not ready
|
||||||
switch(fddnum) {
|
switch(fddnum) {
|
||||||
|
@ -685,26 +664,52 @@ void zx200a_diskio(uint8 fdcnum)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
//check for address error
|
//check for address error
|
||||||
if (
|
if (zx200a[fdcnum].fdd[fddnum].dd == 1) {
|
||||||
((di & 0x07) != 0x03) && (
|
if (
|
||||||
(sa > zx200a[fdcnum].fdd[fddnum].maxsec) ||
|
((di & 0x07) != DHOME) && (
|
||||||
((sa + nr) > (zx200a[fdcnum].fdd[fddnum].maxsec + 1)) ||
|
(sa > MAXSECDD) ||
|
||||||
(sa == 0) ||
|
((sa + nr) > (MAXSECDD + 1)) ||
|
||||||
(ta > zx200a[fdcnum].fdd[fddnum].maxcyl)
|
(sa == 0) ||
|
||||||
)) {
|
(ta > MAXTRK)
|
||||||
if (DEBUG)
|
)) {
|
||||||
sim_printf("\n zx200a-%d: maxsec=%02X maxcyl=%02X",
|
|
||||||
fdcnum, zx200a[fdcnum].fdd[fddnum].maxsec, zx200a[fdcnum].fdd[fddnum].maxcyl);
|
|
||||||
zx200a[fdcnum].rtype = RERR;
|
zx200a[fdcnum].rtype = RERR;
|
||||||
zx200a[fdcnum].rbyte0 = RB0ADR;
|
zx200a[fdcnum].rbyte0 = RB0ADR;
|
||||||
zx200a[fdcnum].intff = 1; //set interrupt FF
|
zx200a[fdcnum].intff = 1; //set interrupt FF
|
||||||
sim_printf("\n zx200a-%d: Address error on drive %d", fdcnum, fddnum);
|
sim_printf("\n zx200a-%d: Address error on drive %d", fdcnum, fddnum);
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
} else if (zx200a[fdcnum].fdd[fddnum].dd == 0) {
|
||||||
|
if (
|
||||||
|
((di & 0x07) != DHOME) && (
|
||||||
|
(sa > MAXSECSD) ||
|
||||||
|
((sa + nr) > (MAXSECSD + 1)) ||
|
||||||
|
(sa == 0) ||
|
||||||
|
(ta > MAXTRK)
|
||||||
|
)) {
|
||||||
|
zx200a[fdcnum].rtype = RERR;
|
||||||
|
zx200a[fdcnum].rbyte0 = RB0ADR;
|
||||||
|
zx200a[fdcnum].intff = 1; //set interrupt FF
|
||||||
|
sim_printf("\n zx200a-%d: Address error on drive %d", fdcnum, fddnum);
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
switch (di & 0x07) {
|
switch (di & 0x07) {
|
||||||
case DNOP:
|
case DNOP:
|
||||||
|
zx200a[fdcnum].rtype = ROK;
|
||||||
|
zx200a[fdcnum].intff = 1; //set interrupt FF
|
||||||
|
break;
|
||||||
case DSEEK:
|
case DSEEK:
|
||||||
|
zx200a[fdcnum].fdd[fddnum].sec = sa;
|
||||||
|
zx200a[fdcnum].fdd[fddnum].cyl = ta;
|
||||||
|
zx200a[fdcnum].rtype = ROK;
|
||||||
|
zx200a[fdcnum].intff = 1; //set interrupt FF
|
||||||
|
break;
|
||||||
case DHOME:
|
case DHOME:
|
||||||
|
zx200a[fdcnum].fdd[fddnum].sec = sa;
|
||||||
|
zx200a[fdcnum].fdd[fddnum].cyl = 0;
|
||||||
|
zx200a[fdcnum].rtype = ROK;
|
||||||
|
zx200a[fdcnum].intff = 1; //set interrupt FF
|
||||||
|
break;
|
||||||
case DVCRC:
|
case DVCRC:
|
||||||
zx200a[fdcnum].rtype = ROK;
|
zx200a[fdcnum].rtype = ROK;
|
||||||
zx200a[fdcnum].intff = 1; //set interrupt FF
|
zx200a[fdcnum].intff = 1; //set interrupt FF
|
||||||
|
@ -719,18 +724,19 @@ void zx200a_diskio(uint8 fdcnum)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
fmtb = multibus_get_mbyte(ba); //get the format byte
|
fmtb = multibus_get_mbyte(ba); //get the format byte
|
||||||
//calculate offset into disk image
|
if (zx200a[fdcnum].fdd[fddnum].dd == 1) {
|
||||||
dskoff = ((ta * (uint32)(zx200a[fdcnum].fdd[fddnum].maxsec)) + (sa - 1)) * 128;
|
//calculate offset into DD disk image
|
||||||
for(i=0; i<=((uint32)(zx200a[fdcnum].fdd[fddnum].maxsec) * 128); i++) {
|
dskoff = ((ta * MAXSECDD) + (sa - 1)) * 128;
|
||||||
*(zx200a[fdcnum].fdd[fddnum].buf + (dskoff + i)) = fmtb;
|
for(i=0; i<=((uint32)(MAXSECDD) * 128); i++) {
|
||||||
|
*(fbuf + (dskoff + i)) = fmtb;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
//calculate offset into SD disk image
|
||||||
|
dskoff = ((ta * MAXSECSD) + (sa - 1)) * 128;
|
||||||
|
for(i=0; i<=((uint32)(MAXSECSD) * 128); i++) {
|
||||||
|
*(fbuf + (dskoff + i)) = fmtb;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
//*** quick fix. Needs more thought!
|
|
||||||
fp = fopen(uptr->filename, "wb"); // write out modified image
|
|
||||||
for (i=0; i<uptr->capac; i++) {
|
|
||||||
c = *(zx200a[fdcnum].fdd[fddnum].buf + i);
|
|
||||||
fputc(c, fp);
|
|
||||||
}
|
|
||||||
fclose(fp);
|
|
||||||
zx200a[fdcnum].rtype = ROK;
|
zx200a[fdcnum].rtype = ROK;
|
||||||
zx200a[fdcnum].intff = 1; //set interrupt FF
|
zx200a[fdcnum].intff = 1; //set interrupt FF
|
||||||
break;
|
break;
|
||||||
|
@ -738,11 +744,17 @@ void zx200a_diskio(uint8 fdcnum)
|
||||||
nrptr = 0;
|
nrptr = 0;
|
||||||
while(nrptr < nr) {
|
while(nrptr < nr) {
|
||||||
//calculate offset into disk image
|
//calculate offset into disk image
|
||||||
dskoff = ((ta * zx200a[fdcnum].fdd[fddnum].maxsec) + (sa - 1)) * 128;
|
if (zx200a[fdcnum].fdd[fddnum].dd == 1) {
|
||||||
// sim_printf("\n zx200a-%d: cw=%02X di=%02X nr=%02X ta=%02X sa=%02X ba=%04X dskoff=%06X",
|
dskoff = ((ta * MAXSECDD) + (sa - 1)) * 128;
|
||||||
// fdcnum, cw, di, nr, ta, sa, ba, dskoff);
|
} else {
|
||||||
for (i=0; i<128; i++) { //copy sector from image to RAM
|
dskoff = ((ta * MAXSECSD) + (sa - 1)) * 128;
|
||||||
data = *(zx200a[fdcnum].fdd[fddnum].buf + (dskoff + i));
|
}
|
||||||
|
if (DEBUG)
|
||||||
|
sim_printf("\n isbc202-%d: cw=%02X di=%02X nr=%02X ta=%02X sa=%02X ba=%04X dskoff=%06X",
|
||||||
|
fdcnum, cw, di, nr, ta, sa, ba, dskoff);
|
||||||
|
//copy sector from image to RAM
|
||||||
|
for (i=0; i<128; i++) {
|
||||||
|
data = *(fbuf + (dskoff + i));
|
||||||
multibus_put_mbyte(ba + i, data);
|
multibus_put_mbyte(ba + i, data);
|
||||||
}
|
}
|
||||||
sa++;
|
sa++;
|
||||||
|
@ -764,24 +776,22 @@ void zx200a_diskio(uint8 fdcnum)
|
||||||
nrptr = 0;
|
nrptr = 0;
|
||||||
while(nrptr < nr) {
|
while(nrptr < nr) {
|
||||||
//calculate offset into disk image
|
//calculate offset into disk image
|
||||||
dskoff = ((ta * zx200a[fdcnum].fdd[fddnum].maxsec) + (sa - 1)) * 128;
|
if (zx200a[fdcnum].fdd[fddnum].dd == 1) {
|
||||||
// sim_printf("\n zx200a-%d: cw=%02X di=%02X nr=%02X ta=%02X sa=%02X ba=%04X dskoff=%06X",
|
dskoff = ((ta * MAXSECDD) + (sa - 1)) * 128;
|
||||||
// fdcnum, cw, di, nr, ta, sa, ba, dskoff);
|
} else {
|
||||||
for (i=0; i<128; i++) { //copy sector from image to RAM
|
dskoff = ((ta * MAXSECSD) + (sa - 1)) * 128;
|
||||||
|
}
|
||||||
|
if (DEBUG)
|
||||||
|
sim_printf("\n isbc202-%d: cw=%02X di=%02X nr=%02X ta=%02X sa=%02X ba=%04X dskoff=%06X",
|
||||||
|
fdcnum, cw, di, nr, ta, sa, ba, dskoff);
|
||||||
|
for (i=0; i<128; i++) { //copy sector from image to RAM
|
||||||
data = multibus_get_mbyte(ba + i);
|
data = multibus_get_mbyte(ba + i);
|
||||||
*(zx200a[fdcnum].fdd[fddnum].buf + (dskoff + i)) = data;
|
*(fbuf + (dskoff + i)) = data;
|
||||||
}
|
}
|
||||||
sa++;
|
sa++;
|
||||||
ba+=0x80;
|
ba+=0x80;
|
||||||
nrptr++;
|
nrptr++;
|
||||||
}
|
}
|
||||||
//*** quick fix. Needs more thought!
|
|
||||||
fp = fopen(uptr->filename, "wb"); // write out modified image
|
|
||||||
for (i=0; i<uptr->capac; i++) {
|
|
||||||
c = *(zx200a[fdcnum].fdd[fddnum].buf + i);
|
|
||||||
fputc(c, fp);
|
|
||||||
}
|
|
||||||
fclose(fp);
|
|
||||||
zx200a[fdcnum].rtype = ROK;
|
zx200a[fdcnum].rtype = ROK;
|
||||||
zx200a[fdcnum].intff = 1; //set interrupt FF
|
zx200a[fdcnum].intff = 1; //set interrupt FF
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -31,6 +31,8 @@
|
||||||
|
|
||||||
#include "system_defs.h"
|
#include "system_defs.h"
|
||||||
|
|
||||||
|
#define DEBUG 0
|
||||||
|
|
||||||
/* function prototypes */
|
/* function prototypes */
|
||||||
|
|
||||||
uint8 get_mbyte(uint16 addr);
|
uint8 get_mbyte(uint16 addr);
|
||||||
|
@ -123,15 +125,18 @@ uint16 get_mword(uint16 addr)
|
||||||
void put_mbyte(uint16 addr, uint8 val)
|
void put_mbyte(uint16 addr, uint8 val)
|
||||||
{
|
{
|
||||||
if (addr >= 0xF800) { //monitor ROM - always there
|
if (addr >= 0xF800) { //monitor ROM - always there
|
||||||
sim_printf("Write to R/O memory address %04X from PC=%04X - ignored\n", addr, PCX);
|
if (DEBUG)
|
||||||
|
sim_printf("Write to R/O memory address %04X from PC=%04X - ignored\n", addr, PCX);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if ((addr < 0x1000) && ((ipc_cont_unit.u3 & 0x04) == 0)) { //startup
|
if ((addr < 0x1000) && ((ipc_cont_unit.u3 & 0x04) == 0)) { //startup
|
||||||
sim_printf("Write to R/O memory address %04X from PC=%04X - ignored\n", addr, PCX);
|
if (DEBUG)
|
||||||
|
sim_printf("Write to R/O memory address %04X from PC=%04X - ignored\n", addr, PCX);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if ((addr >= 0xE800) && (addr < 0xF000) && ((ipc_cont_unit.u3 & 0x10) == 0)) { //diagnostic ROM
|
if ((addr >= 0xE800) && (addr < 0xF000) && ((ipc_cont_unit.u3 & 0x10) == 0)) { //diagnostic ROM
|
||||||
sim_printf("Write to R/O memory address %04X from PC=%04X - ignored\n", addr, PCX);
|
if (DEBUG)
|
||||||
|
sim_printf("Write to R/O memory address %04X from PC=%04X - ignored\n", addr, PCX);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
RAM_put_mbyte(addr, val);
|
RAM_put_mbyte(addr, val);
|
||||||
|
|
|
@ -69,7 +69,7 @@
|
||||||
|
|
||||||
//board definitions for the multibus
|
//board definitions for the multibus
|
||||||
/* set the base I/O address for the iSBC 201 */
|
/* set the base I/O address for the iSBC 201 */
|
||||||
#define SBC201_BASE 0x88
|
#define SBC201_BASE 0x78
|
||||||
#define SBC201_INT INT_1
|
#define SBC201_INT INT_1
|
||||||
#define SBC201_NUM 0
|
#define SBC201_NUM 0
|
||||||
|
|
||||||
|
@ -84,8 +84,7 @@
|
||||||
#define SBC208_NUM 0
|
#define SBC208_NUM 0
|
||||||
|
|
||||||
/* set the base for the zx-200a disk controller */
|
/* set the base for the zx-200a disk controller */
|
||||||
#define ZX200A_BASE_DD 0x78
|
#define ZX200A_BASE 0x78
|
||||||
#define ZX200A_BASE_SD 0x88
|
|
||||||
#define ZX200A_NUM 0
|
#define ZX200A_NUM 0
|
||||||
|
|
||||||
/* set INTR for CPU */
|
/* set INTR for CPU */
|
||||||
|
|
|
@ -33,7 +33,7 @@
|
||||||
#define SET_XACK(VAL) (xack = VAL)
|
#define SET_XACK(VAL) (xack = VAL)
|
||||||
|
|
||||||
//chip definitions for the iSBC-80/10
|
//chip definitions for the iSBC-80/10
|
||||||
/* set the base I/O address and device count for the 8251s */
|
/* set the base I/O address and device count for the 8251s */
|
||||||
#define I8251_BASE 0xEC
|
#define I8251_BASE 0xEC
|
||||||
#define I8251_NUM 1
|
#define I8251_NUM 1
|
||||||
|
|
||||||
|
@ -59,7 +59,7 @@
|
||||||
/* set the base I/O address for the iSBC 201 */
|
/* set the base I/O address for the iSBC 201 */
|
||||||
#define SBC201_BASE 0x88
|
#define SBC201_BASE 0x88
|
||||||
#define SBC201_INT INT_1
|
#define SBC201_INT INT_1
|
||||||
#define SBC201_NUM 1
|
#define SBC201_NUM 0
|
||||||
|
|
||||||
/* set the base I/O address for the iSBC 202 */
|
/* set the base I/O address for the iSBC 202 */
|
||||||
#define SBC202_BASE 0x78
|
#define SBC202_BASE 0x78
|
||||||
|
|
|
@ -37,7 +37,7 @@
|
||||||
#define I8041_BASE 0xDC
|
#define I8041_BASE 0xDC
|
||||||
#define I8041_NUM 1
|
#define I8041_NUM 1
|
||||||
|
|
||||||
/* set the base I/O address and device count for the 8251s */
|
/* set the base I/O address and device count for the 8251s */
|
||||||
#define I8251_BASE 0xEC
|
#define I8251_BASE 0xEC
|
||||||
#define I8251_NUM 1
|
#define I8251_NUM 1
|
||||||
|
|
||||||
|
|
|
@ -208,6 +208,10 @@
|
||||||
RelativePath="..\Intel-Systems\common\i8259.c"
|
RelativePath="..\Intel-Systems\common\i8259.c"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\Intel-Systems\common\ieprom.c"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\Intel-Systems\imds-225\imds-225_sys.c"
|
RelativePath="..\Intel-Systems\imds-225\imds-225_sys.c"
|
||||||
>
|
>
|
||||||
|
@ -224,16 +228,12 @@
|
||||||
RelativePath="..\Intel-Systems\imds-225\ipc.c"
|
RelativePath="..\Intel-Systems\imds-225\ipc.c"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
<File
|
|
||||||
RelativePath="..\Intel-Systems\common\ipceprom.c"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
<File
|
||||||
RelativePath="..\Intel-Systems\common\ipcmultibus.c"
|
RelativePath="..\Intel-Systems\common\ipcmultibus.c"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\Intel-Systems\common\ipcram8.c"
|
RelativePath="..\Intel-Systems\common\iram8.c"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
<File
|
<File
|
||||||
|
|
2
makefile
2
makefile
|
@ -1400,7 +1400,7 @@ IMDS-225C = Intel-Systems/common
|
||||||
IMDS-225 = ${IMDS-225C}/i8080.c ${IMDS-225D}/imds-225_sys.c \
|
IMDS-225 = ${IMDS-225C}/i8080.c ${IMDS-225D}/imds-225_sys.c \
|
||||||
${IMDS-225C}/i8251.c ${IMDS-225C}/i8255.c \
|
${IMDS-225C}/i8251.c ${IMDS-225C}/i8255.c \
|
||||||
${IMDS-225C}/i8259.c ${IMDS-225C}/i8253.c \
|
${IMDS-225C}/i8259.c ${IMDS-225C}/i8253.c \
|
||||||
${IMDS-225C}/ipceprom.c ${IMDS-225C}/ipcram8.c \
|
${IMDS-225C}/ieprom.c ${IMDS-225C}/iram8.c \
|
||||||
${IMDS-225C}/ipcmultibus.c ${IMDS-225D}/ipc.c \
|
${IMDS-225C}/ipcmultibus.c ${IMDS-225D}/ipc.c \
|
||||||
${IMDS-225C}/ipc-cont.c ${IMDS-225C}/ioc-cont.c \
|
${IMDS-225C}/ipc-cont.c ${IMDS-225C}/ioc-cont.c \
|
||||||
${IMDS-225C}/isbc202.c ${IMDS-225C}/isbc201.c \
|
${IMDS-225C}/isbc202.c ${IMDS-225C}/isbc201.c \
|
||||||
|
|
Loading…
Add table
Reference in a new issue