Browse Source

Preliminary Support for Interrupt Management API

patch
Wayne Warthen 8 years ago
parent
commit
f5294a19d7
  1. 1
      Doc/ChangeLog.txt
  2. 2
      ReadMe.txt
  3. 7
      Source/Apps/Build.cmd
  4. 519
      Source/Apps/IntTest.asm
  5. 2
      Source/Apps/Timer.asm
  6. 2
      Source/CBIOS/ver.inc
  7. 102
      Source/HBIOS/API.txt
  8. 2
      Source/HBIOS/Build.ps1
  9. 174
      Source/HBIOS/hbios.asm
  10. 5
      Source/HBIOS/hbios.inc
  11. 2
      Source/HBIOS/ver.inc

1
Doc/ChangeLog.txt

@ -14,6 +14,7 @@ Version 2.9.1
- WBW: Added NZCOM distribution files to third slice of hard disk image
- WBW: Fixed getnum32 bug in MODE command (found by Phil Summers)
- P?S: Added serial support for Zilog Peripherals Baord
- WBW: Added preliminary support for interrupt management API
Version 2.9.0
-------------

2
ReadMe.txt

@ -7,7 +7,7 @@
***********************************************************************
Wayne Warthen (wwarthen@gmail.com)
Version 2.9.1-pre.6, 2018-08-01
Version 2.9.1-pre.7, 2018-08-28
https://www.retrobrewcomputers.org/
RomWBW is a ROM-based implementation of CP/M-80 2.2 and Z-System for

7
Source/Apps/Build.cmd

@ -20,6 +20,7 @@ call :asm OSLdr || goto :eof
call :asm Mode || goto :eof
call :asm RTC || goto :eof
call :asm Timer || goto :eof
call :asm180 IntTest || goto :eof
zx Z80ASM -SYSGEN/F
@ -38,4 +39,10 @@ goto :eof
echo.
echo Building %1...
tasm -t80 -g3 -fFF %1.asm %1.com %1.lst
goto :eof
:asm180
echo.
echo Building %1...
tasm -t180 -g3 -fFF %1.asm %1.com %1.lst
goto :eof

519
Source/Apps/IntTest.asm

@ -0,0 +1,519 @@
;===============================================================================
; INTTEST - Test HBIOS interrupt API functions
;
;===============================================================================
;
; Author: Wayne Warthen (wwarthen@gmail.com)
;_______________________________________________________________________________
;
; Usage:
; INTTEST
;_______________________________________________________________________________
;
;===============================================================================
; Definitions
;===============================================================================
;
stksiz .equ $40 ; Working stack size
;
restart .equ $0000 ; CP/M restart vector
bdos .equ $0005 ; BDOS invocation vector
;
bf_sysint .equ $FC ; INT function
;
bf_sysintinfo .equ $00 ; INT INFO subfunction
bf_sysintget .equ $10 ; INT GET subfunction
bf_sysintset .equ $20 ; INT SET subfunction
;
z180_base .equ $40 ; i/o base address for internal z180 registers
z180_tcr .equ z180_base + $10 ; timer control
z180_tmdr0l .equ z180_base + $0C ; timer 0 data lo
;
;===============================================================================
; Code Section
;===============================================================================
;
.org $100
;
; setup stack (save old value)
ld (stksav),sp ; save stack
ld sp,stack ; set new stack
;
; initialization
call init ; initialize
jr nz,exit ; abort if init fails
;
; process
call process ; do main processing
jr nz,exit ; abort on error
;
exit: ; clean up and return to command processor
call crlf ; formatting
ld sp,(stksav) ; restore stack
;jp restart ; return to CP/M via restart
ret ; return to CP/M w/o restart
;
; Initialization
;
init:
call crlf ; formatting
ld de,msgban ; point to version message part 1
call prtstr ; print it
;
; relocate handler
ld hl,reladr
ld de,$8000
ld bc,hsiz
ldir
;
initx
; initialization complete
xor a ; signal success
ret ; return
;
; Process
;
process:
;
; Get info
;
call crlf2
ld de,msginfo ; message
call prtstr
;
ld b,bf_sysint ; INT function
ld c,bf_sysintinfo ; INFO subfunction
rst 08
ld a,d
ld (intmod),a ; save int mode
ld a,e
ld (veccnt),a ; save vector count
;
push de
call crlf
ld de,msgmode ; mode
call prtstr
pop de
push de
ld a,d ; interrupt mode
call prtdecb
call crlf
ld de,msgcnt ; count of vectors
call prtstr
pop de
ld a,e
call prtdecb
;
; Done if int mode is 0
;
ld a,(intmod)
or a
ret z
;
; List vectors
;
call crlf2
ld de,msglst
call prtstr
ld a,(veccnt) ; get count of vectors
or a
jr z,estidx ; bypass if nothing to list
ld b,a ; make it the loop counter
ld c,0 ; vector entry index
;
lstlp:
push bc
call crlf
ld a,' '
call prtchr
call prtchr
ld a,c
call prthex
ld a,':'
call prtchr
ld e,c
ld b,bf_sysint
ld c,bf_sysintget
rst 08
push hl
pop bc
call prthexword
pop bc
inc c
djnz lstlp
;
; Establish interrupt vector index to hook
;
estidx:
ld a,(intmod)
ld c,0
cp 1
jr z,setidx
ld c,2 ; assume timer in entry 2 if im2
cp 2
jr z,setidx
ret ; neither im1 or im2, bail out
setidx:
ld a,c
ld (vecidx),a
;
; Hook vector
;
call crlf2
ld de,msghook
call prtstr
call crlf2
ld a,$ff
ld (count),a ; set counter to max value
;
ld a,(intmod)
cp 1
jr z,hkim1
cp 2
jr z,hkim2
ret
;
; IM1 specific code
;
hkim1:
ld hl,m1int ; pointer to my interrupt handler
ld b,bf_sysint
ld c,bf_sysintset ; set new vector
ld a,(vecidx) ; get vector idx
ld e,a ; put in E
di
rst 08 ; do it
ld (chain),hl ; save the chain address
ei ; interrupts back on
jr start
;
; IM2 specific code
;
hkim2:
ld hl,m2stub ; pointer to my interrupt stub
ld b,bf_sysint
ld c,bf_sysintset ; set new vector
ld a,(vecidx) ; get vector idx
ld e,a ; put in E
di
rst 08 ; do it
ld (chain),hl ; save the chain address
ld (engadr),de ; insert the int routing engine address
ei ; interrupts back on
jr start
;
; Wait for counter to countdown to zero
;
start:
ld a,(count)
ld e,a
call prthex ; print it
ld a,13
call prtchr
loop:
ld a,(count) ; get current count value
cp e
jr z,loop
push af
call prthex ; print it
ld a,13
call prtchr
pop af
or a ; set flags
jr z,loop1 ; done
jr loop ; and loop
loop1:
;
; Unhook
;
call crlf2
ld de,msgunhk
call prtstr
ld hl,(chain) ; original vector
ld b,bf_sysint
ld c,bf_sysintset ; set new vector
ld a,(vecidx) ; get vector idx
ld e,a ; put in E
di
rst 08 ; do it
ei ; interrupts back on
;
xor a ; signal success
ret ; done
;
; Print character in A without destroying any registers
;
prtchr:
push bc ; save registers
push de
push hl
ld e,a ; character to print in E
ld c,$02 ; BDOS function to output a character
call bdos ; do it
pop hl ; restore registers
pop de
pop bc
ret
;
prtdot:
;
; shortcut to print a dot preserving all regs
push af ; save af
ld a,'.' ; load dot char
call prtchr ; print it
pop af ; restore af
ret ; done
;
prtcr:
;
; shortcut to print a dot preserving all regs
push af ; save af
ld a,13 ; load CR value
call prtchr ; print it
pop af ; restore af
ret ; done
;
; Print a zero terminated string at (DE) without destroying any registers
;
prtstr:
push de
;
prtstr1:
ld a,(de) ; get next char
or a
jr z,prtstr2
call prtchr
inc de
jr prtstr1
;
prtstr2:
pop de ; restore registers
ret
;
; Print the value in A in hex without destroying any registers
;
prthex:
push af ; save AF
push de ; save DE
call hexascii ; convert value in A to hex chars in DE
ld a,d ; get the high order hex char
call prtchr ; print it
ld a,e ; get the low order hex char
call prtchr ; print it
pop de ; restore DE
pop af ; restore AF
ret ; done
;
; print the hex word value in bc
;
prthexword:
push af
ld a,b
call prthex
ld a,c
call prthex
pop af
ret
;
; print the hex dword value in de:hl
;
prthex32:
push bc
push de
pop bc
call prthexword
push hl
pop bc
call prthexword
pop bc
ret
;
; Convert binary value in A to ascii hex characters in DE
;
hexascii:
ld d,a ; save A in D
call hexconv ; convert low nibble of A to hex
ld e,a ; save it in E
ld a,d ; get original value back
rlca ; rotate high order nibble to low bits
rlca
rlca
rlca
call hexconv ; convert nibble
ld d,a ; save it in D
ret ; done
;
; Convert low nibble of A to ascii hex
;
hexconv:
and $0F ; low nibble only
add a,$90
daa
adc a,$40
daa
ret
;
; Print value of A or HL in decimal with leading zero suppression
; Use prtdecb for A or prtdecw for HL
;
prtdecb:
push hl
ld h,0
ld l,a
call prtdecw ; print it
pop hl
ret
;
prtdecw:
push af
push bc
push de
push hl
call prtdec0
pop hl
pop de
pop bc
pop af
ret
;
prtdec0:
ld e,'0'
ld bc,-10000
call prtdec1
ld bc,-1000
call prtdec1
ld bc,-100
call prtdec1
ld c,-10
call prtdec1
ld e,0
ld c,-1
prtdec1:
ld a,'0' - 1
prtdec2:
inc a
add hl,bc
jr c,prtdec2
sbc hl,bc
cp e
ret z
ld e,0
call prtchr
ret
;
; Start a new line
;
crlf2:
call crlf ; two of them
crlf:
push af ; preserve AF
ld a,13 ; <CR>
call prtchr ; print it
ld a,10 ; <LF>
call prtchr ; print it
pop af ; restore AF
ret
;
; Get the next non-blank character from (HL).
;
nonblank:
ld a,(hl) ; load next character
or a ; string ends with a null
ret z ; if null, return pointing to null
cp ' ' ; check for blank
ret nz ; return if not blank
inc hl ; if blank, increment character pointer
jr nonblank ; and loop
;
; Convert character in A to uppercase
;
ucase:
cp 'a' ; if below 'a'
ret c ; ... do nothing and return
cp 'z' + 1 ; if above 'z'
ret nc ; ... do nothing and return
res 5,a ; clear bit 5 to make lower case -> upper case
ret ; and return
;
; Add the value in A to HL (HL := HL + A)
;
addhl:
add a,l ; A := A + L
ld l,a ; Put result back in L
ret nc ; if no carry, we are done
inc h ; if carry, increment H
ret ; and return
;
; Jump indirect to address in HL
;
jphl:
jp (hl)
;
;===============================================================================
; Storage Section
;===============================================================================
;
intmod .db 0 ; active interrupt mode
veccnt .db 0 ; count of ingterrupt vectors
vecidx .db 0 ; vector index to hook
;
stksav .dw 0 ; stack pointer saved at start
.fill stksiz,0 ; stack
stack .equ $ ; stack top
;
; Messages
;
msgban .db "INTTEST v1.0, 27-Aug-2018",13,10
.db "Copyright (C) 2018, Wayne Warthen, GNU GPL v3",0
msginfo .db "Interrupt information request...",0
msgmode .db " Active interrupt mode: ",0
msgcnt .db " Vector entries in use: ",0
msglst .db "Interrupt vector address list:",0
msghook .db "Hooking vector...",0
msgunhk .db "Unhooking vector...",0
;
;===============================================================================
; Interrupt Handler
;===============================================================================
;
reladr .equ $ ; relocation start adr
;
.org $8000 ; code will run here
;
m1int:
; count down to zero
ld a,(count)
or a
jr z,m1int1
dec a
ld (count),a
m1int1:
; follow the chain...
ld hl,(chain)
jp (hl)
;
m2stub:
push hl
ld hl,m2int
jp $0000
engadr .equ $ - 2
;
m2int:
; count down to zero
ld a,(count)
or a
jr z,m2int1
dec a
ld (count),a
m2int1:
; ack/reset z180 timer interrupt
in0 a,(z180_tcr)
in0 a,(z180_tmdr0l)
ret
;
chain .dw $0000 ; chain address
count .db 0 ; counter
hsiz .equ $ - $8000 ; size of handler to relocate
.end

2
Source/Apps/Timer.asm

@ -1,5 +1,5 @@
;===============================================================================
; SIMER - Display system timer value
; TIMER - Display system timer value
;
;===============================================================================
;

2
Source/CBIOS/ver.inc

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

102
Source/HBIOS/API.txt

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

2
Source/HBIOS/Build.ps1

@ -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}..."

174
Source/HBIOS/hbios.asm

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

5
Source/HBIOS/hbios.inc

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

2
Source/HBIOS/ver.inc

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

Loading…
Cancel
Save