AltairZ80: Add support for Z80 Mode 2 interrupts.
Add support for Z80 Mode 2 interrupts to altairz80_cpu.c Also implement interrupts for the WD179x floppd controller.
This commit is contained in:
parent
c73474df8d
commit
81afea160c
3 changed files with 46 additions and 4 deletions
|
@ -241,6 +241,7 @@ UNIT cpu_unit = {
|
|||
int32 IP_S; /* IP register (8086) */
|
||||
int32 FLAGS_S; /* flags register (8086) */
|
||||
int32 SR = 0; /* switch register */
|
||||
int32 vectorInterrupt = 0; /* Vector Interrupt bitfield */
|
||||
static int32 bankSelect = 0; /* determines selected memory bank */
|
||||
static uint32 common = 0xc000; /* addresses >= 'common' are in common memory */
|
||||
static uint32 common_low = 0; /* Common area is in low memory */
|
||||
|
@ -2078,7 +2079,6 @@ void setClockFrequency(const uint32 Value) {
|
|||
clockHasChanged = TRUE;
|
||||
}
|
||||
|
||||
|
||||
static t_stat sim_instr_mmu (void) {
|
||||
extern int32 timerInterrupt;
|
||||
extern int32 timerInterruptHandler;
|
||||
|
@ -2135,7 +2135,7 @@ static t_stat sim_instr_mmu (void) {
|
|||
SP = SP_S;
|
||||
IX = IX_S;
|
||||
IY = IY_S;
|
||||
specialProcessing = clockFrequency | timerInterrupt | keyboardInterrupt | sim_brk_summ;
|
||||
specialProcessing = clockFrequency | timerInterrupt | vectorInterrupt | keyboardInterrupt | sim_brk_summ;
|
||||
tStates = 0;
|
||||
if (rtc_avail) {
|
||||
startTime = sim_os_msec();
|
||||
|
@ -2157,7 +2157,7 @@ static t_stat sim_instr_mmu (void) {
|
|||
} else /* make sure that sim_os_msec() is not called later */
|
||||
clockFrequency = startTime = tStatesInSlice = 0;
|
||||
}
|
||||
specialProcessing = clockFrequency | timerInterrupt | keyboardInterrupt | sim_brk_summ;
|
||||
specialProcessing = clockFrequency | timerInterrupt | vectorInterrupt | keyboardInterrupt | sim_brk_summ;
|
||||
}
|
||||
|
||||
if (specialProcessing) { /* quick check for special processing */
|
||||
|
@ -2186,6 +2186,35 @@ static t_stat sim_instr_mmu (void) {
|
|||
PC = timerInterruptHandler & ADDRMASK;
|
||||
}
|
||||
|
||||
if ((IM_S == 2) && vectorInterrupt && (IFF_S & 1)) {
|
||||
int32 vectable = (IR_S & 0xFF00);
|
||||
int32 vector;
|
||||
uint32 tempVectorInterrupt = vectorInterrupt;
|
||||
uint8 intVector = 0;
|
||||
|
||||
while ((tempVectorInterrupt & 1) == 0) {
|
||||
tempVectorInterrupt >>= 1;
|
||||
intVector++;
|
||||
}
|
||||
|
||||
vectorInterrupt &= ~(1 << intVector);
|
||||
specialProcessing = clockFrequency | sim_brk_summ;
|
||||
IFF_S = 0; /* disable interrupts */
|
||||
CHECK_BREAK_TWO_BYTES_EXTENDED(SP - 2, SP - 1, (vectorInterrupt |= (1 << intVector), IFF_S |= 1));
|
||||
if ((GetBYTE(PC) == HALTINSTRUCTION) && ((cpu_unit.flags & UNIT_CPU_STOPONHALT) == 0)) {
|
||||
PUSH(PC + 1);
|
||||
PCQ_ENTRY(PC);
|
||||
}
|
||||
else {
|
||||
PUSH(PC);
|
||||
PCQ_ENTRY(PC - 1);
|
||||
}
|
||||
|
||||
vector = GetBYTE(vectable + (intVector * 2)+1) << 8;
|
||||
vector |= GetBYTE(vectable + (intVector * 2));
|
||||
PC = vector & ADDRMASK;
|
||||
}
|
||||
|
||||
if (keyboardInterrupt && (IFF_S & 1)) {
|
||||
keyboardInterrupt = FALSE;
|
||||
specialProcessing = clockFrequency | sim_brk_summ;
|
||||
|
|
|
@ -100,6 +100,8 @@ typedef struct {
|
|||
typedef struct {
|
||||
PNP_INFO pnp; /* Plug-n-Play Information */
|
||||
uint16 fdctype; /* Default is 1793 */
|
||||
uint8 intenable; /* Interrupt Enable */
|
||||
uint8 intvector; /* Interrupt Vector */
|
||||
uint8 intrq; /* WD179X Interrupt Request Output (EOJ) */
|
||||
uint8 hld; /* WD179X Head Load Output */
|
||||
uint8 drq; /* WD179X DMA Request Output */
|
||||
|
@ -131,6 +133,8 @@ typedef struct {
|
|||
WD179X_DRIVE_INFO drive[WD179X_MAX_DRIVES];
|
||||
} WD179X_INFO;
|
||||
|
||||
extern int32 vectorInterrupt; /* FDC interrupt pending */
|
||||
|
||||
static SECTOR_FORMAT sdata;
|
||||
extern uint32 PCX;
|
||||
extern t_stat set_iobase(UNIT *uptr, int32 val, CONST char *cptr, void *desc);
|
||||
|
@ -197,6 +201,8 @@ static UNIT wd179x_unit[] = {
|
|||
|
||||
static REG wd179x_reg[] = {
|
||||
{ DRDATAD(FDCTYPE, wd179x_info_data.fdctype, 16, "Controller type"), },
|
||||
{ FLDATAD(INTENABLE, wd179x_info_data.intenable, 1, "FDC Interrupt Enable"), },
|
||||
{ DRDATAD(INTVECTOR, wd179x_info_data.intvector, 8, "FDC Interrupt Vector"), },
|
||||
{ FLDATAD(INTRQ, wd179x_info_data.intrq, 1, "Interrupt Request"), },
|
||||
{ FLDATAD(HLD, wd179x_info_data.hld, 1, "Head Load"), },
|
||||
{ FLDATAD(DRQ, wd179x_info_data.drq, 1, "DMA Request"), },
|
||||
|
@ -542,6 +548,7 @@ uint8 WD179X_Read(const uint32 Addr)
|
|||
sim_debug(STATUS_MSG, &wd179x_dev, "WD179X: " ADDRESS_FORMAT
|
||||
" RD STATUS = 0x%02x, CMDTYPE=%x\n", PCX, cData, wd179x_info->cmdtype);
|
||||
wd179x_info->intrq = 0;
|
||||
if (wd179x_info->intenable) vectorInterrupt &= ~(1 << wd179x_info->intvector);
|
||||
break;
|
||||
case WD179X_TRACK:
|
||||
cData = pDrive->track;
|
||||
|
@ -946,6 +953,7 @@ static uint8 Do1793Command(uint8 cCommand)
|
|||
}
|
||||
} else {
|
||||
wd179x_info->intrq = 1;
|
||||
if (wd179x_info->intenable) vectorInterrupt |= (1 << wd179x_info->intvector);
|
||||
}
|
||||
wd179x_info->fdc_status &= ~(WD179X_STAT_BUSY); /* Clear BUSY */
|
||||
}
|
||||
|
@ -989,6 +997,7 @@ static uint8 Do1793Command(uint8 cCommand)
|
|||
|
||||
wd179x_info->fdc_status &= ~(WD179X_STAT_BUSY); /* Clear BUSY */
|
||||
wd179x_info->intrq = 1;
|
||||
if (wd179x_info->intenable) vectorInterrupt |= (1 << wd179x_info->intvector);
|
||||
wd179x_info->drq = 1;
|
||||
break;
|
||||
/* Type II Commands */
|
||||
|
@ -1006,7 +1015,6 @@ static uint8 Do1793Command(uint8 cCommand)
|
|||
break;
|
||||
}
|
||||
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -1043,6 +1051,7 @@ uint8 WD179X_Write(const uint32 Addr, uint8 cData)
|
|||
wd179x_info->fdc_write_track = FALSE;
|
||||
wd179x_info->fdc_datacount = 0;
|
||||
wd179x_info->fdc_dataindex = 0;
|
||||
if (wd179x_info->intenable) vectorInterrupt |= (1 << wd179x_info->intvector);
|
||||
|
||||
Do1793Command(cData);
|
||||
break;
|
||||
|
@ -1068,6 +1077,7 @@ uint8 WD179X_Write(const uint32 Addr, uint8 cData)
|
|||
wd179x_info->fdc_status &= ~(WD179X_STAT_DRQ | WD179X_STAT_BUSY); /* Clear DRQ, BUSY */
|
||||
wd179x_info->drq = 0;
|
||||
wd179x_info->intrq = 1;
|
||||
if (wd179x_info->intenable) vectorInterrupt |= (1 << wd179x_info->intvector);
|
||||
|
||||
sim_debug(WR_DATA_MSG, &wd179x_dev, "WD179X[%d]: " ADDRESS_FORMAT
|
||||
" Writing sector, T:%2d/S:%d/N:%2d, Len=%d\n", wd179x_info->sel_drive, PCX, pDrive->track, wd179x_info->fdc_head, wd179x_info->fdc_sector, 128 << wd179x_info->fdc_sec_len);
|
||||
|
@ -1188,6 +1198,7 @@ uint8 WD179X_Write(const uint32 Addr, uint8 cData)
|
|||
wd179x_info->fdc_status &= ~(WD179X_STAT_BUSY | WD179X_STAT_LOST_DATA); /* Clear BUSY, LOST_DATA */
|
||||
wd179x_info->drq = 0;
|
||||
wd179x_info->intrq = 1;
|
||||
if (wd179x_info->intenable) vectorInterrupt |= (1 << wd179x_info->intvector);
|
||||
|
||||
/* Recalculate disk size */
|
||||
pDrive->uptr->capac = sim_fsize(pDrive->uptr->fileref);
|
||||
|
|
|
@ -55,6 +55,8 @@ extern uint8 wd179x_get_nheads(void);
|
|||
typedef struct {
|
||||
PNP_INFO pnp; /* Plug-n-Play Information */
|
||||
uint16 fdctype; /* Default is 1793 */
|
||||
uint8 intenable; /* Interrupt Enable */
|
||||
uint8 intvector; /* Interrupt Vector */
|
||||
uint8 intrq; /* WD179X Interrupt Request Output (EOJ) */
|
||||
uint8 hld; /* WD179X Head Load Output */
|
||||
uint8 drq; /* WD179X DMA Request Output */
|
||||
|
|
Loading…
Add table
Reference in a new issue