home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
CP/M
/
CPM_CDROM.iso
/
cpm
/
cbios
/
fifos.mac
< prev
next >
Wrap
Text File
|
1994-07-13
|
9KB
|
265 lines
;************************************************************************
; FIFO BUFFERS FOR CP/M BIOS
;
; The following code is submitted by Glenn Ewing and Bob Richardson
; of MicroPro. It is intended as an aid to those who wish to implement
; interrupts in their systems. Also included in the submission is a
; sample port driver and console bios routine intended to show the
; implementation of the routines as ring buffers for a Bios.
;
; Further Distribution of this file should contain the notice:
; This code Copyright (c) 1981 MicroPro International Corp.
; made available by permission of the authors
; and by MicroPro. Not to be Resold.
; Good Luck!
; ps: most of this code is Glenn's - Bob R.
.z80
size0 equ 16 ; size definition for the fifo queue -must be power of
; 2 - actual size depends on the device in questionc
;
; fifo stuf
defb 'COPYRIGHT (c) 1981 MicroPro International Corp'
;
;
; This module impliments first-in-first-out buffers for the
; various BIOS I/O paths. The buffers function as follows:
;
; If:
; cnt = number of characters currently stored in buffer, and
;
; nout = relative position in buffer of characer to be output
; next, and
;
; size = size of buffer (even power of 2), and
;
; base = address of bottom of buffer, then
;
; A character is stored in the buffer at address:
;
; base + ((cnt + nout) mod size)
;
; and the variables are updated:
;
; cnt = (cnt + 1) mod size
;
; Alternately, a character is retrieved from address:
;
; base + nout
;
; and the variables are updated:
;
; cnt = (cnt - 1) mod size
;
; nout = (nout + 1) mod size.
;
;
; These items are stored in memory as follows:
;
fifo macro size
;
defb 0 ; cnt
defb 0 ; nout
defb size-1 ; mask for mod ops
defs size ; actual buffer
endm
;
;
;
; The fifo input and output routines provide no protection
; from underflow and overflow. The calling code must use
; the fstat routine to ensure that these conditions are
; avoided. Also, the calling code must enable and disable
; interupts as appropriate to ensure proper maintainance of
; the variables.
;
;
fstat:
; routine to determine status (fullness) of a buffer.
; enter with ix = adr of cnt.
; return Z-flag set if buffer empty, Cy set if buffer full.
; note that buffer capacity is actually size-1.
;
ld a, (ix + 0) ; get cnt
push de
ld e, (ix + 2) ; get mask
and e ; cnt = cnt mod size
dec e ; e = size - 2
cp e ; test for full
pop de
inc a ; clear z leaving cy
dec a
ccf
ret
;
;
fin:
; routine to enter a character into a buffer.
; enter with c=chr, ix=.cnt
;
ld a, (ix + 0) ; compute: (cnt + nout) mod size
inc (ix + 0) ; first update cnt
add a, (ix + 1)
and (ix + 2)
push de
ld e, a ; compute base + nin
ld d, 0
inc ix
inc ix
inc ix
add ix, de
pop de
ld (ix+0), c ; store character
ret
;
;
;
fout:
; routine to retreve a character from a buffer.
; enter with ix=.cnt
; return with c=chr
;
dec (ix + 0) ; update cnt
ld a, (ix + 1) ; compute: base + nout
inc (ix + 1)
and (ix + 2)
push de
ld e, a
ld d, 0
inc ix
inc ix
inc ix
add ix, de
pop de
ld c, (ix + 0) ; get chr
ret
;
fifo0: fifo size0 ; sample invocation of the fifo macro
fifo1: fifo size0 ; dummy queues for sample codes
;
sample:
jp cboot ; phoney jp
jp wboot ; phoney jp
jp const ; console status
jp conin ; console input vector
jp conout ; console output routine
; end of phoney bios branch vector-
; note that for this end of the queueing, all that is necessary is to test
; the status of the queue and return a value based on the queue status-
; not the status of the device-
;
;*************************************************************************
; start of the front end queue - dequeue routines - these routines are
; code samples only and are not intended to run on any particular machine
; and in fact ignore specifically some details of implementation
const:
ld ix,fifo0 ; note on real sys, you must save ix
; this sets up the pointer for the
; fifo routines
call fstat ; check on the status of the queue
ret z ; return if z-flag set, and hence
; ; no char is ready - this will
; ; also have zero in a at this point
ld a,0ffh ; get flag to show that a char is rdy
ret ; and return that value -
;
;
conin: ; read a char from the queue
call const ; first, wait until a char is
; available - necessary to avoid
; underflow
jp z,conin ; loop until char is ready
di ; interrupts must be off to use
; fin and fout routines
call fout ; get a character from the queue
ld a,c ; and put it in correct register
and 07fh ; strip parity per spec
ret ; to caller
;
;
conout: ; send a character to the console
ld ix,fifo1 ; setup for console output queue
call fstat ; test queue status
jp c,conout ; wait for a space in the queue
; note: carry set if queue is full
di ; interrupts off for queue manipulation
push ix ; save queue pointer for conditional
; output routine
call fin ; put a character into the fifo queue
pop ix ; restore pointer
call tryout ; routine to output a character and
; turn on interrupts from console
; if a character is waiting and if
; port is not busy
ei ; restart interrupts
ret ; to caller
tryout:
; This routine is installation dependant-
; it must output a character to the console if and only if
; the port is ready to accept a character
; I will not supply the routine, but rather the logic for the routine
; which would run as follows:
; select the status port for the console or modem
; test the tx ready bit
; return if not ready
; otherwise if tx is ready to go
; call fout <- gets next char in c register
; output the character to the data port
; then return
;*****************************************************************************
;*****************************************************************************
; now - the easy part - servicing the interrupts from the console/printer/
; whatever you have hooked up - I am going to just give you the logic for
; the routine we have been working on, without getting into details as this
; is obviously a highly installation dependant part of the code.
; the philosophy of the coding is, however, the same as the front end
; when the device needs a character, get one from the queue with
; call fout ; and then
; send the character to the device through whatever mode you use to speak
; to it - if the queue becomes empty, you generally want to ignore the next
; interrupt
; ++++++++++++++++++++++++++++++++++++++++++++
; if, therefore
; it is an input device with a character ready
; read the character from the device and then
; use
; call fin ; to put the newly read character into queue
; if the input queue fills up, you will want to ignore further characters-
; one standard thing to do is just throw them into the bit bucket and return
; from the interrupt
; sample code for the output interrupt on an sio might read:
sint0:
ld ix,fifo1 ; get output queue
call fstat ; check queue status
;
jp z,underf ; the queue is empty - no more chars to send
call tryout ; note: this is the same routine we created
; prviously to handle output to port if not
; busy -
; This is interrupt code so it is not necessary to disable the interrupts
; before calling the fin and fout routines
underf:
;this routine should turn off the transmit interrupt with a device dependant
; code - ie, for the sio it would send a 28h to the status port for the sio
; and then
ret
;the code for an input interrupt would be similar, except the routine would
; read a byte from the device
; call fstat
; ret c ; throw away character if queue full
; call fin ; else put it in queue
; ret ; and return
;
;
;
;
;******************************************************************************
; the end - note - this file is copyright (c) Micropro International Corp.
; and may not be duplicated in whole or in part for resale. The code
; contained here does not exist in any real implementation of bios except for
; the fifo routines and are presented here as a service and in expression
; of our support for this group. Any source copy of the fifo stuff must
; retain the credits for this piece of code. Good luck, may all your
; interruptions be quick ones.
; -bob-