(FILECREATED "29-Jun-85 18:18:44" {DSK}<DSK>HTHOMPSON>DSL>BUSMASTER.;12 36369
changes to: (FNS PCBUS.READARRAY PCBUS.WRITEARRAY)
previous date: "24-Jun-85 09:12:06" {DSK}<DSK>HTHOMPSON>DSL>BUSMASTER.;10)
(* Copyright (c) 1984, 1985 by Xerox Corporation. All rights reserved.)
(PRETTYCOMPRINT BUSMASTERCOMS)
(RPAQQ BUSMASTERCOMS ((* peek and poke functions)
(FNS BUS.RESET MBUS.INPUT MBUS.OUTPUT MBUS.READ MBUS.READHL MBUS.WRITE MBUS.WRITEHL
PCBUS.INPUT PCBUS.OUTPUT PCBUS.READ PCBUS.READHL PCBUS.READWORD PCBUS.WRITE
PCBUS.WRITEHL PCBUS.WRITEWORD)
(* block transfer and test functions (words <-> PC only to date))
(FNS PCBUS.READARRAY PCBUS.WRITEARRAY PCBUS.TESTARRAY)
(* define the \BUSBLT subopcodes in terms of the basic one)
(PROP DOPVAL \BUSBLTIN \BUSBLTINBYTES \BUSBLTINSWAPBYTES \BUSBLTOUT \BUSBLTOUTBYTES
\BUSBLTOUTNYBBLES \BUSBLTOUTSWAPBYTES \BUSBLTCHECK \BUSBLTCHECKBYTES
\BUSBLTCHECKSWAPBYTES)
(FNS \BUSBLT.UFN)
(* 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)
(VARS (BUSDMA.TCBITS 0))
(GLOBALVARS BUSDMA.TCBITS)
(MACROS BUSDMA.FASTUPDATEADDR BUSDMA.SLOWUPDATEADDR)
(PROP ARGNAMES BUSDMA.FASTUPDATEADDR BUSDMA.SLOWUPDATEADDR)
(FNS \FUATran \SUATran)
(* Busmaster and PC/Multibus connection checkout)
(FNS BUS.CHECKADDR BUS.CHECKCNT BUS.CHECKOUT BM16LOOP BM8LOOP BMSTATLOOP MB.CHECKOUT
MBRCVR.CHECKOUT MBMEM.PRELIMCHECK PC.CHECKOUT PCRCVR.CHECKOUT PCMEM.PRELIMCHECK
STATPRINT)
(FILES (SYSLOAD)
BUSEXTENDER)
(DECLARE: DONTEVAL@LOAD DOEVAL@COMPILE DONTCOPY (FILES (LOADCOMP)
BUSEXTENDER))))
(* peek and poke functions)
(DEFINEQ
(BUS.RESET
[LAMBDA NIL (* ht: "25-May-85 17:33")
(* * 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 32 4)
(BX.OUTPUT 0 5)
(* * this amounts to the core of PCDAC.STOP if it is at the standard address -
this shouldn:t be necessary but apparently it is, and I hope it won%'t screw up if what%'s attached is a multibus
instead of a pc bus.)
(PCBUS.OUTPUT 748+1 15)
(PCBUS.INPUT 748])
(MBUS.INPUT
[LAMBDA (IOADR) (* ht: "25-May-85 13:18")
(* * input a word datum from an i/o address on the external multibus -- latch address, latch command, write dummy
datum to trigger the cycle, read the resulting datum)
(BX.OUTPUT IOADR 7)
(BX.OUTPUT 34308 4) (* "8604 hex")
(BX.OUTPUT 0 5)
(BX.INPUT 5])
(MBUS.OUTPUT
[LAMBDA (IOADR DATUM) (* ht: "25-May-85 13:19")
(* * output a word datum to an i/o address on the external multibus -- latch address, latch command, write datum
(which triggers the cycle))
(BX.OUTPUT IOADR 7)
(BX.OUTPUT 34056 4) (* "8508 hex")
(BX.OUTPUT DATUM 5])
(MBUS.READ
[LAMBDA (MEMADDR) (* ht: "25-May-85 13:10")
(* * read a word datum from a memory address on the external multibus)
(MBUS.READHL (LRSH MEMADDR 16)
(LOGAND MEMADDR 65535])
(MBUS.READHL
[LAMBDA (MEMADRH MEMADRL) (* ht: "25-May-85 13:20")
(* * read a word datum from a memory address on the external multibus -- 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 33281 4) (* "8201 hex")
(BX.OUTPUT 0 5)
(BX.INPUT 5])
(MBUS.WRITE
[LAMBDA (MEMADDR DATUM) (* ht: "25-May-85 13:10")
(* * write a word datum to a memory address on the external multibus)
(MBUS.WRITEHL (LRSH MEMADDR 16)
(LOGAND MEMADDR 65535)
DATUM])
(MBUS.WRITEHL
[LAMBDA (MEMADRH MEMADRL DATUM) (* ht: "25-May-85 13:17")
(* * write a word datum to a memory address on the external multibus -- latch page number, latch address, latch
command, write datum (which triggers the cycle))
(BX.OUTPUT MEMADRH 6)
(BX.OUTPUT MEMADRL 7)
(BX.OUTPUT 33026 4) (* "8102 hex")
(BX.OUTPUT DATUM 5])
(PCBUS.INPUT
[LAMBDA (IOADR) (* ht: "25-May-85 13:23")
(* * input a byte datum from an i/o address on the external pcbus -- 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])
(PCBUS.OUTPUT
[LAMBDA (IOADR DATUM) (* ht: "25-May-85 13:24")
(* * output a byte datum to an i/o address on the external pcbus -- latch address, latch command, write datum
(which triggers the cycle))
(BX.OUTPUT IOADR 7)
(BX.OUTPUT 8 4)
(BX.OUTPUT DATUM 5])
(PCBUS.READ
[LAMBDA (MEMADDR) (* ht: "25-May-85 13:24")
(* * read a byte datum from a memory address on the external pcbus)
(PCBUS.READHL (LRSH MEMADDR 16)
(LOGAND MEMADDR 65535])
(PCBUS.READHL
[LAMBDA (MEMADRH MEMADRL) (* ht: "25-May-85 13:25")
(* * read a byte datum from a memory address on the external pcbus -- 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])
(PCBUS.READWORD
[LAMBDA (hiAddr loWordAddr mode) (* ht: "26-May-85 18:44")
(* * read a word from the external pc memory -
hiAddr is pcmem page number, loWordAddr is word address on page. mode is either STRAIGHT (or NIL) meaning bytes are
stored hiOrder/loOrder, or SWAP meaning bytes are stored loOrder/hiOrder)
(LET*[(loAddr (LLSH loWordAddr 1))
(first (PCBUS.READHL hiAddr loAddr))
(second (PCBUS.READHL hiAddr (IPLUS loAddr 1]
(SELECTQ mode
((NIL STRAIGHT)
(IPLUS (LLSH first 8)
second))
(SWAP (IPLUS (LLSH second 8)
first))
(SHOULDNT "bad mode"])
(PCBUS.WRITE
[LAMBDA (MEMADDR DATUM) (* ht: "25-May-85 13:24")
(* * write a byte datum to a memory address on the external pcbus)
(PCBUS.WRITEHL (LRSH MEMADDR 16)
(LOGAND MEMADDR 65535)
DATUM])
(PCBUS.WRITEHL
[LAMBDA (MEMADRH MEMADRL DATUM) (* ht: "25-May-85 13:25")
(* * write a byte datum to a memory address on the external pcbus -- 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])
(PCBUS.WRITEWORD
[LAMBDA (hiAddr loWordAddr word mode) (* ht: "26-May-85 18:48")
(* * write a word to the external pc memory -
hiAddr is pcmem page number, loWordAddr is word address on page. mode is either STRAIGHT (or NIL) meaning bytes are
stored hiOrder/loOrder, or SWAP meaning bytes are stored loOrder/hiOrder)
(LET ((lo (LOGAND word 255))
(hi (LRSH word 8))
(loAddr (LLSH loWordAddr 1)))
(SELECTQ mode
((NIL STRAIGHT)
(PCBUS.WRITEHL hiAddr loAddr hi)
(PCBUS.WRITEHL hiAddr (IPLUS loAddr 1)
lo))
(SWAP (PCBUS.WRITEHL hiAddr loAddr lo)
(PCBUS.WRITEHL hiAddr (IPLUS loAddr 1)
hi))
(SHOULDNT "bad mode"])
)
(* block transfer and test functions (words <-> PC only to date))
(DEFINEQ
(PCBUS.READARRAY
[LAMBDA (array loWordAddr count mode arrayIndex wrap? hiAddr)
(* ht: "29-Jun-85 18:18")
(* * read words from the external pc memory to an array -
hiAddr is pcmem page number (defaults to 1), loWordAddr is word address on page. mode is either STRAIGHT
(or NIL) meaning bytes are stored hiOrder/loOrder, or SWAP meaning bytes are stored loOrder/hiOrder -
count is the number of words to transfer, and arrayIndex is the first element of the array to store into
(defaults to first element of array) -
Works for either 0 or 1 origin arrays. Checks array references are in bounds, but not PC ones because it will wrap
around in case of overflow, which is probably what one wants. (If wrap? is non-NIL, will wrap around with respect to
the array if necessary.))
(if (IGREATERP count 0)
then (if (ARRAYTYP array)= 'SMALLPOSP
then (LET ((size (ARRAYSIZE array))
(orig (ARRAYORIG array))
firstCount)
(if (OR (ILEQ (OR arrayIndex orig)+count size+orig)
(AND wrap? (ILEQ count size)
(PCBUS.READARRAY array loWordAddr firstCount←size+orig-(OR
arrayIndex orig)
mode arrayIndex NIL hiAddr)
(add loWordAddr firstCount)
count←count-firstCount
arrayIndex←orig))
then (SELECTQ mode
((NIL STRAIGHT)
(\BUSBLTINBYTES (if arrayIndex
then (\ADDBASE (ARRAYBASE array)
(IDIFFERENCE
arrayIndex
orig))
else (ARRAYBASE array))
(OR hiAddr 1)
(LLSH loWordAddr 1)
count))
(SWAP (\BUSBLTINSWAPBYTES (if arrayIndex
then (\ADDBASE (ARRAYBASE
array)
(IDIFFERENCE
arrayIndex
orig))
else (ARRAYBASE array))
(OR hiAddr 1)
(LLSH loWordAddr 1)
count))
(SHOULDNT "bad mode"))
else (SETERRORN 27 count)
(ERRORX)))
else (SETERRORN 27 array)
(ERRORX])
(PCBUS.WRITEARRAY
[LAMBDA (array loWordAddr count mode arrayIndex wrap? hiAddr)
(* ht: "29-Jun-85 18:18")
(* * write words to the external pc memory from an array of WORDs -
hiAddr is pcmem page number (defaults to 1), loWordAddr is word address on page. mode is either STRAIGHT
(or NIL) meaning bytes are stored hiOrder/loOrder, or SWAP meaning bytes are stored loOrder/hiOrder -
count is the number of words to transfer, and arrayIndex is the first element of the array to store into
(defaults to first element of array) -
Works for either 0 or 1 origin arrays. Checks array references are in bounds, but not PC ones because it will wrap
around in case of overflow, which is probably what one wants. If wrap? is non-NIL, will wrap around with respect to
the array if necessary.)
(if (IGREATERP count 0)
then (if (ARRAYTYP array)= 'SMALLPOSP
then (LET ((size (ARRAYSIZE array))
(orig (ARRAYORIG array))
firstCount)
(if (OR (ILEQ (OR arrayIndex orig)+count size+orig)
(AND wrap? (ILEQ count size)
(PCBUS.WRITEARRAY array loWordAddr firstCount←size+orig-(OR
arrayIndex orig)
mode arrayIndex NIL hiAddr)
(add loWordAddr firstCount)
count←count-firstCount
arrayIndex←orig))
then (SELECTQ mode
((NIL STRAIGHT)
(\BUSBLTOUTBYTES (if arrayIndex
then (\ADDBASE (ARRAYBASE array)
(IDIFFERENCE
arrayIndex
orig))
else (ARRAYBASE array))
(OR hiAddr 1)
(LLSH loWordAddr 1)
count))
(SWAP (\BUSBLTOUTSWAPBYTES (if arrayIndex
then (\ADDBASE (ARRAYBASE
array)
(IDIFFERENCE
arrayIndex
orig))
else (ARRAYBASE array))
(OR hiAddr 1)
(LLSH loWordAddr 1)
count))
(SHOULDNT "bad mode"))
else (SETERRORN 27 count)
(ERRORX)))
else (SETERRORN 27 array)
(ERRORX])
(PCBUS.TESTARRAY
[LAMBDA (array loWordAddr count mode arrayIndex hiAddr) (* ht: "26-May-85 18:52")
(* * read and compare words from the external pc memory to an array -
hiAddr is pcmem page number (defaults to 1), loWordAddr is word address on page. mode is either STRAIGHT
(or NIL) meaning bytes are stored hiOrder/loOrder, or SWAP meaning bytes are stored loOrder/hiOrder -
count is the number of words to transfer, and arrayIndex is the first element of the array to store into
(defaults to first element of array) -
Works for either 0 or 1 origin arrays. Works backwords until it finds an error or completes, and returns the offset
of the failing word -
i.e. 0 means success, n means (ELT array (PLUS (SUB1 n) arrayIndex)) is bad. Checks array references are in bounds,
but not PC ones because it will wrap around in case of overflow, which is probably what one wants.)
(if (count gt 0)
then (ELT array (IPLUS count -1)+(IPLUS (OR arrayIndex 1)
-1)+(ARRAYORIG array))
(* cheap bounds check)
(if (ARRAYTYP array)= 'SMALLPOSP
then (SELECTQ mode
((NIL STRAIGHT)
(\BUSBLTCHECKBYTES (if arrayIndex
then (\ADDBASE (ARRAYBASE array)
(IDIFFERENCE arrayIndex
(ARRAYORIG array))
)
else (ARRAYBASE array))
(OR hiAddr 1)
(LLSH loWordAddr 1)
count))
(SWAP (\BUSBLTCHECKSWAPBYTES (if arrayIndex
then (\ADDBASE (ARRAYBASE array)
(IDIFFERENCE
arrayIndex
(ARRAYORIG array)))
else (ARRAYBASE array))
(OR hiAddr 1)
(LLSH loWordAddr 1)
count))
(SHOULDNT "bad mode"))
else (ERROR "array must be of WORDs"])
)
(* define the \BUSBLT subopcodes in terms of the basic one)
(PUTPROPS \BUSBLTIN DOPVAL (4 BUSBLT 4))
(PUTPROPS \BUSBLTINBYTES DOPVAL (4 BUSBLT 5))
(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))
(PUTPROPS \BUSBLTCHECK DOPVAL (4 BUSBLT 20))
(PUTPROPS \BUSBLTCHECKBYTES DOPVAL (4 BUSBLT 21))
(PUTPROPS \BUSBLTCHECKSWAPBYTES DOPVAL (4 BUSBLT 22))
(DEFINEQ
(\BUSBLT.UFN
[LAMBDA (DLADR BUSADRH BUSADRL NWORDS ALPHABYTE) (* ht: "26-May-85 17:25")
(* * error 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)
(ERROR "Attempt to use busmaster on a machine which doesn't support it"])
)
(* dma controller%'s low level (command) functions)
(DEFINEQ
(BUSDMA.SETMODE
[LAMBDA (CHAN WRITEMEMORY? AUTOINIT? DECADDR?) (* ht: "25-May-85 12:55")
(* * set the channel%'s mode register. Assumes "single" mode)
(PCBUS.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) (* ht: "25-May-85 12:55")
(* * write the channel%'s page register. Note that the page register for channel 0 (the memory refresh channel) is
of no use.)
(PCBUS.OUTPUT (SELECTQ CHAN
(1 131)
(2 129)
(3 130)
(HELP "bad channel# arg:" CHAN))
PAGE])
(BUSDMA.SETADDRESS
[LAMBDA (CHAN ADDR) (* ht: "25-May-85 12:55")
(* * 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)))
(PCBUS.OUTPUT 12 0)
(PCBUS.OUTPUT CMD ADDR)
(PCBUS.OUTPUT CMD (LRSH ADDR 8])
(BUSDMA.READADDRESS
[LAMBDA (CHAN) (* ht: "26-May-85 18:53")
(* * 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.)
(LET ((CMD (LLSH CHAN 1)))
(PCBUS.OUTPUT 12 0)
(LOGOR (PCBUS.INPUT CMD)
(LLSH (PCBUS.INPUT CMD)
8])
(BUSDMA.SETCOUNTER
[LAMBDA (CHAN NBYTES) (* ht: "25-May-85 12:55")
(* * 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 (NBYTES-1))
(CMD (1+(LLSH CHAN 1]
(if (OR (ILEQ NBYTES 0)
(IGREATERP NBYTES 65536))
then (HELP "arg must be 1..64K:" NBYTES))
(PCBUS.OUTPUT 12 0)
(PCBUS.OUTPUT CMD NBYTESLESS1)
(PCBUS.OUTPUT CMD (LRSH NBYTESLESS1 8])
(BUSDMA.READCOUNTER
[LAMBDA (CHAN) (* ht: "26-May-85 18:56")
(* * 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.)
(LET [(CMD (IPLUS 1 (LLSH CHAN 1]
(PCBUS.OUTPUT 12 0)
(IPLUS (LOGOR (PCBUS.INPUT CMD)
(LLSH (PCBUS.INPUT CMD)
8))
1])
(BUSDMA.MASK
[LAMBDA (CHAN) (* ht: "25-May-85 12:55")
(* * prevent dma activity on a channel, by setting its bit in the controller%'s mask register)
(PCBUS.OUTPUT 10 4+CHAN])
(BUSDMA.UNMASK
[LAMBDA (CHAN) (* ht: "25-May-85 12:55")
(* * allow dma activity on a channel, by clearing its bit in the controller%'s mask register)
(PCBUS.OUTPUT 10 CHAN])
)
(* dma controller%'s higher level functions)
(DEFINEQ
(BUSDMA.INIT
[LAMBDA NIL (* ht: "25-May-85 12:55")
(* * 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 --)
(PCBUS.OUTPUT 3+TIMER 84)
(PCBUS.OUTPUT 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)
(PCBUS.OUTPUT MASTERCLEAR 0)
(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?) (* ht: "26-May-85 18:58")
(* * 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 global variable BUSDMA.TCBITS -- BUSDMA.INIT clears BUSDMA.TCBITS)
(LET ((MASK (LLSH 1 CHANNEL)))
BUSDMA.TCBITS←(LOGOR BUSDMA.TCBITS (PCBUS.INPUT 8))
(PROG1 (LOGAND BUSDMA.TCBITS MASK)
~=0
(if CLEARTHEBIT?
then BUSDMA.TCBITS←(LOGAND BUSDMA.TCBITS (LOGNOT MASK])
)
(RPAQQ BUSDMA.TCBITS 0)
(DECLARE: DOEVAL@COMPILE DONTCOPY
(GLOBALVARS BUSDMA.TCBITS)
)
(DECLARE: EVAL@COMPILE
(PUTPROPS BUSDMA.FASTUPDATEADDR MACRO (X (\FUATran (CAR X)
(CADR X)
(CADDR X))))
(PUTPROPS BUSDMA.SLOWUPDATEADDR MACRO (X (\SUATran (CAR X)
(CADR X)
(CADDR X))))
)
(PUTPROPS BUSDMA.FASTUPDATEADDR ARGNAMES (dmaChannel currentAddress wrapped))
(PUTPROPS BUSDMA.SLOWUPDATEADDR ARGNAMES (dmaChannel currentAddress wrapped))
(DEFINEQ
(\FUATran
[LAMBDA (dmaChannel currentAddress wrapped) (* ht: "22-Jun-85 18:01")
(if (AND (OR (NUMBERP dmaChannel)
(NUMBERP (EVAL dmaChannel)))
currentAddress wrapped (LITATOM currentAddress)
(LITATOM wrapped))
then
(* * Open coded all the way -
This is the fast, unsafe version -
For channel, which must be an explicit number updates currentAddress and wrapped, which must be variable names.
Generates an error if a double wrap has happened. See documentation of BUSMASTER for description of what this is
for.)
[BQUOTE (PROGN (PROGN (BX.OUTPUT 12 7)
(BX.OUTPUT 8 4)
(BX.OUTPUT 0 5))
(SETQ , currentAddress
(LOGOR (LRSH (PROGN (BX.OUTPUT (CONSTANT (LLSH , dmaChannel 1))
7)
(BX.OUTPUT 4 4)
(BX.OUTPUT 0 5)
(BX.INPUT 5))
1)
(LLSH (PROGN (BX.OUTPUT (CONSTANT (LLSH , dmaChannel 1))
7)
(BX.OUTPUT 4 4)
(BX.OUTPUT 0 5)
(BX.INPUT 5))
7)))
(* * Check the TC bit for this channel -
open coded for speed)
(if , wrapped
then (if [NOT (ZEROP (LOGAND (PROGN (BX.OUTPUT 8 7)
(BX.OUTPUT 4 4)
(BX.OUTPUT 0 5)
(BX.INPUT 5))
(CONSTANT (LLSH 1 , dmaChannel]
then (SETQ , wrapped 'DoubleWrap)
else T)
else (if [SETQ , wrapped
(NOT (ZEROP (LOGAND (PROGN (BX.OUTPUT 8 7)
(BX.OUTPUT 4 4)
(BX.OUTPUT 0 5)
(BX.INPUT 5))
(CONSTANT (LLSH 1 , dmaChannel]
then
(* * read address again to be sure to get past the end)
(PROGN (BX.OUTPUT 12 7)
(BX.OUTPUT 8 4)
(BX.OUTPUT 0 5))
(SETQ , currentAddress
(LOGOR (LRSH (PROGN (BX.OUTPUT (CONSTANT (LLSH ,
dmaChannel 1))
7)
(BX.OUTPUT 4 4)
(BX.OUTPUT 0 5)
(BX.INPUT 5))
1)
(LLSH (PROGN (BX.OUTPUT (CONSTANT (LLSH ,
dmaChannel 1))
7)
(BX.OUTPUT 4 4)
(BX.OUTPUT 0 5)
(BX.INPUT 5))
7)))
(* * if we%'ve wrapped again already, that means we were not paying attention for a long time before the current
round, and things are in bad shape)
(if [NOT (ZEROP (LOGAND (PROGN (BX.OUTPUT 8 7)
(BX.OUTPUT 4 4)
(BX.OUTPUT 0 5)
(BX.INPUT 5))
(CONSTANT (LLSH 1 , dmaChannel]
then (ERROR "double wrap 2" , dmaChannel)
else T]
else (ERROR "Invalid arguments - must be a number and two atoms" (LIST dmaChannel
currentAddress wrapped])
(\SUATran
[LAMBDA (dmaChannel currentAddress wrapped) (* ht: "24-Jun-85 09:11")
(* * update the address and wrapped flags safely)
(if (AND currentAddress wrapped (LITATOM currentAddress)
(LITATOM wrapped))
then [BQUOTE (LET ((channel , dmaChannel))
(BUSDMA.MASK channel)
(SETQ , currentAddress (BUSDMA.READADDRESS channel))
(PROG1 (if , wrapped
then (if (BUSDMA.READTCBIT channel T)
then 'DoubleWrap
else T)
else (SETQ , wrapped (BUSDMA.READTCBIT channel T)))
(BUSDMA.UNMASK channel]
else (ERROR "Invalid arguments - currentAddress and wrapped must be atoms" (LIST currentAddress
wrapped])
)
(* Busmaster and PC/Multibus connection checkout)
(DEFINEQ
(BUS.CHECKADDR
[LAMBDA (chan pat) (* ht: "26-May-85 19:00")
(* * loopback on dma address register)
(LET (result (cmd (LLSH chan 1)))
(PCBUS.OUTPUT 12 0)
(PCBUS.OUTPUT cmd pat)
(PCBUS.OUTPUT cmd (LRSH pat 8))
(if pat~=result←(LOGOR (PCBUS.INPUT cmd)
(LLSH (PCBUS.INPUT cmd)
8))
then result])
(BUS.CHECKCNT
[LAMBDA (chan pat) (* ht: "26-May-85 19:00")
(* * loopback on dma count register)
(LET (result (cmd (IPLUS (LLSH chan 1)
1)))
(PCBUS.OUTPUT 12 0)
(PCBUS.OUTPUT cmd pat)
(PCBUS.OUTPUT cmd (LRSH pat 8))
(if pat~=result←(LOGOR (PCBUS.INPUT cmd)
(LLSH (PCBUS.INPUT cmd)
8))
then result])
(BUS.CHECKOUT
[LAMBDA (quietFlg) (* ht: "26-May-85 18:16")
(* * Do an escalating series of loop-backs to check out the Busmaster card)
(BUS.RESET)
(* * the following is just my best guess to date at how to tell whether there is anything out there -
may be wrong e.g. for case where a multibus is attached or under other circumstances)
(AND (SELECTQ (LOGAND (BX.INPUT 4)
63679)
((47287 14519 14518 47286)
T)
(PROGN (printout T
"Either the busmaster is powered down, or there isn't anything connected to the parallel I/O port where the busmaster should be - please check that the busmaster is indeed cabled up to the bottom socket on the CPE (3) board of the Dandetiger and that it has power."
T)
NIL))
(if (bind result for i from 0 to 15 never (if result←(BMSTATLOOP i)
then (printout T "Status loopback failure: " #
(STATPRINT i)
"in," 25 # (STATPRINT result)
"out." T)
T))
then (if (NOT quietFlg)
then (printout T "Status loopback OK" T))
T)
(if (bind result for i from 0 to 255
never (if result←(BM8LOOP i)
then (printout T "8-bit data loopback failure: " .I2.16 i " in," 29 .I2.16
result " out." T)
T))
then (if (NOT quietFlg)
then (printout T "8-bit data loopback OK" T))
T)
(if (bind result for i from 0 to 255 never (if result←(BM16LOOP (LOGOR i (LLSH i 8)))
then (printout T
"16-bit data loopback failure: "
.I4.16
(LOGOR i (LLSH i 8))
" in," 30 .I4.16 result
" out."
T)
T))
then (if (NOT quietFlg)
then (printout T "16-bit data loopback OK" T))
T)
(if [bind result for chan from 0 to 3
always (for pat in '(0 65535)
never (OR (if result←(BUS.CHECKADDR chan pat)
then (printout T
"DMA channel address loopback failure on channel "
chan ": " .I4.16 pat " in," 51 .I4.16 result
" out."
T)
T)
(if result←(BUS.CHECKCNT chan pat)
then (printout T
"DMA channel counter loopback failure on channel "
chan ": " .I4.16 pat " in," 51 .I4.16 result
" out."
T)
T]
then (if (NOT quietFlg)
then (printout T "DMA loopback OK" T))
T])
(BM16LOOP
[LAMBDA (D) (* ht: "22-Apr-85 16:19")
(* * loop back check of the busmaster data register -
write to MB memory and read back data register)
(LET (result)
(BX.OUTPUT 15 6)
(BX.OUTPUT 0 7)
(BX.OUTPUT 33026 4)
(BX.OUTPUT D 5)
result←(BX.INPUT 5)
(if D~=result
then result])
(BM8LOOP
[LAMBDA (D) (* ht: "22-Apr-85 15:42")
(* * loop back check of the busmaster data register low half -
write to PC memory and read back data register)
(LET (result)
(BX.OUTPUT 15 6)
(BX.OUTPUT 0 7)
(BX.OUTPUT 2 4)
(BX.OUTPUT D 5)
result←(BX.INPUT 5)
(if D~=result
then result])
(BMSTATLOOP
[LAMBDA (pat) (* ht: "26-May-85 19:11")
(* * do a simple loop-back from the command and address registers back thru the status register -
pat is interpreted as Test:Addr16:Addr8:Addr0)
(LET (result status)
(BX.OUTPUT (LRSH pat 2)
6)
(BX.OUTPUT (LOGOR (LLSH pat 7)
pat)
7)
(BX.OUTPUT (LOGOR (LLSH (LOGAND 8 pat)
3)
1)
4)
(BX.OUTPUT 0 5)
status←(BX.INPUT 4)
(if pat~=result←(LOGOR (LRSH (LOGAND 256 status)
5)
(LRSH (LOGAND (IPLUS 1024 512)
status)
8)
(LRSH (LOGAND 64 status)
6))
then result])
(MB.CHECKOUT
[LAMBDA (quietFlg) (* ht: "26-May-85 18:37")
"Not implemented yet"])
(MBRCVR.CHECKOUT
[LAMBDA (quietFlg) (* ht: "26-May-85 18:37")
"Not implemented yet"])
(MBMEM.PRELIMCHECK
[LAMBDA (pageNumber quietFlg) (* ht: "26-May-85 18:37")
"Not implemented yet"])
(PC.CHECKOUT
[LAMBDA (quietFlg) (* ht: "26-May-85 18:22")
(BUS.RESET)
(if (AND (BUS.CHECKOUT quietFlg)
(PCRCVR.CHECKOUT quietFlg)
(PCMEM.PRELIMCHECK NIL quietFlg))
then (BUS.RESET)
(BUSDMA.INIT)
T])
(PCRCVR.CHECKOUT
[LAMBDA (quietFlg) (* ht: "26-May-85 18:16")
(* * some simple loop back checks to see if the busmaster is cabled to a working receiver card on a PC backplane)
(BUS.RESET)
(PCBUS.OUTPUT 532 0)
(AND (if (PCBUS.INPUT 532)=255
then (printout T
"The PC appears to be powered down or not connected -
please check and try again"
T)
NIL
else T)
(if (bind result for i from 0 to 255
never (PCBUS.OUTPUT 532 i)
(if i~=result←(PCBUS.INPUT 532)
then (printout T "Receiver data register loopback failure: " .I2.16 i
" in,"
41 .I2.16 result " out." T)
T))
then (if (NOT quietFlg)
then (printout T "Receiver data register loopback OK" T))
T)
(if (bind result for i from 0 to 255
never (PCBUS.WRITEHL 15 (LOGOR (LLSH i 8)
i)
255)
(OR (if i~=result←(PCBUS.INPUT 533)
then (printout T "Receiver addr-hi register loopback failure: " .I2.16
i " in," 44 .I2.16 result " out." T)
T)
(if i~=result←(PCBUS.INPUT 534)
then (printout T "Receiver addr-lo register loopback failure: " .I2.16
i " in," 44 .I2.16 result " out." T)
T)))
then (if (NOT quietFlg)
then (printout T "Receiver address registers loopback OK" T))
T])
(PCMEM.PRELIMCHECK
[LAMBDA (pageNumber quietFlg) (* ht: "26-May-85 18:17")
(* * run some simple tests to validate the 1109-Busmaster-PCmemory paths and contents -
assumes that BUS.CHECKOUT and PCRCVR.CHECKOUT have been run successfully)
(LET ((pages (for i from 0 to (IMAX (OR pageNumber 0)
15)
when (AND (PROGN (PCBUS.WRITEHL i 0 0)
(PCBUS.READHL i 0)=0)
(PROGN (PCBUS.WRITEHL i 0 255)
(PCBUS.READHL i 0)=255))
collect i)))
(if pages=NIL
then (printout T
"There does not appear to be any memory connected to the PC in page address range 0 - "
(IMAX (OR pageNumber 0)
15)
"." T
"Please check that the busmaster and PC are powered up and running correctly by calling (BUS.CHECKOUT) and (PCRCVR.CHECKOUT), and check that there is at least one memory board installed in the PC. If that doesn't help, check the page address switches on the memory board to see that they are in the indicated range."
T)
NIL
else (if (NOT quietFlg)
then (printout T "Memory there OK" T))
T])
(STATPRINT
[LAMBDA (statbits) (* ht: "22-Apr-85 15:33")
(for i from 3 to 0 by -1 as label in '(test a16 a8 a0) do (printout NIL label ":"
(LOGAND 1 (LRSH statbits i))
,])
)
(FILESLOAD (SYSLOAD)
BUSEXTENDER)
(DECLARE: DONTEVAL@LOAD DOEVAL@COMPILE DONTCOPY
(FILESLOAD (LOADCOMP)
BUSEXTENDER)
)
(PUTPROPS BUSMASTER COPYRIGHT ("Xerox Corporation" 1984 1985))
(DECLARE: DONTCOPY
(FILEMAP (NIL (1881 8593 (BUS.RESET 1891 . 2511) (MBUS.INPUT 2513 . 2970) (MBUS.OUTPUT 2972 . 3386) (
MBUS.READ 3388 . 3655) (MBUS.READHL 3657 . 4167) (MBUS.WRITE 4169 . 4449) (MBUS.WRITEHL 4451 . 4918) (
PCBUS.INPUT 4920 . 5314) (PCBUS.OUTPUT 5316 . 5668) (PCBUS.READ 5670 . 5937) (PCBUS.READHL 5939 . 6387
) (PCBUS.READWORD 6389 . 7112) (PCBUS.WRITE 7114 . 7395) (PCBUS.WRITEHL 7397 . 7802) (PCBUS.WRITEWORD
7804 . 8591)) (8668 15337 (PCBUS.READARRAY 8678 . 10978) (PCBUS.WRITEARRAY 10980 . 13297) (
PCBUS.TESTARRAY 13299 . 15335)) (15931 16494 (\BUSBLT.UFN 15941 . 16492)) (16555 20048 (BUSDMA.SETMODE
16565 . 16990) (BUSDMA.SETPAGE 16992 . 17390) (BUSDMA.SETADDRESS 17392 . 17870) (BUSDMA.READADDRESS
17872 . 18334) (BUSDMA.SETCOUNTER 18336 . 19027) (BUSDMA.READCOUNTER 19029 . 19537) (BUSDMA.MASK 19539
. 19792) (BUSDMA.UNMASK 19794 . 20046)) (20102 22350 (BUSDMA.INIT 20112 . 21591) (BUSDMA.READTCBIT
21593 . 22348)) (22876 26881 (\FUATran 22886 . 26059) (\SUATran 26061 . 26879)) (26940 36156 (
BUS.CHECKADDR 26950 . 27397) (BUS.CHECKCNT 27399 . 27865) (BUS.CHECKOUT 27867 . 30672) (BM16LOOP 30674
. 31106) (BM8LOOP 31108 . 31544) (BMSTATLOOP 31546 . 32325) (MB.CHECKOUT 32327 . 32462) (
MBRCVR.CHECKOUT 32464 . 32603) (MBMEM.PRELIMCHECK 32605 . 32746) (PC.CHECKOUT 32748 . 33065) (
PCRCVR.CHECKOUT 33067 . 34638) (PCMEM.PRELIMCHECK 34640 . 35870) (STATPRINT 35872 . 36154)))))
STOP