page 255 .z80 extrn ddtz,bpent extrn $stack extrn charini,?const,?conin extrn romend global isv_sw include config.inc include z180reg.inc include z180.lib ;CR equ 0dh ;---------------------------------------------------------------------- cseg jp start ; restart vectors rsti defl 1 rept 7 db 0, 0, 0, 0, 0 jp bpent rsti defl rsti+1 endm db 0, 0, 0, 0, 0 ;---------------------------------------------------------------------- ;org 40h dw 0 db 0 if ROMSYS $crom: defb c$rom ; else db 0 ; endif dmclrt: ;clear ram per dma db dmct_e-dmclrt-2 ; db sar0l ;first port dw nullbyte ;src (fixed) nullbyte: db 000h ;src dw romend ;dst (inc), start after "rom" code db 00h ;dst dw 0-romend ;count (64k) dmct_e: INIWAITS defl CWAITIO if ROMSYS INIWAITS defl INIWAITS+CWAITROM endif hwini0: db 3 ;count db rcr,CREFSH ;configure DRAM refresh db dcntl,INIWAITS ;wait states db cbar,SYS$CBAR ;---------------------------------------------------------------------- start: ld (tmpstack),sp ld sp,tmpstack push af in0 a,(itc) ;Illegal opcode trap? jp m,??st01 ld a,i ;I register == 0 ? jr z,??st02 ; yes, harware reset ??st01: ld a,(syscbr) out0 (cbr),a pop af ;restore registers ld sp,(tmpstack) ; jp bpent ; ??st02: di ;0058 ld a,CREFSH out0 (rcr),a ; configure DRAM refresh ld a,CWAITIO out0 (dcntl),a ; wait states ld a,M_NCD ;No Clock Divide out0 (ccr),a ; ld a,M_X2CM ;X2 Clock Multiplier ; out0 (cmr),a ; search warm start mark ld ix,mark_55AA ;00b8 ; top of common area ld a,SYS$CBAR ; out0 (cbar),a ; ld a,071h ;00bc ex af,af' ;00be ;for cbr = 0x70 downto 0x40 swsm_l: ex af,af' ;00bf dec a ;00c0 cp 03fh ;00c1 jr z,kstart ;00c3 ; break (mark not found) out0 (cbr),a ;00c5 ex af,af' ;00c8 ld a,0aah ;00c9 cp (ix+000h) ;00cb jr nz,swsm_l ;00ce cp (ix+002h) ;00d0 jr nz,swsm_l ;00d3 cpl ;00d5 cp (ix+001h) ;00d6 jr nz,swsm_l ;00d9 cp (ix+003h) ;00db jr nz,swsm_l ;00de ld sp,$stack ;00e0 mark found, check call checkcrc_alv ;00e3 jp z,wstart ;00e6 check ok, ; ; ram not ok, initialize -- kstart -- kstart: ld a,088h ;00e9 0000-7fff: common 0 out0 (cbar),a ;00eb 8000-ffff: common 1 ld ix,08000h ;00f3 ld a,0 ;00f1 start at 008000 (2. phys. 32k block) ??f_0: out0 (cbr),a ;00f9 ld (ix+0),a ;0103 cpl ld (ix+1),a ;0103 cpl add a,8 ;010a next 'bank' cp 078h ;010c stop at 078000 jr nz,??f_0 ;010e ld de,8000h ;0114 first block not tested, but mark as ok ld a,0 ;00f1 start at 008000 (2. phys. 32k block) ??cp_0: out0 (cbr),a ;011c ld c,a xor (ix+0) ld b,a ld a,c cpl xor (ix+1) or b jr nz,??cp_1 scf ??cp_1: rr d rr e ld a,c add a,8 cp 078h ; stop at 078000 jr nz,??cp_0 ; ; ram test found 1 or more error free blocks (32k) ; ramok: ld a,SYS$CBAR ;01c8 out0 (cbar),a ;01ca ld h,d ld l,e ld c,070h ;01ce highest block ld b,15 ;01d0 ??sr_1: add hl,hl jr c,alloc ;01d4 highest "error free" block ld a,c ;01d6 sub 008h ;01d7 ld c,a ;01d9 djnz ??sr_1 ;01da slp ;01dc should never be reached alloc: out0 (cbr),c ;01de ld a,c ld (syscbr),a ld sp,$stack ;01e1 ; Clear RAM using DMA0 ld hl,dmclrt ;load DMA registers call io.ini.m ld a,0cbh ;01ef dst +1, src fixed, burst out0 (dmode),a ;01f1 ld b,512/64 ld a,062h ;01f4 enable dma0, ??cl_1: out0 (dstat),a ;01f9 clear (up to) 64k djnz ??cl_1 ; end of RAM? ; Init bank manager ld hl,banktabsys ;020f ld (hl),c ; Common area inc hl ;0213 ld (hl),c ; System work area inc hl ;0215 Point to bank 0 entry ld b,BANKS ;0216 l0218h: ld (hl),0ffh ;0218 Mark all banks as unassigned inc hl ;021a djnz l0218h ;021b ld hl,memalv ; ld b,8 ; 8*4k ie. first 32k ??a_0: ld (hl),0e0h ; mark as sys ("rom"/monitor) inc hl djnz ??a_0 rr d ; shift out bit for block 0 rr e ; ld c,15 ;022c 15*32k remaining blocks l022eh: ld a,0feh ; 0xfe == block with error(s) rr d ; rr e adc a,0 ; ==> 0xff : block ok ld b,32/4 ; 32k == 8 * 4k l0236h: ld (hl),a ; inc hl ; djnz l0236h ; dec c ; jr nz,l022eh ;next 32k block ld hl,memalv+0ch ;memalv+0ch ld a,(banktabsys) ; call add_hl_a ld b,3 ; l024ah: ld (hl),0ech ;alloc system ram inc hl ; djnz l024ah ; ld (hl),0efh ;alloc common call gencrc_alv ld hl,0000h ;bank # ld bc,0f0fh ; size (?) (4k blocks) xor a ; call sub_0420h ;alloc mem for bank 0 ld c,l ; or a ; call z,sub_04b5h ; ld hl,0101h ; ld bc,0f0fh ; xor a ; call sub_0420h ; ld c,l ; or a ; call z,sub_04b5h ; ld hl,055AAh ;set warm start mark ld (mark_55AA),hl ; ld (mark_55AA+2),hl; ; ; crc ok -- wstart -- ; wstart: call sysram_init ;027f call ivtab_init call prt0_init call charini call bufferinit im 2 ;?030e ei ;0282 call ?const ;0284 call ?const ;0287 or a ;028a call nz,?conin ;028d ld a,(banktab) ; ld e,a ; jp ddtz ;0290 ds 8 tmpstack: dw 2 syscbr: db 1 ; ;---------------------------------------------------------------------- ; ;TODO: Make a ringbuffer module. global buf.init buf.init: ld (ix+o.in_idx),0 ld (ix+o.out_idx),0 ld (ix+o.mask),a ret ;---------------------------------------------------------------------- if 0 extrn msginit,msg_tx_fifo,msg_rx_fifo extrn msg.sout bufferinit: ld de,msg_tx_fifo in0 a,cbr call log2phys ld (40h+0),hl ld (40h+2),a ; ld (bufdat+1),hl ; ld (bufdat+3),a ; ld a,1 ; ld (bufdat+0),a ; ld hl,inimsg ; call msg.sout ld de,msg_rx_fifo in0 a,cbr call log2phys ld (bufdat+1),hl ld (bufdat+3),a ld a,2 ld (bufdat+0),a ld hl,inimsg call msg.sout ret inimsg: db inimsg_e - $ - 1 db 0AEh db inimsg_e - $ - 1 db 0 bufdat: db 0 dw 0 db 0 inimsg_e: endif ;---------------------------------------------------------------------- ; extrn msginit,msg.sout extrn mtx.fifo,mrx.fifo extrn co.fifo,ci.fifo bufferinit: call msginit ld hl,buffers ld b,buftablen bfi_1: ld a,(hl) inc hl ld (bufdat+0),a ld e,(hl) inc hl ld d,(hl) inc hl push hl or a jr nz,bfi_2 in0 a,cbr call log2phys ld (40h+0),hl ld (40h+2),a out0 (AVRINT5),a jr bfi_3 bfi_2: in0 a,cbr call log2phys ld (bufdat+1),hl ld (bufdat+3),a ld hl,inimsg call msg.sout bfi_3: pop hl djnz bfi_1 ret buffers: db 0 dw mtx.fifo db 1 dw mrx.fifo db 2 dw co.fifo db 3 dw ci.fifo buftablen equ ($ - buffers)/3 inimsg: db inimsg_e - $ -1 db 0AEh db inimsg_e - $ -1 db 0 bufdat: db 0 dw 0 db 0 inimsg_e: ; ;---------------------------------------------------------------------- ; sysram_init: ld hl,sysramw ld de,topcodsys ld bc,sysrame-sysramw ldir ret ;---------------------------------------------------------------------- ivtab_init: ld hl,ivtab ; ld a,h ; ld i,a ; out0 (il),l ; ; Let all vectors point to spurious int routines. ld d,high sp.int0 ld a,low sp.int0 ld b,9 ivt_i1: ld (hl),a inc l ld (hl),d inc l add a,sp.int.len djnz ivt_i1 ret ;---------------------------------------------------------------------- prt0_init: ld a,i ld h,a in0 a,(il) and 0E0h or IV$PRT0 ld l,a ld (hl),low iprt0 inc hl ld (hl),high iprt0 ld hl,prt0itab call io.ini.m ret prt0itab: db prt0it_e-prt0itab-2 db tmdr0l dw PRT_TC10MS dw PRT_TC10MS db M_TIE0+M_TDE0 ;enable timer 0 interrupt and down count. prt0it_e: ; ;---------------------------------------------------------------------- ; io.ini: push bc ld b,0 ;high byte port adress ld a,(hl) ;count inc hl ioi_1: ld c,(hl) ;port address inc hl outi inc b ;outi decrements b dec a jr nz,ioi_1 pop bc ret io.ini.m: push bc ld b,(hl) inc hl ld c,(hl) inc hl otimr pop bc ret io.ini.l: ; ;---------------------------------------------------------------------- ; ; compute crc ; hl: start adr ; bc: len ; bc returns crc val do_crc16: ld de,0FFFFh crc1: ld a,(hl) xor e ld e,a rrca rrca rrca rrca and 0Fh xor e ld e,a rrca rrca rrca push af and 1Fh xor d ld d,a pop af push af rrca and 0F0h xor d ld d,a pop af and 0E0h xor e ld e,d ld d,a cpi jp pe,crc1 or e ;z-flag ret gencrc_alv: push hl ;03f6 push de ;03f7 push bc push af ;03f8 ld hl,banktabsys ;03f9 ld bc,crc_len ;03fc call do_crc16 ;03ff ld (hl),e inc hl ld (hl),d pop af ;0406 pop bc pop de ;0407 pop hl ;0408 ret ;0409 checkcrc_alv: push hl ;040a push de push bc ;040b ld hl,banktabsys ;040d ld bc,crc_len+2 ;0410 call do_crc16 ;0413 pop bc ;041d pop de pop hl ;041e ret ;041f ;---------------------------------------------------------------------- ; ; alloc ; ; h: max bank # ; l: min bank # ; b: max size ; c: min size ; ; ret: ; a: 0 == ok ; 1 == ; 2 == no bank # in requested range ; ff == crc error ; sub_0420h: call checkcrc_alv ;0420 jr nz,l049ch ;0424 crc error, tables corrupt call sub_049dh ;0427 bank # in req. range available? jr c,l0499h ;042a push ix ;042c push iy ;042e push de ;0430 push hl ;0431 push bc ;0432 ld c,b ;0433 ld b,alv_len+1 ;0434 ld d,0 ;0436 ld hl,memalv-1 ;0438 jr l0441h ;043b ; find free blocks l043dh: ld a,(hl) ;043d inc a ;043e free blocks are marked 0ffh jr z,l0446h ;043f l0441h: inc hl ;0441 djnz l043dh ;0442 jr l0464h ;0444 l0446h: push hl ;0446 pop ix ;0447 free blocks start here ld e,000h ;0449 jr l0451h ;044b l044dh: ; count free blocks ld a,(hl) ;044d inc a ;044e jr nz,l0457h ;044f l0451h: inc e ;0451 inc hl ;0452 djnz l044dh ;0453 jr l0464h ;0455 ; end of free blocks run. l0457h: ld a,d ;0457 cp e ;0458 nr of blocks >= requested ? jr nc,l0441h ;0459 ld d,e ;045b push ix ;045c pop iy ;045e ld a,d ;0460 cp c ;0461 jr c,l0441h ;0462 l0464h: pop bc ;0464 ld a,d ;0465 cp b ;0466 jr c,l046ch ;0467 ld d,b ;0469 jr l0471h ;046a l046ch: cp c ;046c jr nc,l0471h ;046d ld d,000h ;046f l0471h: ld a,d ;0471 push iy ;0472 pop hl ;0474 ld de,memalv ;0475 or a ;0478 sbc hl,de ;0479 ld b,l ;047b ld c,a ;047c pop hl ;047d l047eh: or a ;047e jr z,l0489h ;047f ld (iy+0),l ;0481 inc iy ;0484 dec a ;0486 jr l047eh ;0487 l0489h: pop de ;0489 pop iy ;048a pop ix ;048c call gencrc_alv ;048e ld a,c ;0491 or a ;0492 ld a,000h ;0493 ret nz ;0495 or 001h ;0496 ret ;0498 l0499h: ld a,2 ;0499 l049ch: or a ret ;049c ; search a free bank number in range ; h: max # ; l: min # ; ret: ; l: bank number available ; nc, if found, bank nr. in l ; cy, if none found sub_049dh: push de ;049d push bc ;049e ex de,hl ;049f dec e ;04a0 l04a1h: inc e ;04a1 test next # ld a,d ;04a2 cp e ;04a3 jr c,l04b1h ;04a4 ld a,e ;04a6 ld hl,memalv ;04a7 ld bc,alv_len ;04aa cpir ;04ad bank# allready allocated? jr z,l04a1h ;04af if yes, search for next l04b1h: ex de,hl ;04b1 pop bc ;04b2 pop de ;04b3 ret ;04b4 sub_04b5h: ld a,l ;04b5 cp 012h ;04b6 ccf ;04b8 ret c ;04b9 push hl ;04ba ld hl,banktab ;04bb call add_hl_a ld (hl),b ;04c3 call gencrc_alv ;04c4 pop hl ;04c7 or a ;04c8 clear carry ret ;04c9 ;-------------------------------------------------------------- ; ; de: Log. Address ; a: Bank number ; ;out ahl: Phys. (linear) Address bnk2phys: push hl ld hl,banktab call add_hl_a ld a,(hl) pop hl ; fall thru ;-------------------------------------------------------------- ; ; de: Log. Address ; a: Bank (bbr) ; ; OP: ahl = (a<<12) + (d<<8) + e ; ;out ahl: Phys. (linear) Address log2phys: push bc ; ld c,a ; ld b,16 ; mlt bc ;bc = a<<4 ld l,d ; ld h,0 ; add hl,bc ;bc + d == a<<4 + d ld a,h ; ld h,l ; ld l,e ; pop bc ; ret ; ;-------------------------------------------------------------- ; ;return: ; hl = hl + a ; Flags undefined ; add_hl_a: add a,l ld l,a ret nc inc h ret ; --------------------------------------------------------- sysramw: .phase isvsw_loc topcodsys: ; Trampoline for interrupt routines in banked ram. ; Switch stack pointer to "system" stack in top ram ; Save cbar isv_sw: ; ex (sp),hl ; save hl, return adr in hl push de ; push af ; ex de,hl ; ld hl,0 ; add hl,sp ; ld a,h ; cp 0f8h ; jr nc,isw_1 ; ld sp,$stack ; isw_1: push hl ; in0 h,(cbar) ; push hl ; ld a,SYS$CBAR ; out0 (cbar),a ; ex de,hl ; ld e,(hl) ; inc hl ; ld d,(hl) ; ex de,hl ; push bc ; call jphl ; pop bc ; pop hl ; out0 (cbar),h ; pop hl ; ld sp,hl ; pop af ; pop de ; pop hl ; ei ; ret ; jphl: jp (hl) ; ; --------------------------------------------------------- iprt0: push af push hl in0 a,(tcr) in0 a,(tmdr0l) in0 a,(tmdr0h) ld a,(tim_ms) inc a cp 100 jr nz,iprt_1 xor a ld hl,(tim_s) inc hl ld (tim_s),hl iprt_1: ld (tim_ms),a pop hl pop af ei ret ; --------------------------------------------------------- sp.int0: ld a,0d0h jr sp.i.1 sp.int.len equ $-sp.int0 ld a,0d1h jr sp.i.1 ld a,0d2h jr sp.i.1 ld a,0d3h jr sp.i.1 ld a,0d4h jr sp.i.1 ld a,0d5h jr sp.i.1 ld a,0d6h jr sp.i.1 ld a,0d7h jr sp.i.1 ld a,0d8h sp.i.1: ; out (80h),a halt curph defl $ .dephase sysrame: .phase curph tim_ms: db 0 tim_s: dw 0 .dephase ;----------------------------------------------------- dseg ds 1 banktabsys: ds 1 ;0c001h ds 1 ;0c002h banktab: ds BANKS ;0c003h memalv: ds 512/4 ;Number of 4k blocks alv_len equ $-memalv crc_len equ $-banktabsys crc_memalv: ds 2 ; cseg ;.phase 0ffc0h ;ivtab equ 0ffc0h ; 0ffc0h ;int vector table ;.dephase ;.phase 0fffch mark_55AA equ 0fffch ;ds 4 ; 0fffch ;.dephase end