(FILECREATED "30-Oct-84 14:34:06" {ERIS}<LISPCORE>LIBRARY>BUSMASTER.;2 22284  

      changes to:  (VARS BUSMASTERCOMS)
		   (FNS BUS.WRITE2 BUS.READ)

      previous date: "25-Sep-84 15:52:50" {ERIS}<LISPCORE>LIBRARY>BUSMASTER.;1)


(* Copyright (c) 1984 by Xerox Corporation. All rights reserved.)

(PRETTYCOMPRINT BUSMASTERCOMS)

(RPAQQ BUSMASTERCOMS ((FILES BUSEXTENDER)
		      (* peek and poke functions)
		      (FNS BUS.RESET BUS.INPUT BUS.OUTPUT BUS.READ BUS.READHL BUS.WRITE BUS.WRITE2 
			   BUS.WRITEHL)
		      (* define the \BUSBLT subopcodes in terms of the basic one)
		      (PROP DOPVAL \BUSBLTIN \BUSBLTINBYTES \BUSBLTINNYBBLES \BUSBLTINSWAPBYTES 
			    \BUSBLTOUT \BUSBLTOUTBYTES \BUSBLTOUTNYBBLES \BUSBLTOUTSWAPBYTES)
		      (FNS \BUSBLT.UFN)
		      (* bus <-> dTiger BLT functions)
		      (FNS BUSBLT.BYTES BUSBLT.RIGHTBYTES BUSBLT.NYBBLES)
		      (* dma controller's low level (command)
			 functions)
		      (FNS BUSDMA.SETMODE BUSDMA.SETPAGE BUSDMA.SETADDRESS BUSDMA.READADDRESS 
			   BUSDMA.SETCOUNTER BUSDMA.READCOUNTER BUSDMA.MASK BUSDMA.UNMASK)
		      (* dma controller's higher level functions)
		      (FNS BUSDMA.INIT BUSDMA.READTCBIT)))
(FILESLOAD BUSEXTENDER)



(* peek and poke functions)

(DEFINEQ

(BUS.RESET
  [LAMBDA NIL                                                (* edited: "25-Sep-84 12:25")

          (* * reset the BusMaster and do a reset cycle on the external bus -- emit a control code then write a dummy datum to
	  trigger the cycle)


    (BX.OUTPUT 16 4)
    (BX.OUTPUT 0 5])

(BUS.INPUT
  [LAMBDA (IOADR)                                            (* edited: "25-Sep-84 12:34")

          (* * input a byte datum from an i/o address on the external bus -- latch address, latch command, write dummy datum 
	  to trigger the cycle, read the resulting datum)


    (BX.OUTPUT IOADR 7)
    (BX.OUTPUT 4 4)
    (BX.OUTPUT 0 5)
    (BX.INPUT 5])

(BUS.OUTPUT
  [LAMBDA (IOADR DATUM)                                      (* edited: "25-Sep-84 12:28")

          (* * output a byte datum to an i/o address on the external bus -- latch address, latch command, write datum 
	  (which triggers the cycle))


    (BX.OUTPUT IOADR 7)
    (BX.OUTPUT 8 4)
    (BX.OUTPUT DATUM 5])

(BUS.READ
  [LAMBDA (MEMADDR)                                          (* edited: "25-Sep-84 12:29")

          (* * read a byte datum from a memory address on the external bus)


    (BUS.READHL (LRSH MEMADDR 16)
		(LOGAND MEMADDR 65535])

(BUS.READHL
  [LAMBDA (MEMADRH MEMADRL)                                  (* edited: "25-Sep-84 12:31")

          (* * read a byte datum from a memory address on the external bus -- latch page number, latch address, latch command,
	  write dummy datum to trigger the cycle, read the resulting datum)


    (BX.OUTPUT MEMADRH 6)
    (BX.OUTPUT MEMADRL 7)
    (BX.OUTPUT 1 4)
    (BX.OUTPUT 0 5)
    (BX.INPUT 5])

(BUS.WRITE
  [LAMBDA (MEMADDR DATUM)                                    (* edited: "25-Sep-84 12:32")

          (* * write a byte datum to a memory address on the external bus)


    (BUS.WRITEHL (LRSH MEMADDR 16)
		 (LOGAND MEMADDR 65535)
		 DATUM])

(BUS.WRITE2
  [LAMBDA (A D)                                              (* hdj "30-Oct-84 12:43")
    (BUS.WRITE A (LOGAND 255 D))
    (BUS.WRITE (ADD1 A)
	       (LRSH D 8])

(BUS.WRITEHL
  [LAMBDA (MEMADRH MEMADRL DATUM)                            (* edited: "25-Sep-84 12:34")

          (* * write a byte datum to a memory address on the external bus -- latch page number, latch address, latch command, 
	  write datum (which triggers the cycle))


    (BX.OUTPUT MEMADRH 6)
    (BX.OUTPUT MEMADRL 7)
    (BX.OUTPUT 2 4)
    (BX.OUTPUT DATUM 5])
)



(* define the \BUSBLT subopcodes in terms of the basic one)


(PUTPROPS \BUSBLTIN DOPVAL (4 BUSBLT 4))

(PUTPROPS \BUSBLTINBYTES DOPVAL (4 BUSBLT 5))

(PUTPROPS \BUSBLTINNYBBLES DOPVAL (4 BUSBLT 7))

(PUTPROPS \BUSBLTINSWAPBYTES DOPVAL (4 BUSBLT 6))

(PUTPROPS \BUSBLTOUT DOPVAL (4 BUSBLT 0))

(PUTPROPS \BUSBLTOUTBYTES DOPVAL (4 BUSBLT 1))

(PUTPROPS \BUSBLTOUTNYBBLES DOPVAL (4 BUSBLT 3))

(PUTPROPS \BUSBLTOUTSWAPBYTES DOPVAL (4 BUSBLT 2))
(DEFINEQ

(\BUSBLT.UFN
  [LAMBDA (DLADR BUSADRH BUSADRL NWORDS ALPHABYTE)           (* edited: "25-Sep-84 15:43")

          (* * null UFN for the busblt opcode -- we do not need more because (1) machines without the BUSBLT microcode also 
	  dont have the BX.INPUT etc microcode one would need to simulate the BUSBLT, (2) we have not publicly documented the 
	  BUSBLT subopcodes that are not implemented in microcode, and (3) the BUSBLT opcode doesn't punt)


    NIL])
)



(* bus <-> dTiger BLT functions)

(DEFINEQ

(BUSBLT.BYTES
  [LAMBDA (ARRAY INDEX BUSADDR NELTS TOEXTBUS?)              (* edited: "25-Sep-84 15:44")

          (* * move bytes from array (of BYTE, WORD=SMALLPOSP, or FIXP) <-> external bus memory -- left byte of 1108 word <-> 
	  low address on the external bus)



          (* * we have to have logic around the basic BUSBLT opcode for two reasons -- (1) the microcode can only handle data 
	  that is word-aligned on the 1108, (2) the microcode does not handle (64KB) page-crosses on the external bus)


    (PROG (0BASEDINDEX ARRAYBASE ARRAYSIZEINELTS 0BASEDBYTEINDEX NBYTESREM BUSADDRHI BUSADDRLO 
		       NBYTESREMTHISPAGE NWORDS NBYTES P (PAGELENGTH 65536)
		       (SUB1PAGELENGTH 65535)
		       (LOG2PAGELENGTH 16))

          (* * check args except for array-element type -- get 0BASEDINDEX ARRAYBASE)


          (if (NOT (ARRAYP ARRAY))
	      then (HELP "arg not array:" ARRAY))
          (SETQ 0BASEDINDEX (IDIFFERENCE INDEX (ARRAYORIG ARRAY)))
          (SETQ ARRAYSIZEINELTS (ARRAYSIZE ARRAY))
          (if (OR (MINUSP 0BASEDINDEX)
		  (IGEQ 0BASEDINDEX ARRAYSIZEINELTS))
	      then (HELP "bad index arg:" INDEX))
          (if (OR (ILEQ NELTS 0)
		  (IGREATERP (IPLUS 0BASEDINDEX NELTS)
			     ARRAYSIZEINELTS))
	      then (HELP "bad #elts arg:" NELTS))
          (SETQ ARRAYBASE (\GETBASEPTR ARRAY 0))

          (* * check array-element type -- initialize 0BASEDBYTEINDEX NBYTESREM BUSADDRHI BUSADDRLO)


          (SELECTQ (ARRAYTYP ARRAY)
		   (BYTE (SETQ 0BASEDBYTEINDEX 0BASEDINDEX)
			 (SETQ NBYTESREM NELTS))
		   (SMALLPOSP (SETQ 0BASEDBYTEINDEX (LLSH 0BASEDINDEX 1))
			      (SETQ NBYTESREM (LLSH NELTS 1)))
		   (FIXP (SETQ 0BASEDBYTEINDEX (LLSH 0BASEDINDEX 2))
			 (SETQ NBYTESREM (LLSH NELTS 2)))
		   (HELP "bad array-element type:" (ARRAYTYP ARRAY)))
          (SETQ BUSADDRHI (LRSH BUSADDR LOG2PAGELENGTH))
          (SETQ BUSADDRLO (LOGAND BUSADDR SUB1PAGELENGTH))

          (* * loop: over external-bus pages)


          (while (NOT (ZEROP NBYTESREM))
	     do (SETQ NBYTESREMTHISPAGE (IMIN NBYTESREM (IDIFFERENCE PAGELENGTH BUSADDRLO)))
		(SETQ NBYTESREM (IDIFFERENCE NBYTESREM NBYTESREMTHISPAGE)) 

          (* * possibly do initial halfword out of array)


		(if (NOT (ZEROP (LOGAND 0BASEDBYTEINDEX 1)))
		    then (if TOEXTBUS?
			     then (BUS.WRITEHL BUSADDRHI BUSADDRLO (\GETBASEBYTE ARRAYBASE 
										 0BASEDBYTEINDEX))
			   else (\PUTBASEBYTE ARRAYBASE 0BASEDBYTEINDEX (BUS.READHL BUSADDRHI 
										    BUSADDRLO)))
			 (SETQ 0BASEDBYTEINDEX (ADD1 0BASEDBYTEINDEX))
			 (SETQ BUSADDRLO (ADD1 BUSADDRLO))
			 (SETQ NBYTESREMTHISPAGE (SUB1 NBYTESREMTHISPAGE)))

          (* * possibly BLT whole words)


		(SETQ NWORDS (LRSH NBYTESREMTHISPAGE 1))
		(if (NOT (ZEROP NWORDS))
		    then (SETQ P (\ADDBASE ARRAYBASE (LRSH 0BASEDBYTEINDEX 1)))
			 (if TOEXTBUS?
			     then (\BUSBLT.OUTBYTES P BUSADDRHI BUSADDRLO NWORDS)
			   else (\BUSBLT.INBYTES P BUSADDRHI BUSADDRLO NWORDS))
			 (SETQ NBYTES (LLSH NWORDS 1))
			 (SETQ 0BASEDBYTEINDEX (IPLUS 0BASEDBYTEINDEX NBYTES))
			 (SETQ BUSADDRLO (IPLUS BUSADDRLO NBYTES)))

          (* * possibly do one more byte to finish external-bus page, because of odd alignment on external bus)


		(if (NOT (ZEROP (LOGAND NBYTESREMTHISPAGE 1)))
		    then (if TOEXTBUS?
			     then (BUS.WRITEHL BUSADDRHI BUSADDRLO (\GETBASEBYTE ARRAYBASE 
										 0BASEDBYTEINDEX))
			   else (\PUTBASEBYTE ARRAYBASE 0BASEDBYTEINDEX (BUS.READHL BUSADDRHI 
										    BUSADDRLO)))
			 (SETQ 0BASEDBYTEINDEX (ADD1 0BASEDBYTEINDEX)))

          (* * end of loop)


		(SETQ BUSADDRHI (ADD1 BUSADDRHI))
		(SETQ BUSADDRLO 0])

(BUSBLT.RIGHTBYTES
  [LAMBDA (ARRAY INDEX BUSADDR NELTS TOEXTBUS?)              (* edited: "25-Sep-84 15:45")

          (* * move right bytes only from the words of the array (of WORD=SMALLPOSP, or FIXP) <-> external bus memory)



          (* * we have to have logic around the basic BUSBLT opcode because the microcode does not handle 
	  (64KB) page-crosses on the external bus)


    (PROG (0BASEDINDEX ARRAYBASE ARRAYSIZEINELTS 0BASEDWORDINDEX NWORDSREM BUSADDRHI BUSADDRLO 
		       NWORDSTHISPAGE P (PAGELENGTH 65536)
		       (SUB1PAGELENGTH 65535)
		       (LOG2PAGELENGTH 16))

          (* * check args except for array-element type -- get 0BASEDINDEX ARRAYBASE)


          (if (NOT (ARRAYP ARRAY))
	      then (HELP "arg not array:" ARRAY))
          (SETQ 0BASEDINDEX (IDIFFERENCE INDEX (ARRAYORIG ARRAY)))
          (SETQ ARRAYSIZEINELTS (ARRAYSIZE ARRAY))
          (if (OR (MINUSP 0BASEDINDEX)
		  (IGEQ 0BASEDINDEX ARRAYSIZEINELTS))
	      then (HELP "bad index arg:" INDEX))
          (if (OR (ILEQ NELTS 0)
		  (IGREATERP (IPLUS 0BASEDINDEX NELTS)
			     ARRAYSIZEINELTS))
	      then (HELP "bad #elts arg:" NELTS))
          (SETQ ARRAYBASE (\GETBASEPTR ARRAY 0))

          (* * check array-element type -- initialize 0BASEDWORDINDEX NWORDSREM BUSADDRHI BUSADDRLO)


          (SELECTQ (ARRAYTYP ARRAY)
		   (SMALLPOSP (SETQ 0BASEDWORDINDEX 0BASEDINDEX)
			      (SETQ NWORDSREM NELTS))
		   (FIXP (SETQ 0BASEDWORDINDEX (LLSH 0BASEDINDEX 1))
			 (SETQ NWORDSREM (LLSH NELTS 1)))
		   (HELP "bad array-element type:" (ARRAYTYP ARRAY)))
          (SETQ BUSADDRHI (LRSH BUSADDR LOG2PAGELENGTH))
          (SETQ BUSADDRLO (LOGAND BUSADDR SUB1PAGELENGTH))

          (* * loop: over external-bus pages)


          (while (NOT (ZEROP NWORDSREM))
	     do (SETQ NWORDSTHISPAGE (IMIN NWORDSREM (IDIFFERENCE PAGELENGTH BUSADDRLO))) 

          (* * BLT whole words)


		(SETQ P (\ADDBASE ARRAYBASE 0BASEDWORDINDEX))
		(if TOEXTBUS?
		    then (\BUSBLT.OUT P BUSADDRHI BUSADDRLO NWORDSTHISPAGE)
		  else (\BUSBLT.IN P BUSADDRHI BUSADDRLO NWORDSTHISPAGE))

          (* * end of loop)


		(SETQ 0BASEDWORDINDEX (IPLUS 0BASEDWORDINDEX NWORDSTHISPAGE))
		(SETQ NWORDSREM (IDIFFERENCE NWORDSREM NWORDSTHISPAGE))
		(SETQ BUSADDRHI (ADD1 BUSADDRHI))
		(SETQ BUSADDRLO 0])

(BUSBLT.NYBBLES
  [LAMBDA (ARRAY INDEX BUSADDR NELTS)                        (* edited: "25-Sep-84 15:46")

          (* * move 4-bit nybbles from array (of BYTE, WORD=SMALLPOSP, or FIXP) to external bus memory -- each 1108 nybble 
	  corresponds to one byte on the external bus, the nybble being right-aligned in the byte, with the left 4 bits of the
	  byte being garbage -- byte corresponding to left nybble of 1108 word <-> lower address on the external bus)



          (* * we have to have logic around the basic BUSBLT opcode for two reasons -- (1) the microcode can only handle data 
	  that is word-aligned on the 1108, (2) the microcode does not handle (64KB) page-crosses on the external bus)


    (PROG (0BASEDINDEX ARRAYBASE ARRAYSIZEINELTS 0BASEDNYBBLEINDEX NNYBBLESREM BUSADDRHI BUSADDRLO 
		       NNYBBLESREMTHISPAGE NWORDS NYBBLENUMBER X N S (PAGELENGTH 65536)
		       (SUB1PAGELENGTH 65535)
		       (LOG2PAGELENGTH 16))

          (* * check args except for array-element type -- get 0BASEDINDEX ARRAYBASE)


          (if (NOT (ARRAYP ARRAY))
	      then (HELP "arg not array:" ARRAY))
          (SETQ 0BASEDINDEX (IDIFFERENCE INDEX (ARRAYORIG ARRAY)))
          (SETQ ARRAYSIZEINELTS (ARRAYSIZE ARRAY))
          (if (OR (MINUSP 0BASEDINDEX)
		  (IGEQ 0BASEDINDEX ARRAYSIZEINELTS))
	      then (HELP "bad index arg:" INDEX))
          (if (OR (ILEQ NELTS 0)
		  (IGREATERP (IPLUS 0BASEDINDEX NELTS)
			     ARRAYSIZEINELTS))
	      then (HELP "bad #elts arg:" NELTS))
          (SETQ ARRAYBASE (\GETBASEPTR ARRAY 0))

          (* * check array-element type -- initialize 0BASEDNYBBLEINDEX NNYBBLESREM BUSADDRHI BUSADDRLO)


          (SELECTQ (ARRAYTYP ARRAY)
		   (BYTE (SETQ 0BASEDNYBBLEINDEX (LLSH 0BASEDINDEX 1))
			 (SETQ NNYBBLESREM (LLSH NELTS 1)))
		   (SMALLPOSP (SETQ 0BASEDNYBBLEINDEX (LLSH 0BASEDINDEX 2))
			      (SETQ NNYBBLESREM (LLSH NELTS 2)))
		   (FIXP (SETQ 0BASEDNYBBLEINDEX (LLSH 0BASEDINDEX 3))
			 (SETQ NNYBBLESREM (LLSH NELTS 3)))
		   (HELP "bad array-element type:" (ARRAYTYP ARRAY)))
          (SETQ BUSADDRHI (LRSH BUSADDR LOG2PAGELENGTH))
          (SETQ BUSADDRLO (LOGAND BUSADDR SUB1PAGELENGTH))

          (* * loop: over external-bus pages)


          (while (NOT (ZEROP NNYBBLESREM))
	     do (SETQ NNYBBLESREMTHISPAGE (IMIN NNYBBLESREM (IDIFFERENCE PAGELENGTH BUSADDRLO)))
		(SETQ NNYBBLESREM (IDIFFERENCE NNYBBLESREM NNYBBLESREMTHISPAGE)) 

          (* * possibly do initial part-word of nybbles)


		(SETQ NYBBLENUMBER (LOGAND 0BASEDNYBBLEINDEX 3))
		(if (NOT (ZEROP NYBBLENUMBER))
		    then (SETQ X (\GETBASE ARRAYBASE (LRSH 0BASEDNYBBLEINDEX 2)))
			 (SETQ N (IMIN (IDIFFERENCE 4 NYBBLENUMBER)
				       NNYBBLESREMTHISPAGE))
			 (for I from 1 to N as S from (IDIFFERENCE 12 (LLSH NYBBLENUMBER 2))
			    by -4
			    do (BUS.WRITEHL BUSADDRHI BUSADDRLO (LRSH X S))
			       (SETQ BUSADDRLO (ADD1 BUSADDRLO)))
			 (SETQ 0BASEDNYBBLEINDEX (IPLUS 0BASEDNYBBLEINDEX N))
			 (SETQ NNYBBLESREMTHISPAGE (IDIFFERENCE NNYBBLESREMTHISPAGE N)))

          (* * possibly BLT whole words)


		(SETQ NWORDS (LRSH NNYBBLESREMTHISPAGE 2))
		(if (NOT (ZEROP NWORDS))
		    then (\BUSBLT.OUTNYBBLES (\ADDBASE ARRAYBASE (LRSH 0BASEDNYBBLEINDEX 2))
					     BUSADDRHI BUSADDRLO NWORDS)
			 (SETQ N (LLSH NWORDS 2))
			 (SETQ 0BASEDNYBBLEINDEX (IPLUS 0BASEDNYBBLEINDEX N))
			 (SETQ BUSADDRLO (IPLUS BUSADDRLO N)))

          (* * possibly do more odd nybbles to finish external-bus page because of odd alignment on external bus)


		(SETQ N (LOGAND NNYBBLESREMTHISPAGE 3))
		(if (NOT (ZEROP N))
		    then (SETQ X (\GETBASE ARRAYBASE (LRSH 0BASEDNYBBLEINDEX 2)))
			 (FOR I FROM 1 TO N AS S FROM 12 BY -4
			    DO (BUS.WRITEHL BUSADDRHI BUSADDRLO (LRSH X S))
			       (SETQ BUSADDRLO (ADD1 BUSADDRLO)))
			 (SETQ 0BASEDNYBBLEINDEX (IPLUS 0BASEDNYBBLEINDEX N)))

          (* * end of loop)


		(SETQ BUSADDRHI (ADD1 BUSADDRHI))
		(SETQ BUSADDRLO 0])
)



(* dma controller's low level (command) functions)

(DEFINEQ

(BUSDMA.SETMODE
  [LAMBDA (CHAN WRITEMEMORY? AUTOINIT? DECADDR?)             (* edited: "17-Sep-84 18:37")

          (* * set the channel's mode register. Assumes "single" mode)


    (BUS.OUTPUT 11 (LOGOR CHAN (if WRITEMEMORY?
				   then 4
				 else 8)
			  (if AUTOINIT?
			      then 16
			    else 0)
			  (if DECADDR?
			      then 32
			    else 0)
			  64])

(BUSDMA.SETPAGE
  [LAMBDA (CHAN PAGE)                                        (* edited: "25-Sep-84 13:05")

          (* * write the channel's page register. Note that the page register for channel 0 (the memory refresh channel) is of
	  no use.)


    (BUS.OUTPUT (SELECTQ CHAN
			 (1 131)
			 (2 129)
			 (3 130)
			 (HELP "bad channel# arg:" CHAN))
		PAGE])

(BUSDMA.SETADDRESS
  [LAMBDA (CHAN ADDR)                                        (* edited: "25-Sep-84 12:59")

          (* * write low-16-bit part of base address to a channel's base and current address registers -- presumes the channel
	  is masked, but does clear the byte-select flipflop first.)


    (PROG ((CMD (LLSH CHAN 1)))
          (BUS.OUTPUT 12 0)
          (BUS.OUTPUT CMD ADDR)
          (BUS.OUTPUT CMD (LRSH ADDR 8])

(BUSDMA.READADDRESS
  [LAMBDA (CHAN)                                             (* edited: "25-Sep-84 13:03")

          (* * read and return a channel's current address register (that is, the low-16-bit part) -- presumes the channel is 
	  masked, but does clear the byte-select flipflop first.)


    (PROG ((CMD (LLSH CHAN 1))
	   V)
          (BUS.OUTPUT 12 0)
          (SETQ V (BUS.INPUT CMD))
          (RETURN (LOGOR V (LLSH (BUS.INPUT CMD)
				 8])

(BUSDMA.SETCOUNTER
  [LAMBDA (CHAN NBYTES)                                      (* edited: "25-Sep-84 15:47")

          (* * write 16-bit base byte count for dma to a channel's base and current byte count registers, as byte-count-less-1
	  mod 64K -- presumes the channel is masked, but does clear the byte-select flipflop first.)


    (PROG [(NBYTESLESS1 (SUB1 NBYTES))
	   (CMD (IPLUS 1 (LLSH CHAN 1]
          (IF (OR (ILEQ NBYTES 0)
		  (IGREATERP NBYTES 65536))
	      THEN (HELP "arg must be 1..64K:" NBYTES))
          (BUS.OUTPUT 12 0)
          (BUS.OUTPUT CMD NBYTESLESS1)
          (BUS.OUTPUT CMD (LRSH NBYTESLESS1 8])

(BUSDMA.READCOUNTER
  [LAMBDA (CHAN)                                             (* edited: "25-Sep-84 15:47")

          (* * read a channel's current byte-count-remaining-less-1 register, and return as byte count, mod 64K -- presumes 
	  the channel is masked, but does clear the byte-select flipflop first.)


    (PROG ((CMD (IPLUS 1 (LLSH CHAN 1)))
	   V)
          (BUS.OUTPUT 12 0)
          (SETQ V (BUS.INPUT CMD))
          (RETURN (ADD1 (LOGOR V (LLSH (BUS.INPUT CMD)
				       8])

(BUSDMA.MASK
  [LAMBDA (CHAN)                                             (* scp "25-Jul-84 12:20")

          (* * prevent dma activity on a channel, by setting its bit in the controller's mask register)


    (BUS.OUTPUT 10 (IPLUS 4 CHAN])

(BUSDMA.UNMASK
  [LAMBDA (CHAN)                                             (* scp "25-Jul-84 12:22")

          (* * allow dma activity on a channel, by clearing its bit in the controller's mask register)


    (BUS.OUTPUT 10 CHAN])
)



(* dma controller's higher level functions)

(DEFINEQ

(BUSDMA.INIT
  [LAMBDA NIL                                                (* edited: "25-Sep-84 13:06")

          (* * initialize the bus's dma controller AND start memory refresh in the bus's memory, using channel 0 -- so it also
	  has to initialize the timer used for memory refresh -- leaves channels 1-3 masked but uninitialized)



          (* * TIMER is the base i/o command address for the memory refresh timer -- MASTERCLEAR is the dma chip's 
	  "master clear" command address -- BUSDMA.TCBITS is memory of status register, see BUSDMA.READTCBIT)


    (PROG ((TIMER 64)
	   (MASTERCLEAR 13))

          (* * initialize timer --)


          (BUS.OUTPUT (IPLUS 3 TIMER)
		      84)
          (BUS.OUTPUT (IPLUS 1 TIMER)
		      18)

          (* * dma in general -- master clear, including in particular: clear command register (enable dma controller, no 
	  specials), set mask register (disable all channels), and clear high-byte-select flipflop -- the datum argument is 
	  ignored by the hadware)


          (BUS.OUTPUT MASTERCLEAR 0)
          (SETQ BUSDMA.TCBITS 0)

          (* * memory refresh via channel 0 --)


          (BUSDMA.SETCOUNTER 0 8192)                         (* max wordcount)
          (BUSDMA.SETMODE 0 NIL T NIL)                       (* read, autoinit, increment address 
							     (and "single" mode))
          (BUSDMA.UNMASK 0)                                  (* go)
      ])

(BUSDMA.READTCBIT
  [LAMBDA (CHANNEL CLEARTHEBIT?)                             (* edited: "25-Sep-84 13:07")

          (* * return value of TC bit for channel -- hardware remembers all bits, in status register, until init or read from 
	  status register, either of which clears them all -- we want to remember each bit separately until init or that bit 
	  is explicitly cleared via this function -- so use memory register BUSDMA.TCBITS -- BUSDMA.INIT clears BUSDMA.TCBITS)


    (PROG ((MASK (LLSH 1 CHANNEL))
	   VALUE)
          (SETQ BUSDMA.TCBITS (LOGOR BUSDMA.TCBITS (BUS.INPUT 8)))
          [SETQ VALUE (NOT (ZEROP (LOGAND BUSDMA.TCBITS MASK]
          [IF CLEARTHEBIT?
	      THEN (SETQ BUSDMA.TCBITS (LOGAND BUSDMA.TCBITS (LOGNOT MASK]
          (RETURN VALUE])
)
(PUTPROPS BUSMASTER COPYRIGHT ("Xerox Corporation" 1984))
(DECLARE: DONTCOPY
  (FILEMAP (NIL (1248 3933 (BUS.RESET 1258 . 1577) (BUS.INPUT 1579 . 1974) (BUS.OUTPUT 1976 . 2328) (
BUS.READ 2330 . 2593) (BUS.READHL 2595 . 3042) (BUS.WRITE 3044 . 3319) (BUS.WRITE2 3321 . 3524) (
BUS.WRITEHL 3526 . 3931)) (4416 4909 (\BUSBLT.UFN 4426 . 4907)) (4951 16115 (BUSBLT.BYTES 4961 . 9070)
 (BUSBLT.RIGHTBYTES 9072 . 11641) (BUSBLT.NYBBLES 11643 . 16113)) (16175 19762 (BUSDMA.SETMODE 16185
 . 16607) (BUSDMA.SETPAGE 16609 . 16997) (BUSDMA.SETADDRESS 16999 . 17473) (BUSDMA.READADDRESS 17475
 . 17985) (BUSDMA.SETCOUNTER 17987 . 18691) (BUSDMA.READCOUNTER 18693 . 19246) (BUSDMA.MASK 19248 . 
19509) (BUSDMA.UNMASK 19511 . 19760)) (19815 22204 (BUSDMA.INIT 19825 . 21347) (BUSDMA.READTCBIT 21349
 . 22202)))))
STOP