;
-; Extended memory driver for the Commodore REU
+; Extended memory driver for the Commodore REU. Driver works without
+; problems when statically linked.
;
; Ullrich von Bassewitz, 2002-11-29
;
; Driver signature
.byte $65, $6d, $64 ; "emd"
- .byte $00 ; EM API version number
+ .byte EMD_API_VERSION ; EM API version number
; Jump table.
.word INSTALL
- .word DEINSTALL
+ .word UNINSTALL
.word PAGECOUNT
.word MAP
- .word MAPCLEAN
+ .word USE
+ .word COMMIT
.word COPYFROM
.word COPYTO
REU_COUNT = $DF07 ; Transfer count register
REU_IRQMASK = $DF09 ; IRQ mask register
REU_CONTROL = $DF0A ; Control register
+REU_TRIGGER = $FF00 ; REU command trigger
OP_COPYFROM = $ED
OP_COPYTO = $EC
; ------------------------------------------------------------------------
; Data.
-.data
+.bss
pagecount: .res 2 ; Number of pages available
-curpage: .word $FFFF ; Current page number (invalid)
+curpage: .res 2 ; Current page number
-.bss
window: .res 256 ; Memory "window"
reu_params: .word $0000 ; Host address, lo, hi
- .word $0000 ; Exp address, lo, hi
+ .word $0000 ; Exp address, lo, hi
.byte $00 ; Expansion bank no.
.word $0000 ; # bytes to move, lo, hi
- .byte $00 ; Interrupt mask reg.
- .byte $00 ; Adress control reg.
-
-
+ .byte $00 ; Interrupt mask reg.
+ .byte $00 ; Adress control reg.
.code
;
INSTALL:
+ ldx #$00 ; High byte of return code
lda #$55
sta REU_REUADDR
cmp REU_REUADDR ; Check for presence of REU
bne nodevice
- lda #$AA
+ asl a ; A = $AA
sta REU_REUADDR
cmp REU_REUADDR ; Check for presence of REU
bne nodevice
- ldx #>(128*4) ; Assume 128KB
+ ldy #>(128*4) ; Assume 128KB
lda REU_STATUS
and #$10 ; Check size bit
beq @L1
- ldx #>(256*4) ; 256KB when size bit is set
-@L1: stx pagecount+1
+ ldy #>(256*4) ; 256KB when size bit is set
+@L1: sty pagecount+1
- lda #<EM_ERR_OK
- ldx #>EM_ERR_OK
+ ldy #$FF
+ sty curpage
+ sty curpage+1 ; Invalidate the current page
+ txa ; X = A = EM_ERR_OK
rts
; No REU found
nodevice:
- lda #<EM_ERR_NO_DEVICE
- ldx #>EM_ERR_NO_DEVICE
- rts
+ lda #EM_ERR_NO_DEVICE
+; rts ; Run into UNINSTALL instead
; ------------------------------------------------------------------------
-; DEINSTALL routine. Is called before the driver is removed from memory.
+; UNINSTALL routine. Is called before the driver is removed from memory.
; Can do cleanup or whatever. Must not return anything.
;
-DEINSTALL:
+UNINSTALL:
rts
; ------------------------------------------------------------------------
; MAP: Map the page in a/x into memory and return a pointer to the page in
-; a/x. The contents of the currently mapped page (if any) are assumed to be
-; dirty and must be saved into secondary storage if this is necessary.
+; a/x. The contents of the currently mapped page (if any) may be discarded
+; by the driver.
;
-MAP: ldy curpage+1 ; Do we have a page mapped?
- bmi MAPCLEAN ; Jump if no page mapped
-
- ldy #<window
- sty REU_C64ADDR
- ldy #>window
- sty REU_C64ADDR+1
+MAP: sta curpage
+ stx curpage+1 ; Remember the new page
- ldy #0
- sty REU_COUNT+0
- sty REU_REUADDR+0
- ldy curpage
- sty REU_REUADDR+1
- ldy curpage+1
- sty REU_REUADDR+2
+ ldy #OP_COPYFROM
+ jsr common ; Copy the window
- ldy #1
- sty REU_COUNT+1 ; Move 256 bytes
- ldy #OP_COPYTO
- pha
- jsr Transfer ; Transfer 256 bytes into REU
- pla
+ lda #<window
+ ldx #>window ; Return the window address
+done: rts
-; Run straight into MAPCLEAN
+; ------------------------------------------------------------------------
+; USE: Tell the driver that the window is now associated with a given page.
+
+USE: sta curpage
+ stx curpage+1 ; Remember the page
+ lda #<window
+ ldx #>window ; Return the window
+ rts
; ------------------------------------------------------------------------
-; MAPCLEAN: Map the page in a/x into memory and return a pointer to the page
-; in a/x. The contents of the currently mapped page (if any) are assumed to
-; be clean, so if this is an advantage for the driver, the current contents
-; may be discarded.
+; COMMIT: Commit changes in the memory window to extended storage.
-MAPCLEAN:
- sta curpage
- stx curpage+1 ; Remember the new page
+COMMIT: lda curpage
+ ldx curpage+1 ; Do we have a page mapped?
+ bmi done ; Jump if no page mapped
+
+ ldy #OP_COPYTO
+common: sty tmp1
ldy #<window
sty REU_C64ADDR
sty REU_C64ADDR+1
ldy #0
- sty REU_COUNT+0
sty REU_REUADDR+0
sta REU_REUADDR+1
stx REU_REUADDR+2
+ sty REU_COUNT+0
ldy #1
sty REU_COUNT+1 ; Move 256 bytes
- ldy #OP_COPYFROM
- jsr Transfer ; Transfer 256 bytes into REU
-
- lda #<window
- ldx #>window ; Return the window address
- rts
+ bne transfer1 ; Transfer 256 bytes into REU
; ------------------------------------------------------------------------
; COPYFROM: Copy from extended into linear memory. A pointer to a structure
;
COPYFROM:
-
+ ldy #OP_COPYFROM
+ .byte $2C
; ------------------------------------------------------------------------
; COPYTO: Copy from linear into extended memory. A pointer to a structure
;
COPYTO:
- lda #0
- tax
- rts
+ ldy #OP_COPYTO
+ sty tmp1
+
+; Remember the passed pointer
+
+ sta ptr1
+ stx ptr1+1 ; Save the pointer
+
+; The structure passed to the functions has the same layout as the registers
+; of the Commodore REU, so register programming is easy.
+
+ ldy #7-1
+@L1: lda (ptr1),y
+ sta REU_C64ADDR,y
+ dey
+ bpl @L1
+
+; Invalidate the page in the memory window
+
+ sty curpage+1 ; Y = $FF
+
+; Reload the REU command and start the transfer
+
+transfer1:
+ ldy tmp1
-; ---------------------------------------------------------------------------
; Transfer subroutine for the REU. Expects command in Y.
-Transfer:
- sty $df01 ; Issue command
+transfer:
+ sty REU_COMMAND ; Issue command
- sei ; Save the value of the
- ldy $01 ; the c64 control port
- tya ; and turn on lower 3 bits
- ora #$03 ; to bank out ROMs, I/O.
+ ldy $01 ; Save the value of the c64 control port...
+ tya ;
+ and #$F8 ; Disable ROMs and I/O.
+ sei ;
sta $01
- lda $ff00
- sta $ff00 ; Now start transfer...
+ lda REU_TRIGGER ; Don't change $FF00
+ sta REU_TRIGGER ; Start the transfer...
- sty $01 ; Restore the old configuration
+ sty $01 ; Restore the old configuration
cli
rts
+