imds-224, isys80xx: Rework attach routines to leverage SCP provided functionality

This commit is contained in:
Bill Beech 2017-04-27 11:20:12 -07:00
parent 0586d34f16
commit 357910dfb9
21 changed files with 412 additions and 2392 deletions

View file

@ -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 */

View file

@ -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);

View file

@ -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);

View file

@ -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)

View file

@ -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 */

View file

@ -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;
} }

View file

@ -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 */

View file

@ -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;
} }

View file

@ -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 */

View file

@ -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;
} }

View file

@ -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);

View file

@ -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;

View file

@ -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 */

View file

@ -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);

View file

@ -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;

View file

@ -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);

View file

@ -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 */

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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 \