title 'Tarbell - bank & move module for CP/M 3 linked BIOS' ; Copyright (c) 1983 Tarbell Electronics ; Version 1.1 4-13-83 Edwin E. Smith ; added @nbnks value for rtc setup routine in boot module 4-13-83 memory$manager equ 20h ;base of tarbell memory manager ports cseg public ?move,?xmove,?bank,?mmtab,?ax16,?gndma public @nbnks,?rar4 extrn @cbnk,@dma,@dbnk maclib z80 ?mmtab: ; memory select table for Tarbell cpu memory manager ; ;DO NOT ALTER BANK 0 ; db 00h,01h,02h,03h,04h,05h,06h,07h db 08h,09h,0ah,0bh,0ch,0dh,0eh,0fh ;bank 0 ; db 10h,11h,12h,13h,14h,15h,16h,17h db 18h,19h,1ah,1bh,0ch,0dh,0eh,0fh ;bank 1 ; db 20h,21h,22h,23h,24h,25h,26h,27H db 28h,29h,2ah,2bh,0cH,0dh,0eh,0fh ;bank 2 ; db 30h,31h,32h,33h,34h,35h,36h,37h db 38h,39h,3ah,3bh,0ch,0dh,0eh,0fh ;bank 3 ; db 1ch,1dh,1eh,1fh,2ch,2dh,2eh,2fh db 3ch,3dh,3eh,3fh,0ch,0dh,0eh,0fh ;bank 4 ; @nbnks db 5 ;total # of memory segments in the system ; xflag db 0 ; flag to show next move is interbank src$des ds 2 ; source and destination banks for ?xmove desadd ds 2 ; destination address for interbank move srcadd ds 2 ; source address for interbank move mcount ds 2 ; byte count for interbank move ; ds 16 ; setup 16 level local stack newstk equ $ ds 2 ; 2 bytes safety pad oldstk ds 2 ; old stack storage word ; ?xmove: ; next ?move call is interbank move ; B = destination bank ; C = source bank sbcd src$des ;save source and destination mvi a,0ffh sta xflag ;flag to ?move routine ret ?move: lda xflag ;test flag for interbank move ora a jnz interbank$move xchg ; we are passed source in DE and dest in HL ldir ; use Z80 block move instruction xchg ; need next addresses in same regs ret interbank$move di ; disable interrupts sspd oldstk ; save stack pointer lxi sp,newstk ; use local stack shld desadd ; save destination sded srcadd ; save source sbcd mcount ; save count ;setup source memory to overlay first 8k mov a,d ;get high byte source address call ?rar4 ;generate 4k block # mov e,a lda src$des ;get source bank # mvi c,memory$manager ;memory manager port call setport ;go setup 2 ports ;setup destination memory to overlay next 8k lda desadd+1 ;get destination address call ?rar4 ;generate 4k block # mov e,a lda src$des+1 ;get destination bank # inr c ;increment to next memory manager port call setport ;go setup next 2 ports ;now translate the addresses and do the move lhld srcadd ;get source address mov a,h ani 0fh ;clear upper nibble mov h,a lded desadd ;get destination address mov a,d ani 0fh ;clear upper nibble ori 20h ;set to block #2 mov d,a lbcd mcount ;get byte count ldir ; FINALLY lda @cbnk ;get the current bank # call ?bank ;restore the memory ; now we must show de & hl to point to next real address lbcd mcount ;get byte count lhld srcadd ;get source address dad b ;add together xchg ;put hl in de lhld desadd ;get destination address dad b ;add in byte count lxi b,0 ;clear byte count just in case mov a,b sta xflag ;clear interbank move flag lspd oldstk ;restore stack pointer ei ;reenable interrupts ret ;return to cp/m setport: call ?ax16 ;multiply by 16 ora e ; or in 4k block # mov e,a ;setup offset mvi d,0 lxi h,?mmtab ;get table address dad d ;add in offset mov a,m ;get memory manager byte cma ;flip for mm chips outp a ;output to memory manager inr c ;increment to next port inx h ;point to next mm byte mov a,m ;get next block just in case cma ;flip for mm chips outp a ;output to memory manager ret ?bank: push h ;save HL push b ;save BC call ?ax16 ;multiply A reg times 16 mov c,a ;setup offset into memory table mvi b,0 lxi h,?mmtab ;initialize HL to memory table dad b ;add in offset lxi b,1000h+memory$manager ; B=count, C=base port select$loop mov a,m ;get memory manager byte cma ;flip for mm chips outp a ;send it to memory manager inr c ;increment port # inx h ;increment table pointer djnz select$loop ;loop till done pop b pop h ret ?ax16: add a ; * 2 add a ; * 4 add a ; * 8 add a ; * 16 ret ?rar4: ani 0f0h ;move upper nibble of rar ;A to lower nibble rar ;returns with upper rar ;nibble and carry cleared rar ret dseg ;this routine resides below commonbase ?gndma: ;generate the physical address & extended address ;for those disks capable of doing the transfer directly ;returns with extended address in A , the dma address ;in DE and the memory table pointer in HL. ;regs used A,DE,HL. lda @dma+1 ;get high byte of dma address call ?rar4 ;generate 4K block # mov e,a lda @dbnk ;get bank # call ?ax16 ora e ;generate table offset mov e,a mvi d,0 lxi h,?mmtab ;get table address dad d ;add in offset lded @dma ;get dma address mov a,d ani 0fh ;mask upper nibble mov d,a ;of dma address mov a,m ;get memory manager byte ani 0fh ;mask address call ?ax16 ;shift to upper nibble ora d ;or in lower nibble mov d,a mov a,m ;get memory manager byte call ?rar4 ;generate extended address ret end