title queue handler (chararacter queues) ; this module is a subset of the host module IOHANDL.Z80, ; except that the subroutine QINIT has been changed and ; the character buffers have been included at the end. name qhandl ;;iohandl entry qinit, getq, putq, unputq ext addhla ;;*include global.z80 ;cromix globals file ;;*include equates.z80 ;cromix equates file *maclib macros.z80 ;include macro library file list nogen,nocond ; ; character circular buffers ; struct 0 cb.cnt defs 1 ;how many characters cb.get defs 2 ;where to get characters cb.put defs 2 ;where to put characters mend ; ----------------------------------------------------------------------------- subttl character queue buffer initialization qinit: ld hl,cbufs ; build the free list of character buffers ld bc,NCBUFS ;* qinit(hl,bc) -- initialize character queue buffers ; ; call with: hl -> base memory ; bc = number of entries ;qinit: save bc,de,hl ld a,7 call addhla ld a,l and a,0F8H ld l,a ld de,0 qinit3: ; first, check whether IOPDEBUG has been loaded over part of the ; character buffer area. if it has, make fewer buffers. ld a,(hl) inc hl and a,(hl) dec hl cp a,FILLER ; if it still the filler which was loaded? jr nz,qix ld (hl),e ; yes. make another buffer. inc hl ld (hl),d dec hl load de,hl ld a,8 call addhla dec bc test bc jr nz,qinit3 qix: ld (cblist),de restor bc,de,hl ret subttl get from character queue ;* a = getq(hl) -- get character from character queue buffer ; ; call with: hl -> buffer header ; returns with: a = character ; carry => no more characters left ; alters: af ; ; getq(cbp) ; cbuf *cbp; ; { disable; /* disable interrupts */ ; if (cbp->cb_cnt == 0) return(ERR); ; c = *cbp->cb_get++; /* get character */ ; if (--cbp->cb_cnt == 0 || /* dec count */ ; cbp->cb_get & 7 == 0) /* next block ? */ ; { blkp = cbp->cb_get-1 & 0FFF8H; /* ptr to block */ ; if (cbp->cb_cnt != 0) ; { nxtp = *blkp; /* point to next block */ ; *nxtp++ -= blkp; /* fix pointer */ ; cbp->cb_get = nxtp; /* point to next char */ ; } ; *blkp = cblist; /* free block */ ; cblist = blkp; ; } ; enable; /* enable interrupts */ ; return(c); ; } getq: save hl,ix disable load ix,hl test1 (ix+cb.cnt) ;if (cb.cnt == 0) jr z,getq8 ; return(ERR) load hl,(ix+cb.get) inc (ix+cb.get) ;cb.get++ ld a,(hl) ;a = *hl push af dec (ix+cb.cnt) ;if (--cb.cnt == 0 || jr z,getq3 ld a,l ; hl+1 & 7 == 0) inc a and a,7 jr nz,getq6 getq3: ld a,l and a,0F8H ; { hl = hl & FFF8H ld l,a push de test1 (ix+cb.cnt) ; if (cb.cnt != 0) jr z,getq5 ld e,(hl) ; { de = *hl inc hl ld d,(hl) dec hl ld a,(de) ; *de++ -= hl sub a,l ld (de),a inc de ld a,(de) sbc a,h ld (de),a inc de stor de,(ix+cb.get) ; cb.get = de ; ; } getq5: ld de,(cblist) ; *hl = cblist ld (hl),e inc hl ld (hl),d dec hl ld (cblist),hl ; cblist = hl pop de ; } getq6: pop hl enable ld a,h ;return(a) and a,a getq9: restor hl,ix ret ; getq8: enable ;error return seterr jr getq9 subttl put into character queue ;* putq(hl,a) -- put character into character queue buffer ; ; call with: a = character ; hl -> buffer header ; returns with: carry => no more characters left ; alters: af ; ; putq(cbp,c) ; cbuf *cbp; char c; ; { disable; /* disable interrupts */ ; if (cbp->cb_cnt == 255) return(ERR); ; if (cbp->cb_cnt == 0 || ; cbp->cb_put & 7 == 0) /* next block ? */ ; { blkp = cblist; /* get a free block */ ; if (blkp == 0) return(ERR); /* list exhausted */ ; cblist = *blkp; ; if (cbp->cb_cnt != 0) ; { *(cbp->cb_put-8) += blkp; /* forward pointer */ ; *blkp++ = cbp->cb_put-8; /* back pointer */ ; } ; else ; { *blkp++ = 0; /* null back pointer */ ; cbp->cb_get = blkp; ; } ; cbp->cb_put = blkp; ; } ; *cbp->cb_put++ = c; /* put character */ ; cbp->cb_cnt++; ; enable; /* enable interrupts */ ; } putq: save de,hl,ix load ix,hl ld e,a disable ld a,(ix+cb.cnt) ;if (cb.cnt == 255) inc a jr z,putq8 ; return(ERR) dec a jr z,putq3 ;if (cb.cnt == 0 || ld a,(ix+cb.put) and a,7 jr nz,putq6 ; cb.put & 7 == 0) putq3: ld hl,(cblist) ; { hl = cblist test hl ; if (hl == 0) jr z,putq8 ; return(ERR) push de ld e,(hl) ; de = *hl inc hl ld d,(hl) dec hl ; hl = blkp ld (cblist),de ; cblist = *blkp ld a,(ix+cb.cnt) ; if (cb.cnt == 0) and a jr z,putq4 load de,(ix+cb.put) ; { de = cb.put-8 ld a,e sub a,8 ld e,a ld a,(de) ; *de += hl add a,l ld (de),a inc de ld a,(de) adc a,h ld (de),a dec de ld (hl),e ; *hl++ = de inc hl ld (hl),d inc hl jr putq5 ; } ; putq4: ld (hl),0 ; else inc hl ; { *hl++ = 0 ld (hl),0 inc hl stor hl,(ix+cb.get) ; cb.get = blkp ; ; } putq5: stor hl,(ix+cb.put) ; cb.put = blkp pop de ; } putq6: load hl,(ix+cb.put) ld (hl),e ;*hl++ = e inc (ix+cb.put) inc (ix+cb.cnt) ;cb.cnt++ enable and a putq9: ld a,e ;preserve a-reg restor de,hl,ix ret ; putq8: enable ;error return seterr jr putq9 subttl unput character from character queue ;* a = unputq(hl) -- unput character from character queue buffer ; ; call with: hl -> buffer header ; returns with: a = character ; carry => no more characters left ; alters: af ; ; unputq(cbp) ; cbuf *cbp; ; { disable; /* disable interrupts */ ; if (cbp->cb_cnt == 0) return(ERR); ; c = *--cbp->cb_put; /* get character */ ; if (--cbp->cb_cnt == 0 || /* dec count */ ; cbp->cb_put & 7 == 2) /* next block ? */ ; { blkp = cbp->cb_put & 0FFF8H; /* ptr to block */ ; if (cbp->cb_cnt != 0) ; { nxtp = *blkp; /* point to next block */ ; *nxtp -= blkp; /* fix pointer */ ; cbp->cb_put = nxtp + 8; /* point to next char */ ; } ; *blkp = cblist; /* free block */ ; cblist = blkp; ; } ; enable; /* enable interrupts */ ; return(c); ; } unputq: save hl,ix disable load ix,hl test1 (ix+cb.cnt) ;if (cb.cnt == 0) jr z,unput8 ; return(ERR) dec (ix+cb.put) load hl,(ix+cb.put) ;hl = --cb.put ld a,(hl) ;a = *hl push af dec (ix+cb.cnt) ;if (--cb.cnt == 0 || jr z,unput3 ld a,l ; hl & 7 == 2) and a,7 cp a,2 jr nz,unput6 unput3: ld a,l and a,0F8H ; { hl = hl & FFF8H ld l,a push de test1 (ix+cb.cnt) ; if (cb.cnt != 0) jr z,unput5 ld e,(hl) ; { de = *hl inc hl ld d,(hl) dec hl ld a,(de) ; *de -= hl sub a,l ld (de),a inc de ld a,(de) sbc a,h ld (de),a dec de ld a,e add a,8 ld e,a stor de,(ix+cb.put) ; cb.put = de+8 ; ; } unput5: ld de,(cblist) ; *hl = cblist ld (hl),e inc hl ld (hl),d dec hl ld (cblist),hl ; cblist = hl pop de unput6: pop hl enable ld a,h ;return(a) and a,a unput9: restor hl,ix ret ; unput8: enable ;error return seterr jr unput9 ; ----------------------------------------------------------------------------- subttl character buffers ; the following buffers should remain at the end of QHANDL ; which is the last module in CROMIX.IOP ; (the debugger will overlay part of this buffer error in a harmless way) ; character buffer parameters CBUFLEN equ 8 ; length of a character buffer NCBUFS equ 100h ; number of character buffers cblist: ds 2 ; pointer to free list ; (the buffers are placed on an even CBUFLEN-boundary) cbufs: rept NCBUFS*CBUFLEN + CBUFLEN - 1 db FILLER mend FILLER equ 0FFH ; =============================================================================