home *** CD-ROM | disk | FTP | other *** search
/ CP/M / CPM_CDROM.iso / cpm / cbios / fifos.mac < prev    next >
Text File  |  1994-07-13  |  9KB  |  265 lines

  1. ;************************************************************************
  2. ;    FIFO BUFFERS FOR CP/M BIOS
  3. ;
  4. ; The following code is submitted by Glenn Ewing and Bob Richardson
  5. ; of MicroPro.  It is intended as an aid to those who wish to implement
  6. ; interrupts in their systems.    Also included in the submission is a
  7. ; sample port driver and console bios routine intended to show the
  8. ; implementation of the routines as ring buffers for a Bios.
  9. ;
  10. ;  Further Distribution of this file should contain the notice:
  11. ;         This code Copyright (c) 1981 MicroPro International Corp.
  12. ;            made available by permission of the authors
  13. ;            and by MicroPro. Not to be Resold. 
  14. ;     Good Luck!  
  15. ;        ps: most of this code is Glenn's - Bob R.
  16. .z80
  17. size0    equ    16    ; size definition for the fifo queue -must be power of 
  18. ;              2 - actual size depends on the device in questionc
  19. ;
  20. ;    fifo stuf
  21.     defb    'COPYRIGHT (c) 1981 MicroPro International Corp'  
  22. ;
  23. ;
  24. ;    This module impliments first-in-first-out buffers for the
  25. ;    various BIOS I/O paths.  The buffers function as follows:
  26. ;
  27. ;    If:
  28. ;        cnt = number of characters currently stored in buffer, and
  29. ;
  30. ;        nout = relative position in buffer of characer to be output
  31. ;                  next, and
  32. ;
  33. ;        size = size of buffer (even power of 2), and
  34. ;
  35. ;        base = address of bottom of buffer, then
  36. ;
  37. ;    A character is stored in the buffer at address:
  38. ;
  39. ;        base + ((cnt + nout) mod size)
  40. ;
  41. ;    and the variables are updated:
  42. ;
  43. ;        cnt = (cnt + 1) mod size
  44. ;
  45. ;    Alternately, a character is retrieved from address:
  46. ;
  47. ;        base + nout
  48. ;
  49. ;    and the variables are updated:
  50. ;
  51. ;        cnt = (cnt - 1) mod size
  52. ;
  53. ;        nout = (nout + 1) mod size.
  54. ;
  55. ;
  56. ;    These items are stored in memory as follows:
  57. ;
  58. fifo    macro    size
  59. ;
  60.     defb    0        ; cnt
  61.     defb    0        ; nout
  62.     defb    size-1        ; mask for mod ops
  63.     defs    size        ; actual buffer
  64.     endm
  65. ;
  66. ;
  67. ;
  68. ;    The fifo input and output routines provide no protection
  69. ;    from underflow and overflow.  The calling code must use
  70. ;    the fstat routine to ensure that these conditions are
  71. ;    avoided.  Also, the calling code must enable and disable
  72. ;    interupts as appropriate to ensure proper maintainance of
  73. ;    the variables.
  74. ;
  75. ;
  76. fstat:
  77. ;    routine to determine status (fullness) of a buffer.
  78. ;    enter with ix = adr of cnt.
  79. ;    return Z-flag set if buffer empty, Cy set if buffer full.
  80. ;    note that buffer capacity is actually size-1.
  81. ;
  82.     ld    a, (ix + 0)        ; get cnt
  83.     push    de
  84.     ld    e, (ix + 2)        ; get mask
  85.     and    e            ; cnt = cnt mod size
  86.     dec    e            ; e = size - 2
  87.     cp    e            ; test for full
  88.     pop    de
  89.     inc    a            ; clear z leaving cy
  90.     dec    a
  91.     ccf
  92.     ret
  93. ;
  94. ;
  95. fin:
  96. ;    routine to enter a character into a buffer.
  97. ;    enter with c=chr, ix=.cnt
  98. ;
  99.     ld    a, (ix + 0)        ; compute: (cnt + nout) mod size
  100.     inc    (ix + 0)        ; first update cnt
  101.     add    a, (ix + 1)
  102.     and    (ix + 2)
  103.     push    de
  104.     ld    e, a            ; compute base + nin
  105.     ld    d, 0
  106.     inc    ix
  107.     inc    ix
  108.     inc    ix
  109.     add    ix, de
  110.     pop    de
  111.     ld    (ix+0), c        ; store character
  112.     ret
  113. ;
  114. ;
  115. ;
  116. fout:
  117. ;    routine to retreve a character from a buffer.
  118. ;    enter with ix=.cnt
  119. ;    return with c=chr
  120. ;
  121.     dec    (ix + 0)        ; update cnt
  122.     ld    a, (ix + 1)        ; compute: base + nout
  123.     inc    (ix + 1)
  124.     and    (ix + 2)
  125.     push    de
  126.     ld    e, a
  127.     ld    d, 0
  128.     inc    ix
  129.     inc    ix
  130.     inc    ix
  131.     add    ix, de
  132.     pop    de
  133.     ld    c, (ix + 0)        ; get chr
  134.     ret
  135. ;
  136. fifo0:    fifo    size0            ;  sample invocation of the fifo macro
  137. fifo1:    fifo    size0            ; dummy queues for sample codes 
  138. ;
  139. sample:
  140.     jp    cboot            ; phoney jp
  141.     jp    wboot            ; phoney jp
  142.     jp    const            ; console status
  143.     jp    conin            ; console input vector
  144.     jp    conout            ; console output routine
  145. ; end of phoney bios branch vector-
  146. ; note that for this end of the queueing, all that is necessary is to test
  147. ; the status of the queue and return a value based on the queue status-
  148. ; not the status of the device-
  149. ;
  150. ;*************************************************************************
  151. ; start of the front end queue - dequeue routines - these routines are
  152. ; code samples only and are not intended to run on any particular machine
  153. ; and in fact ignore specifically some details of implementation
  154. const:
  155.     ld    ix,fifo0        ; note on real sys, you must save ix
  156. ;                      this sets up the pointer for the 
  157. ;                      fifo routines
  158.     call    fstat            ; check on the status of the queue
  159.     ret    z            ; return if z-flag set, and hence
  160. ;                    ; no char is ready - this will
  161. ;                    ; also have zero in a at this point
  162.     ld    a,0ffh            ; get flag to show that a char is rdy
  163.     ret                ; and return that value -
  164. ;
  165. ;
  166. conin:                    ; read a char from the queue
  167.     call    const            ; first, wait until a char is
  168.                     ; available - necessary to avoid 
  169.                     ; underflow
  170.     jp    z,conin            ; loop until char is ready
  171.     di                ; interrupts must be off to use
  172.                     ; fin and fout routines
  173.     call    fout            ; get a character from the queue
  174.     ld    a,c             ; and put it in correct register
  175.     and    07fh            ; strip parity per spec
  176.     ret                ; to caller
  177. ;
  178. ;
  179. conout:                    ; send a character to the console
  180.     ld    ix,fifo1        ; setup for console output queue
  181.     call    fstat            ; test queue status
  182.     jp    c,conout        ; wait for a space in the queue
  183.                     ; note: carry set if queue is full
  184.     di                ; interrupts off for queue manipulation
  185.     push    ix            ; save queue pointer for conditional
  186.                     ; output routine 
  187.     call    fin            ; put a character into the fifo queue
  188.     pop    ix            ; restore pointer
  189.     call    tryout             ; routine to output a character and
  190.                     ; turn on interrupts from console
  191.                     ; if a character is waiting and if
  192.                     ; port is not busy
  193.     ei                ; restart interrupts
  194.     ret                ; to caller
  195.  
  196. tryout:
  197. ;     This routine is installation dependant-
  198. ;     it must output a character to the console if and only if
  199. ;     the port is ready to accept a character
  200. ;     I will not supply the routine, but rather the logic for the routine
  201. ;     which would run as follows:
  202. ;         select the status port for the console or modem
  203. ;      test the tx ready bit
  204. ;      return if not ready
  205. ;      otherwise if tx is ready to go
  206. ;      call    fout <- gets next char in c register
  207. ;        output the character to the data port
  208. ;      then return
  209. ;*****************************************************************************
  210. ;*****************************************************************************
  211. ;  now - the easy part - servicing the interrupts from the console/printer/
  212. ;  whatever you have hooked up - I am going to just give you the logic for
  213. ; the routine we have been working on, without getting into details as this
  214. ; is obviously a highly installation dependant part of the code.
  215. ;        the philosophy of the coding is, however, the same as the front end
  216. ;   when the device needs a character, get one from the queue with
  217. ;       call  fout             ; and then 
  218. ;   send the character to the device through whatever mode you use to speak
  219. ;   to it - if the queue becomes empty, you generally want to ignore the next
  220. ;   interrupt
  221. ;  ++++++++++++++++++++++++++++++++++++++++++++
  222. ;   if, therefore
  223. ;   it is an input device with a character ready
  224. ;   read the character from the device and then
  225. ;   use
  226. ;       call  fin        ; to put the newly read character into  queue
  227. ;  if the input queue fills up, you will want to ignore further characters-
  228. ;  one standard thing to do is just throw them into the bit bucket and return
  229. ;  from the interrupt
  230. ;  sample code for the output interrupt on an sio might read:
  231. sint0:
  232.     ld    ix,fifo1    ; get output queue
  233.     call    fstat        ; check queue status
  234. ;
  235.     jp    z,underf    ; the queue is empty - no more chars to send
  236.     call    tryout        ; note: this is the same routine we created
  237.                 ; prviously to handle output to port if not
  238.                 ; busy -
  239. ;  This is interrupt code so it is not necessary to disable the interrupts
  240. ;  before calling the fin and fout routines
  241. underf:
  242. ;this routine should turn off the transmit interrupt with a device dependant
  243. ; code - ie, for the sio it would send a 28h to the status port for the sio
  244. ; and then
  245.     ret
  246. ;the code for an input interrupt would be similar, except the routine would
  247. ; read a byte from the device
  248. ; call fstat
  249. ; ret  c    ; throw away character if queue full
  250. ; call fin    ; else put it in queue
  251. ; ret        ; and return
  252. ;
  253. ;
  254. ;
  255. ;
  256. ;******************************************************************************
  257. ; the end - note - this file is copyright (c) Micropro International Corp.
  258. ; and may not be duplicated in whole or in part for resale. The code
  259. ; contained here does not exist in any real implementation of bios except for
  260. ; the fifo routines and are presented here as a service and in expression
  261. ; of our support for this group.  Any source copy of the fifo stuff must
  262. ; retain the credits for this piece of code.  Good luck, may all your 
  263. ; interruptions be quick ones.
  264. ;                             -bob-
  265.