Preliminary Support for Interrupt Management API

This commit is contained in:
Wayne Warthen
2018-08-28 18:55:31 -07:00
parent 5b08693ba2
commit f5294a19d7
11 changed files with 793 additions and 25 deletions

View File

@@ -2,7 +2,7 @@
HBIOS Management Functions
==========================
RESET: ($F0):
RESET ($F0):
B=Function A=Result
VER ($F1):
@@ -52,7 +52,7 @@ GET ($F8):
VDACNT ($40):
BC=Function/Subfunction A=Result
E=Video Unit Count
TIMER ($D0):
BC=Function/Subfunction A=Result
DE:HL=Timer Value (32 bit)
@@ -90,17 +90,101 @@ SET ($F9):
DE=Boot Volume (Disk Unit/Slice)
L=Boot Bank Id
PEEK: ($FA):
PEEK ($FA):
B=Function A=Result
D=Bank E=Byte Value
HL=Address
POKE: ($FB):
POKE ($FB):
B=Function A=Result
D=Bank
E=Byte Value
HL=Address
INT ($FC): Interrupt vector management functions
BC=Function/Subfunction A=Result
Subfunctions:
INTINF ($00): Query interrupt system information
BC=Function/Subfunction A=Result
D=Interrupt Mode
E=Interrupt Vector Table Size
Report interrupt interrupt management system information.
Interrupt Mode:
0: Interrupts disabled
1: Z80 Interrupt Mode 1 active
2: Z80 Interrupt Mode 2 active
Interrupt Vector Table Size:
If interrupts are disabled, this will be zero. if interrupt mode 1, this
will be the number of entries in the interrupt call list. if interrupt mode
2, this will be the number of slots in the interrupt vector table.
INTGET ($10): Get interrupt vector
BC=Function/Subfunction A=Result
E=Interrupt Vector Table Position HL=Interrupt Vector
Return the Interrupt Vector for the specified Interrupt Vector Table Position.
INTSET ($20): Set interrupt vector
BC=Function/Subfunction A=Result
HL=Interrupt Vector HL=Previous Vector
E=Interrupt Vector Table Position DE=Interrupt Routing Engine Address
Set the Interrupt Vector for the specified Interrupt Vector Table Position to the
specified Interrupt Vector. The previous value at the specified table position
will be returned. The Vector Table Position is a zero-based index into the
interrupt vector table and must specify a position less than or equal to the
size of the table.
The new interrupt vector must point to a proper interrupt handler located in the
top 32K of CPU address space. Note that during interrupt processing, the lower
32K of CPU address space will contain the RomWBW HBIOS code bank, not the lower
32K of application TPA. As such, a dynamically installed interrupt handler does
not have access to the lower 32K of TPA and must be careful to avoid modifying
the contents of the lower 32K of memory. Invoking RomWBW HBIOS functions within
an interrupt handler is not supported. The interrupt management framework takes
care of saving and restoring AF, BC, DE, HL, and IY. Any other registers modified
must be saved and restored by the interrupt handler.
Interrupt handlers are different for IM1 or IM2.
For IM1:
The new interrupt handler is responsible for chaining (JP) to the previous vector
if the interrupt is not handled. The interrupt handler must return with ZF set
if interrupt is handled and ZF cleared if not handled.
For IM2:
The interrupt handler requires an invocation stub separate from the actual interrupt
handling code. The stub must be:
PUSH HL
LD HL,<adr of actual interrupt handler>
JP <adr of int routing engine>
When calling Set Interrupt Vector, the address of the stub must be provided for the
Interrupt Vector parameter. The address of the Interrupt Routing Engine will be
returned in DE and must be inserted into the stub code as indicated above. In the
case of IM2 mode interrutps, the actual interrupt handler should not chain to the
previous entry. The new interrupt handler must assume all responsibilities for
the specific interrupt slot being occupied.
If the caller is transient, then the caller must remove the new interrupt handler and
restore the original one prior to termination. This is accomplished by calling this
function with the Interrupt Vector set to the Previous Vector returned in the original
call.
The caller is responsible for disabling interrupts prior to making an INTSET call and
enabling them afterwards. The caller is responsible for ensuring that a valid interrupt
handler is installed prior to enabling any hardware interrupts associated with the handler.
Also, if the handler is transient, the caller must disable the hardware interrupt(s)
associated with the handler prior to uninstalling it.
================
Serial Functions
================
@@ -167,7 +251,7 @@ DEVICE ($06):
Serial Device Attributes Byte:
7: 0=RS-232, 1=Terminal
If Terminal, 3-0 is attached Video Unit #
==============
@@ -234,18 +318,18 @@ DEVICE ($17)
Disk Device Attributes Byte:
7: 1=Floppy, 0=Hard Disk (or similar, e.g. CF, SD, RAM)
If Floppy:
6-5: Form Factor (0=8", 1=5.25", 2=3.5", 3=Other)
4: Sides (0=SS, 1=DS)
3-2: Density (0=SD, 1=DD, 2=HD, 3=ED)
1-0: Reserved
If Hard Disk:
6: Removable
5-3: Type (0=Hard, 1=CF, 2=SD, 3=USB, 4=ROM, 5=RAM, 6=RAMF, 7=?)
2-0: Reserved
Note: IDE value 848Ah in IDENTIFY DEVICE data word 0 indicates CF Card
MEDIA ($18):
@@ -277,7 +361,7 @@ GEOMETRY ($1B):
D:7=LBA Capable
E=Sectors
BC=Block Size
Report current media geometry information.
If media is unknown, return error (no media)

View File

@@ -104,7 +104,7 @@ $ImgFile = "${OutDir}/${RomName}.img" # Final name of IMG image (memory loadable
if ($Platform -eq "UNA") {$CBiosFile = '../CBIOS/cbios_una.bin'} else {$CBiosFile = '../CBIOS/cbios_wbw.bin'}
# List of RomWBW proprietary apps to imbed in ROM disk.
$RomApps = "assign","fdu","format","mode","osldr","rtc","survey","syscopy","sysgen","talk","timer","xm"
$RomApps = "assign","fdu","format","mode","osldr","rtc","survey","syscopy","sysgen","talk","timer","xm","inttest"
""
"Building ${RomName}: ${ROMSize}KB ROM configuration ${Config} for Z${CPUType}..."

View File

@@ -491,6 +491,25 @@ HBX_IVT:
.DW INT_BAD ;
.DW INT_BAD ;
;
HBX_IVTCNT .EQU ($ - HBX_IVT) / 2
;
HBX_ITBL:
.DW HB_BADINT
.DW HB_BADINT
.DW HB_BADINT
.DW HB_BADINT
.DW HB_BADINT
.DW HB_BADINT
.DW HB_BADINT
.DW HB_BADINT
.DW HB_BADINT
.DW HB_BADINT
.DW HB_BADINT
.DW HB_BADINT
.DW HB_BADINT
.DW HB_BADINT
.DW HB_BADINT
.DW HB_BADINT
#ENDIF
;
; INTERRUPT HANDLER STUBS
@@ -1465,6 +1484,8 @@ SYS_DISPATCH:
JP Z,SYS_PEEK ; $FA
DEC A
JP Z,SYS_POKE ; $FB
DEC A
JP Z,SYS_INT ; $FC
CALL PANIC ; INVALID
;
; SOFT RESET HBIOS, RELEASE HEAP MEMORY NOT USED BY HBIOS
@@ -1740,6 +1761,123 @@ SYS_POKE:
XOR A
RET
;
; INTERRUPT MANAGEMENT FUNCTIONS
; SUBFUNCTION IN C
;
SYS_INT:
LD A,C ; GET REQUESTED SUB-FUNCTION
CP BF_SYSINT_INFO
JR Z,SYS_INTINFO
CP BF_SYSINT_GET
JR Z,SYS_INTGET
CP BF_SYSINT_SET
JR Z,SYS_INTSET
OR $FF ; SIGNAL ERROR
RET
;
; GET INTERRUPT SYSTEM INFORMATION
; RETURN D:=INTERRUPT MODE, E:=INT VEC TABLE SIZE
;
SYS_INTINFO:
LD D,INTMODE ; D := ACTIVE INTERRUPT MODE
#IF (INTMODE == 0)
LD E,0 ; 0 ENTRIES IF INTERRUPTS DISABLED
#ENDIF
#IF (INTMODE == 1)
LD A,(HB_IM1CNT) ; RETURN IM1 CALL LIST SIZE
LD E,A
#ENDIF
#IF (INTMODE == 2)
LD E,HBX_IVTCNT ; RETURN INT VEC TABLE SIZE
#ENDIF
XOR A ; INDICATE SUCCESS
RET ; AND DONE
;
; ROUTINE SHARED BY INT GET/SET. RETURNS ADDRESS OF VECTOR FOR SPECIFIED LIST / TABLE
; POSITION. ZF SET ON RETURN FOR SUCCESS, ELSE ERROR.
;
SYS_INTVECADR:
#IF (INTMODE == 0)
CALL PANIC ; INVALID FOR INT MODE 0
OR $FF
RET
#ENDIF
#IF (INTMODE == 1)
LD A,(HB_IM1CNT) ; GET CURRENT ENTRY COUNT
INC A ; ALLOW FOR EXTRA ENTRY TO APPEND AT END
LD C,A ; SAVE IN C FOR COMPARE
#ENDIF
#IF (INTMODE == 2)
LD C,HBX_IVTCNT ; GET CURRENT ENTRY COUNT
#ENDIF
LD A,E ; INCOMING INDEX POSITION TO A
CP C ; COMPARE TO VECTOR COUNT
JR C,SYS_INTGET1 ; CONTINUE IF POSITION IN RANGE
CALL PANIC ; ELSE ERROR
OR $FF
RET
SYS_INTGET1:
OR A
RLA ; HL := (A * 2) FOR IM2
#IF (INTMODE == 1)
RLA ; ... HL := (A * 4) + 1 FOR IM1
INC A
#ENDIF
LD H,0
LD L,A
#IF (INTMODE == 1)
LD DE,HB_IM1INT ; DE := START OF CALL LIST
#ENDIF
#IF (INTMODE == 2)
LD DE,HBX_IVT ; DE := START OF VECTOR TABLE
#ENDIF
ADD HL,DE ; HL := ADR OF VECTOR
XOR A ; INDICATE SUCCESS
RET
;
; RETURN THE INTERRUPT VECTOR FOR A SPECIFIED POSITION IN THE INT VECTOR LIST / TABLE
; ENTRY: E=LIST/TABLE POSITION
; RETURN: HL=INTERRUPT VECTOR
;
SYS_INTGET:
CALL SYS_INTVECADR ; GET VECTOR ADDRESS
RET NZ ; BAIL OUT ON ERROR
LD A,(HL) ; DEREF HL TO GET VECTOR
INC HL
LD H,(HL)
LD L,A
XOR A ; SIGNAL SUCCESS
RET ; DONE
;
; SET AN INTERRUPT VECTOR FOR A SPECIFIED POSITION IN THE INT VECTOR LIST / TABLE
; ENTRY: E=LIST/TABLE POSITION, HL=NEW INTERRUPT VECTOR
; RETURN: HL=PREVIOUS INTERRUPT VECTOR, DE=ADR OF INT ROUTING ENGINE FOR IM2
;
SYS_INTSET:
PUSH HL ; SAVE NEW VECTOR
CALL SYS_INTVECADR ; GET VECTOR ADDRESS
JR Z,SYS_INTSET1 ; CONTINUE IF OK
POP HL ; FIX STACK
RET NZ ; BAIL OUT ON ERROR
SYS_INTSET1:
PUSH HL ; SAVE VECTOR ADDRESS
LD A,(HL) ; DEREF HL TO GET PREV VECTOR
INC HL
LD H,(HL)
LD L,A
EX (SP),HL ; (SP) := PREV VEC, HL := VEC ADR
POP DE ; DE := PREV VEC
POP BC ; BC := NEW VEC
LD (HL),C ; SAVE LSB
INC HL
LD (HL),B ; SAVE MSB
EX DE,HL ; HL := PREV VEC
#IF (INTMODE == 2)
LD DE,HBX_INT ; DE := IM2 INT ROUTING ENGINE
#ENDIF
XOR A ; SIGNAL SUCCESS
RET ; DONE
;
;==================================================================================================
; GLOBAL HBIOS FUNCTIONS
;==================================================================================================
@@ -1765,30 +1903,43 @@ CIO_IDLE:
; CALL XXXX ; CALL INT HANDLER
; RET NZ ; RETURN IF HANDLED
;
HB_IM1INT: ; IM1 DEVICE INTERRUPT HANDLER
JP HB_BADINT
RET ; START WITH NO ENTRIES
.FILL 4 * 8,$C9 ; ROOM FOR 8 ENTRIES
; NOTE THAT THE LIST IS INITIALLY FILLED WITH CALLS TO HB_BADINT.
; AS THE TABLE IS POPULATED, THE ADDRESS OF HB_BADINT IS OVERLAID
; WITH THE ADDRESS OF A REAL INTERRUPT HANDLER.
;
; THERE IS ROOM FOR 8 ENTRIES PLUS A FINAL CALL TO HB_BADINT.
;
HB_IM1INT: ; IM1 DEVICE INTERRUPT HANDLER CALL LIST
CALL HB_BADINT \ RET NZ
CALL HB_BADINT \ RET NZ
CALL HB_BADINT \ RET NZ
CALL HB_BADINT \ RET NZ
CALL HB_BADINT \ RET NZ
CALL HB_BADINT \ RET NZ
CALL HB_BADINT \ RET NZ
CALL HB_BADINT \ RET NZ
CALL HB_BADINT \ RET NZ
;
; ROUTINE BELOW IS USED TO ADD A NEW VECTOR TO THE IM1
; CALL LIST ABOVE. ENTER WITH HL=VECTOR ADDRESS IN HBIOS
;
HB_ADDIM1:
EX DE,HL ; VECTOR ADDRESS TO DE
LD HL,(HB_IM1P) ; GET PTR FOR NEXT ENTRY
LD (HL),$CD ; "CALL" OPCODE
INC HL ; BUMP PTR
LD HL,(HB_IM1PTR) ; GET PTR FOR NEXT ENTRY
INC HL ; BUMP PTR TO ADDRESS FIELD OF CALL OPCODE
LD (HL),E ; ADD VECTOR ADDRESS
INC HL ; ...
LD (HL),D ; ...
INC HL ; BUMP PTR
LD (HL),$C0 ; "RET NZ" OPCODE
INC HL ; BUMP PTR
LD (HL),$C9 ; FINAL "RET" OPCODE
LD (HB_IM1P),HL ; SAVE POINTER
LD (HB_IM1PTR),HL ; SAVE UPDATED POINTER
LD HL,HB_IM1CNT ; POINT TO ENTRY COUNT
INC (HL) ; INCREMENT
RET ; DONE
;
HB_IM1P .DW HB_IM1INT ; POINTER FOR NEXT IM1 ENTRY
HB_IM1CNT .DB 0 ; NUMBER OF ENTRIES IN CALL LIST
HB_IM1MAX .DB 8 ; MAX ENTRIES IN CALL LIST
HB_IM1PTR .DW HB_IM1INT ; POINTER FOR NEXT IM1 ENTRY
;
#ENDIF
;
@@ -1843,6 +1994,7 @@ HB_BADINT:
PRTS("+++ BAD INT: $")
CALL _REGDMP
CALL CONTINUE
OR $FF ; SIGNAL INTERRUPT HANDLED
RET
;
; COMMON API FUNCTION DISPATCH CODE

View File

@@ -65,6 +65,7 @@ BF_SYSGET .EQU BF_SYS + 8 ; GET HBIOS INFO
BF_SYSSET .EQU BF_SYS + 9 ; SET HBIOS PARAMETERS
BF_SYSPEEK .EQU BF_SYS + 10 ; GET A BYTE VALUE FROM ALT BANK
BF_SYSPOKE .EQU BF_SYS + 11 ; SET A BYTE VALUE IN ALT BANK
BF_SYSINT .EQU BF_SYS + 12 ; MANAGE INTERRUPT VECTORS
;
BF_SYSGET_CIOCNT .EQU $00 ; GET CHAR UNIT COUNT
BF_SYSGET_DIOCNT .EQU $10 ; GET DISK UNIT COUNT
@@ -78,6 +79,10 @@ BF_SYSGET_BNKINFO .EQU $F2 ; GET BANK ASSIGNMENT INFO
BF_SYSSET_TIMER .EQU $D0 ; SET TIMER VALUE
BF_SYSSET_BOOTINFO .EQU $E0 ; SET BOOT INFORMATION
;
BF_SYSINT_INFO .EQU $00 ; GET INTERRUPT SYSTEM INFO
BF_SYSINT_GET .EQU $10 ; GET INT VECTOR ADDRESS
BF_SYSINT_SET .EQU $20 ; SET INT VECTOR ADDRESS
;
; SERIAL DEVICE IDS
;
CIODEV_UART .EQU $00

View File

@@ -2,4 +2,4 @@
#DEFINE RMN 9
#DEFINE RUP 1
#DEFINE RTP 0
#DEFINE BIOSVER "2.9.1-pre.6"
#DEFINE BIOSVER "2.9.1-pre.7"