SysIII/usr/src/uts/vax/up/dzb/output.s
/*
* Output segment
*/
.org 1024
seg1:
/*
* The code in this segment is entered via label 'outreq' when it is
* recognized that a DZ11 has requested an output character
*/
statesw:
br disable
br odrst1
br odrst2
br odrst3
br odrst4
br odrst5
ERROR(INVALCD)
br .
/*
* The following table of jump instructions is accessed by a
* calculated branch instruction using the ASCII character
* as index. It provides a fast implementation of tests
* for specific control characters
*/
charsw:
br sendit /* 0 - NUL */
br sendit /* 1 - SOH */
br sendit /* 2 - STX */
br sendit /* 3 - ETX */
br sendit /* 4 - EOT */
br sendit /* 5 - ENQ */
br sendit /* 6 - ACK */
br sendit /* 7 - BEL */
br isbs /* 010 - BS */
br isht /* 011 - HT */
br isnl /* 012 - NL */
br isvt /* 013 - VT */
br isff /* 014 - FF */
br iscr /* 015 - CR */
br sendit /* 016 - SO */
br sendit /* 017 - SI */
br sendit /* 020 - DLE */
br sendit /* 021 - DC1 */
br sendit /* 022 - DC2 */
br sendit /* 023 - DC3 */
br sendit /* 024 - DC4 */
br sendit /* 025 - NAK */
br sendit /* 026 - SYN */
br sendit /* 027 - ETB */
br sendit /* 030 - CAN */
br sendit /* 031 - EM */
br sendit /* 032 - SUB */
br sendit /* 033 - ESC */
br sendit /* 034 - FS */
br sendit /* 035 - GS */
br sendit /* 036 - RS */
br sendit /* 037 - US */
/*
* Entered here from main segment
*/
outreq:
/*
* The DZ11 has requested an output character. Get the line
* number and look up the address of the line-table entry.
* Save the address of the line-table entry in register r10.
*/
mov idh,brg
mov 7,r7
and brg,r7,r7|mar
mov mem,r10|mar
/*
* Get flags
*/
mov FLAGS1,brg
add brg,r10,mar
mov mem,r0
/*
* If a break is being sent then go to disable
*/
mov OUTBRK,brg
orn brg,r0,-
brz disable
/*
* See if there is an express character
*/
mov ~SNDEXP,brg
or brg,r0,-
brz 1f
br 2f
/*
* Send express character reguardless of state of line
*/
1:
and brg,r0,mem
mov EXPCHR,brg
add brg,r10,mar
mov mem,odl
br sendit
2:
/*
* If TTSTOP is set then go to disable
*/
mov TTSTOP,brg
orn brg,r0,-
brz disable
/*
* Get OFLAG into r6
*/
mov OFLAG,brg
add brg,r10,mar
mov mem,r6
/*
* Get the current state of this line
*/
mov STATE,brg
add brg,r10,mar
mov mem,r0
/*
* If state == 0 then go to disable
* else if state == 1 then go to odrst1
* else if state == 2 then go to odrst2
* else if state == 3 then go to odrst3
* else if state == 4 then go to odrst4
* else if state == 5 then go to odrst5
*/
mov statesw,brg
br (add,brg,r0),%statesw
/*
* Output data request with state == 1 (sending normal data)
*/
odrst1:
/*
* If there is a saved byte to be sent then go to sendsave
*/
mov FLAGS,brg
add brg,r10,mar
mov mem,brg
br4 sendsave
/*
* If there are no characters remaining in the current
* buffer for this line then go to odrst1a
*/
mov NCH,brg
add brg,r10,mar
mov mem,r0
dec r0,-
brz odrst1a
/*
* Decrement the number of characters remaining in the current
* buffer for this line
*/
dec r0
mov r0,mem
/*
* If this was the last character queue the line
*/
dec r0,-
brc odrst1b
CALL(oqueue)
mov %dzst,brg
add brg,r8,%mar
br odrst1b
/*
* There are no more characters remaining in the current
* buffer for this line
*/
odrst1a:
/*
* If the host computer has not yet presented a new buffer then
* go to nomore
*/
mov OUTBUF,brg
add brg,r10,mar
mov mem,r4
brz nomore
/*
* Get the buffer address from the queue entry
*/
mov 03,brg
and brg,r4,%mar
mov ~03,brg
and brg,r4,mar
mov 0,r0|mar++
mov mem,r3|mar++
mov mem,r2|mar++
mov mem,r1
mov 3,brg
and brg,r1
/*
* Set the page register to the page for this DZ11
*/
mov %dzst,brg
add brg,r8,%mar
/*
* Get the index of the first and last characters
*/
mov C_FIRST,brg
add brg,r3,brg
mov brg,ial
adc r2,brg
mov brg,iah
adc r1,brg
mov brg,r0
mov 3,brg
and brg,r0
asl r0
asl r0
mov NRQ,brg
or brg,r0,npr
BUSWAIT(buserr1)
/*
* Compute the character count - 1 for the new output
* buffer and record the result as the remaining character
* count for the current buffer.
*/
mov NCH,brg
add brg,r10,mar
mov idh,r0
mov idl,brg
sub brg,r0
dec r0
mov r0,mem
/*
* If there was only one character in this buffer release it
*/
dec r0,-
brc 1f
CALL(oqueue)
mov %dzst,brg
add brg,r8,%mar
1:
/*
* Set bufad = address of the first character
*/
mov BUFAD,brg
add brg,r10,mar
mov idl,r0
mov C_DATA,brg
add brg,r0,brg
add brg,r3,mem|mar++
adc r2,mem|mar++
adc r1,mem
/*
* If the buffer address is even then go to odrst1c
*/
mov BUFAD,brg
add brg,r10,mar
mov mem,brg
br0 1f
br odrst1c
1:
/*
* Clear the low-order bit of the buffer address
*/
mov 1,r1
xor mem,r1,mem
/*
* Fetch two bytes
*/
mov mem,ial|mar++
mov mem,iah|mar++
mov mem,r0
mov 3,brg
and brg,r0
asl r0
asl r0
mov NRQ,brg
or brg,r0,npr
BUSWAIT(buserr1);
/*
* Save the high-order byte as the current output character
*/
mov idh,odl
/*
* Set buffer address += 2
*/
mov BUFAD,brg
add brg,r10,mar
mov 2,r2
add mem,r2,mem|mar++
mov mem,r0
adc r0,mem|mar++
mov mem,r0
adc r0,mem
/*
* Go to sendtest
*/
br sendtest
/*
* The DZ has just started sending the last byte of the
* current output buffer. Call oflush which just
* bookkeeps the lte and dispable the line.
* The next buffer-send command will reactivate the line.
*/
nomore:
CALL(oflush)
mov %dzst,brg
add brg,r8,%mar
br disable
/*
* Output data request with non-empty buffer
*/
odrst1b:
/*
* If there is a high-order byte to send then go to sendhigh
*/
mov FLAGS,brg
add brg,r10,mar
mov mem,brg
br1 sendhigh
/*
* We need to get another word of data for this line.
*/
odrst1c:
/*
* Get the buffer address field of the line-table entry,
* then set up a unibus request for the next two bytes.
*/
mov BUFAD,brg
add brg,r10,mar
mov mem,ial|mar++
mov mem,iah|mar++
mov mem,r0
asl r0
asl r0
mov NRQ,brg
or brg,r0,npr
/*
* Wait for the unibus transfer to complete.
* If an error occurs then go to buserr1.
*/
BUSWAIT(buserr1)
/*
* Set the bit that says to send the high-order byte
*/
mov FLAGS,brg
add brg,r10,mar
mov SENDHIGH,brg
mov mem,r0
or brg,r0,mem|mar++
/*
* Save the high-order data byte in the line-table entry
*/
mov HIBYTE,brg
add brg,r10,mar
mov idh,mem
/*
* Move the low-order data byte to the output data register
*/
mov idl,odl
/*
* Increment the buffer address
*/
mov BUFAD,brg
add brg,r10,mar
mov 2,r2
add mem,r2,mem|mar++
mov mem,r2
adc r2,mem|mar++
mov mem,r2
adc r2,mem
/*
* Go to sendtest
*/
br sendtest
/*
* Prepare to send the high-order byte.
*/
sendhigh:
/*
* Move the high-order data byte from the line-table entry
* to the output data register
*/
mov HIBYTE,brg
add brg,r10,mar
mov mem,odl
/*
* Clear the flag that says to send the high-order byte
*/
mov FLAGS,brg
add brg,r10,mar
mov mem,r0
mov ~SENDHIGH,brg
and brg,r0,mem
/*
* Go to sendtest
*/
br sendtest
/*
* Prepare to send the byte in SAVECHAR
*/
sendsave:
/*
* Clear the flag that says there is a saved byte to be sent
*/
mov ~SENDSAVE,brg
mov mem,r0
and brg,r0,mem
/*
* Move the saved byte into odl
*/
mov SAVECHAR,brg
add brg,r10,mar
mov mem,odl
/*
* Go to sendtest
*/
br sendtest
/*
* The following code acts as a filter for outgoing characters
*/
sendtest:
/*
* Get output flags
*/
mov OFLAG,brg
add brg,r10,mar
mov mem,r6
/*
* If output post-processing is not enabled then go to sendit
*/
mov OPOST,brg
orn brg,r6,-
brz 1f
br sendit
1:
/*
* Get the delays
*/
mov DELAYS,brg
add brg,r10,mar
mov mem,r5
/*
* Get the output character
*/
mov odl,r0
/*
* If the character is a control character then go to iscc
*/
mov 040,brg
sub brg,r0,-
brc 1f
br iscc
1:
/*
* If the character is a DEL then go to sendit
*/
mov 0177,brg
addn brg,r0,-
brz sendit
/*
* Increment the column pointer
*/
mov ICOL,brg
add brg,r10,mar
mov mem,r1
inc r1,mem
/*
* If OLCUC is set then translate lower case alpha to upper case
*/
mov OLCUC,brg
orn brg,r6,-
brz 1f
br 2f
1:
mov 'a',brg
sub brg,r0,-
brc 1f
br 2f
1:
mov 'z',brg
addn brg,r0,-
brc 2f
mov ~040,brg
and brg,r0
mov r0,odl
2:
/*
* Go to sendit
*/
br sendit
/*
* Process an ASCII control character
*/
iscc:
/*
* If the character is a backspace then go to isbs;
* else if the character is a horizontal tab then go to isht;
* else if the character is a newline then go to isnl;
* else if the character is a vertical tab then go to isvt;
* else if the character is a form-feed then go to isff;
* else if the character is a carriage return then go to iscr;
* else go to sendit
*/
mov charsw,brg
br (add,brg,r0),%charsw
/*
* Process a newline character
*/
isnl:
/*
* If ONLRET is set then go to iscr2
*/
mov ONLRET,brg
orn brg,r6,-
brz iscr2
/*
* If we are not expanding NL for this line then go to nlpart3
*/
mov ONLCR,brg
orn brg,r6,-
brz 1f
br nlpart3
1:
/*
* If column pointer == 0 and ONOCR is set then go to iscr2.
* (We omit the carriage return in this case.)
*/
mov ICOL,brg
add brg,r10,mar
mov mem,r0
dec r0,-
brc 1f
mov ONOCR,brg
orn brg,r6,-
brz iscr2
1:
/*
* If this NL has already been expanded then go to nlpart2
*/
mov FLAGS,brg
add brg,r10,mar
mov mem,brg
br0 nlpart2
/*
* Set flags to indicate that there is a saved byte in SAVECHAR
* and that the NL character has already been expanded
*/
mov SENDSAVE|NLEXP,brg
mov mem,r0
or brg,r0,mem
/*
* Put a new-line character into SAVECHAR
*/
mov SAVECHAR,brg
add brg,r10,mar
mov NL,mem
/*
* Put a carriage-return character into odl
*/
mov CR,brg
mov brg,odl
/*
* Go to sendit
*/
br sendit
/*
* Part two of newline character processing
*
* The generated carriage return has already been sent.
*
* At this point we just have to send the saved newline character
* and generate the appropriate time delay, if any.
*/
nlpart2:
/*
* Clear the flag which indicates that this particular newline
* has already been expanded
*/
mov FLAGS,brg
add brg,r10,mar
mov mem,r0
mov ~NLEXP,brg
and brg,r0,mem
/*
* Go to iscr2
*/
br iscr2
/*
* Process a carriage-return character
*/
iscr:
/*
* If translate-CR-to-NL is set then go to xmtnl
*/
mov OCRNL,brg
orn brg,r6,-
brz xmtnl
/*
* If at col 0 and ONOCR is set do not send out carriage return
*/
mov ICOL,brg
add brg,r10,mar
mov mem,r2
dec r2
brc iscr2
mov ONOCR,brg
orn brg,r6,-
brz odrst1
/*
* Entered here from isnl
*/
iscr2:
/*
* Save column pointer
*/
mov ICOL,brg
add brg,r10,mar
mov mem,r2
/*
* Set column pointer = 0
*/
mov 0,mem
/*
* Get delay type for carriage-return.
* If delay type == 0 then go to sendit
* else if delay type == 1 then go to cr1
* else if delay type == 2 then go to cr2
* else go to cr3
*/
mov CRDELAY,brg
and brg,r5,brg
mov 0,brg>>
br1 1f
br0 cr1
br sendit
1:
br0 cr3
br cr2
/*
* Carriage-return delay type 1
*/
cr1:
/*
* If OFILL is set then go to filltwo
*/
mov OFILL,brg
orn brg,r6,-
brz filltwo
/*
* Set delay ticks = (icol>>4)+3
*/
mov 017<<4,brg
and brg,r2,brg
mov brg,brg>>
mov brg,brg>>
mov brg,brg>>
mov brg,brg>>
mov 3,r3
add brg,r3
/*
* If delay > 6 then set delay = 6
*/
mov 6,brg
sub brg,r3,-
brc 1f
mov r3,brg
1:
/*
* Go to delay
*/
br delay
/*
* Carriage-return delay type 2
*/
cr2:
/*
* If OFILL is set then go to fillfour
*/
mov OFILL,brg
orn brg,r6,-
brz fillfour
/*
* Schedule a delay
*/
mov 5,brg
/*
* Go to delay
*/
br delay
/*
* Carriage-return delay type 3
*/
cr3:
/*
* If OFILL is set then go to fill40
*/
mov OFILL,brg
orn brg,r6,-
brz fill40
/*
* Schedule a .15 second delay
*/
mov 9,brg
/*
* Go to delay
*/
br delay
/*
* Translate carriage return to newline
*/
xmtnl:
mov NL,brg
mov brg,odl
br nlpart3
/*
* Entered here from isnl when neither ONLRET nor ONLCR is set
*/
nlpart3:
/*
* If newline delay is not enabled then go to sendit
*/
mov NLDELAY,brg
orn brg,r5,-
brz 1f
br sendit
1:
/*
* Schedule a .083 second delay
*/
mov 5,brg
/*
* Go to delay
*/
br delay
/*
* Process a horizontal tab control character.
*/
isht:
/*
* If we are expanding tabs into spaces then go to ht3
*/
mov HTDELAY,brg
orn brg,r5,-
brz ht3
/*
* Save the column pointer
*/
mov ICOL,brg
add brg,r10,mar
mov mem,r2
/*
* Update the column pointer
*/
mov mem,r1
mov 7,brg
or brg,r1
inc r1,mem
/*
* Get the delay type for horizontal tabs. If the delay type is
* one then go to ht1; else if the delay type is two then go to ht2;
* else go to sendit
*/
mov HTDELAY,brg
and brg,r5,brg
mov 0,brg>>
mov 0,brg>>
mov 0,brg>>
br0 ht1
br1 ht2
br sendit
/*
* HT delay type 1
*/
ht1:
/*
* If OFILL is set then go to filltwo
*/
mov OFILL,brg
orn brg,r6,-
brz filltwo
/*
* Calculate delay ticks = 1 - (icol|~7)
*/
mov 7,brg
orn brg,r2,brg
mov 1,r1
sub brg,r1
/*
* If delay < 5 then go to sendit
*/
mov 5,brg
sub brg,r1,-
brc sendit
mov r1,brg
/*
* Go to delay
*/
br delay
/*
* HT delay type 2
*/
ht2:
/*
* If OFILL is set then go to filltwo
*/
mov OFILL,brg
orn brg,r6,-
brz filltwo
/*
* Schedule a .1 second delay
*/
mov 6,brg
/*
* Go to delay
*/
br delay
/*
* HT delay type 3: Expand horizontal tab into spaces
*/
ht3:
/*
* Calculate the number of spaces needed
*
* The number is calculated by evaluating 7 & ~icol
*/
mov ICOL,brg
add brg,r10,mar
mov 0,r0
orn mem,r0
mov 7,brg
and brg,r0
/*
* Update the column pointer
*/
mov mem,r1
or brg,r1
inc r1,mem
/*
* Save the count of the number of spaces needed
*/
mov COUNT,brg
add brg,r10,mar
mov r0,mem
/*
* Put a space into odl
*/
mov SP,brg
mov brg,odl
/*
* Set state = 3 (expanding horizontal tab)
*/
mov STATE,brg
add brg,r10,mar
mov 3,mem
/*
* Go to sendit
*/
br sendit
/*
* Process a backspace character
*/
isbs:
/*
* If the column pointer is not already zero then decrement it
*/
mov ICOL,brg
add brg,r10,mar
mov mem,r1
dec r1
brz 1f
mov r1,mem
1:
/*
* If backspace delays have not been requested then go to sendit
*/
mov BSDELAY,brg
orn brg,r5,-
brz 1f
br sendit
1:
/*
* If OFILL is set then go to fillone
*/
mov OFILL,brg
orn brg,r6,-
brz fillone
/*
* Schedule a .05 second delay
*/
mov 3,brg
/*
* Go to delay
*/
br delay
/*
* Process a vertical-tab character
*/
isvt:
/*
* If form-feed delays have not been requested then go to sendit
*/
mov VTDELAY,brg
orn brg,r5,-
brz 1f
br sendit
1:
/*
* Schedule a two-second delay
*/
mov 127,brg
/*
* Go to delay
*/
br delay
/*
* Process a form-feed character
*/
isff:
/*
* If form-feed delays have not been requested then go to sendit
*/
mov FFDELAY,brg
orn brg,r5,-
brz 1f
br sendit
1:
/*
* Schedule a two-second delay
*/
mov 127,brg
/*
* Go to delay
*/
br delay
/*
* Schedule one fill character
*/
fillone:
mov 1,brg
br fdelay
/*
* Schedule two fill characters
*/
filltwo:
mov 2,brg
br fdelay
/*
* Schedule four fill characters
*/
fillfour:
mov 4,brg
br fdelay
/*
* Schedule the appropriate number of fill characters for a
* Teletype 40 printer or a GE Terminet 1200
*/
fill40:
mov 36,brg
sub brg,r2,brg
brc sendit
mov 0,r0
sub brg,r0,brg
br fdelay
/*
* Schedule a time delay on a given line
*
* The amount of delay needed has already been calculated.
* Register brg contains the number of 16.7 msec ticks needed
* for the delay. The character which requires time fill has not
* yet been passed to the DZ11.
*/
delay:
/*
* If delay == 0 then go to sendit
*/
mov brg,r1
dec r1
brz sendit
/*
* Add 6 to the delay count and save the result in the LTE
*
* The reason for adding 6 to the delay count is roughly as follows:
*
* 6/60 = .1 second, which is one character time at 110 baud;
* this compensates for the double-buffering in the DZ11;
* at speeds greater than 110 baud it overcompensates, but this is
* traditional
*/
mov COUNT,brg
add brg,r10,mar
mov 6,brg
add brg,r1,mem
/*
* Set STATE = 2
*/
mov STATE,brg
add brg,r10,mar
mov 2,mem
/*
* Go to sendit
*/
br sendit
/*
* Schedule a time delay on a given line
*
* The amount of delay needed has already been calculated.
* Register brg contains the number of character times needed
* for the delay. The character which requires time fill has not
* yet been passed to the DZ11.
*
* This code differs from the delay code above by using fill
* characters rather than timed pauses
*/
fdelay:
/*
* If delay == 0 then go to sendit
*/
mov brg,r1
dec r1,-
brz sendit
/*
* Put the delay count in the lte
*/
mov COUNT,brg
add brg,r10,mar
mov r1,mem
/*
* Set STATE = 4 (Sending fill characters)
*/
mov STATE,brg
add brg,r10,mar
mov 4,mem
/*
* Go to sendit
*/
br sendit
/*
* Output data request with state == 2 (sending a character that needs
* time fill)
*
* Note: The line was put into state 2 when we passed the
* character that needs time fill to the DZ11. Since the DZ11
* is double-buffered, we get another output data request when
* the DZ11 actually starts sending the character that needs
* time fill.
* At this point we turn off the enable bit and put the lte into the
* twait state.
*
* Note that, because of double-buffering in the DZ11, the wait
* time is overlapped with the time required to send the character
* that needs time fill.
*/
odrst2:
/*
* Put this lte into the twait state
*/
mov r10,mar
mov 5,mem
/*
* Go to disable
*/
br disable
/*
* Output data request with state == 3 (expanding horizontal tab)
*/
odrst3:
/*
* Decrement the count field of the lte. If the result is
* negative then go to resume
*/
mov COUNT,brg
add brg,r10,mar
mov mem,r0
dec r0,mem
brz resume
/*
* Put a space character into odl
*/
mov SP,brg
mov brg,odl
/*
* Go to sendit
*/
br sendit
/*
* Output data request with state == 4 (sending fill characters)
*/
odrst4:
/*
* Decrement the count field of the lte. If the result is
* negative then go to resume
*/
mov COUNT,brg
add brg,r10,mar
mov mem,r0
dec r0,mem
brz resume
/*
* Put a fill character into odl
*/
mov DEL,brg
mov brg,odl
mov OFDEL,brg
orn brg,r6,-
brz 1f
mov NUL,brg
mov brg,odl
1:
/*
* Go to sendit
*/
br sendit
/*
* Output data request with state == 5 (twait)
*
* This may happen if an express character has been sent while in this state
*/
odrst5:
br disable
/*
* The following code is used to restart a line which has been
* delaying or expanding a horizontal tab character
*/
resume:
/*
* Set state = 1 (sending normal data)
*/
mov STATE,brg
add brg,r10,mar
mov 1,mem
/*
* Go to odrst1
*/
br odrst1
/*
* Send one character on the specified line. The character to be
* sent has already been placed in odl
*/
sendit:
/*
* Set up a unibus request to put one byte into TBUF
*/
mov csrget,mar
mov mem,r0|mar++
mov mem,r1|mar++
mov mem,r2
mov 6,brg
add brg,r0,oal
adc r1,brg
mov brg,oah
adc r2
mov nprx,r0
mov VEC4,brg
and brg,r0
asl r2
asl r2,brg
or brg,r0,nprx
mov BYTE|OUT|NRQ,brg
mov brg,npr
/*
* Wait for the unibus transfer to complete.
* If an error occurs then go to buserr1.
*/
BUSWAIT(buserr1)
/*
* Go to dispret
*/
br dispret
/*
* Set the break bit in the dz. This code is entered from
* cmdin after output is drained.
*/
break:
/*
* Set up a unibus request to set the break bit
*/
mov enblbits,brg
add brg,r7,mar
mov %enblbits,%mar
mov mem,r0
mov brkbits,mar
mov %dzst,brg
add brg,r8,%mar
or mem,r0,mem
mov mem,odh
mov csrget,mar
mov mem,r0|mar++
mov mem,r1|mar++
mov mem,r2
mov 7,brg
add brg,r0,oal
adc r1,brg
mov brg,oah
adc r2
mov nprx,r0
mov VEC4,brg
and brg,r0
asl r2
asl r2,brg
or brg,r0,nprx
mov BYTE|OUT|NRQ,brg
mov brg,npr
/*
* Wait for the unibus transfer to complete.
* If an error occurs then go to buserr1.
*/
BUSWAIT(buserr1)
/*
* Set OUTBRK
*/
mov FLAGS1,brg
add brg,r10,mar
mov mem,r0
mov OUTBRK,brg
or brg,r0,mem
/*
* Delay for 250 milliseconds before turning off the break bit
*/
mov COUNT,brg
add brg,r10,mar
mov 15,mem
/*
* Set state = 5
*/
mov STATE,brg
add brg,r10,mar
mov 5,mem
/*
* Return to caller
*/
RETURN
/*
* The following code is used to turn off the break bit
*/
ubreak:
/*
* Clear the KMC copy of the break bit for this line
* and set up a unibus request to clear the corresponding bit
* in the DZ11
*/
mov enblbits,brg
add brg,r7,mar
mov %enblbits,%mar
mov mem,r0
mov brkbits,mar
mov %dzst,brg
add brg,r8,%mar
and mem,r0
xor mem,r0,mem
mov mem,odh
mov csrget,mar
mov mem,r0|mar++
mov mem,r1|mar++
mov mem,r2
mov 7,brg
add brg,r0,oal
adc r1,brg
mov brg,oah
adc r2
mov nprx,r0
mov VEC4,brg
and brg,r0
asl r2
asl r2,brg
or brg,r0,nprx
mov BYTE|OUT|NRQ,brg
mov brg,npr
/*
* Wait for the unibus transfer to complete.
* If an error occurs then go to buserr1.
*/
BUSWAIT(buserr1)
/*
* Reset OUTBRK
*/
mov FLAGS1,brg
add brg,r10,mar
mov mem,r0
mov ~OUTBRK,brg
and brg,r0,mem
/*
* Schedule a delay for uart to reset
*/
mov COUNT,brg
add brg,r10,mar
mov 2,mem
/*
* Return to caller
*/
RETURN
/*
* Subroutine to enable a line
*/
enable:
/*
* Set up a unibus request to enable the line
*/
mov enblbits,brg
add brg,r7,mar
mov %enblbits,%mar
mov mem,r0
mov actline,mar
mov %dzst,brg
add brg,r8,%mar
or mem,r0,mem
mov mem,odl
mov csrget,mar
mov mem,r0|mar++
mov mem,r1|mar++
mov mem,r2
mov 4,brg
add brg,r0,oal
adc r1,brg
mov brg,oah
adc r2
mov nprx,r0
mov VEC4,brg
and brg,r0
asl r2
asl r2,brg
or brg,r0,nprx
mov BYTE|OUT|NRQ,brg
mov brg,npr
/*
* Wait for the unibus transfer to complete.
* If an error occurs then go to buserr0.
*/
BUSWAIT(buserr1)
/*
* Return to caller
*/
RETURN
/*
* The following code is used to turn off the transmit-enable bit
* at the beginning of a timed delay period or when there are no
* characters to transmit
*/
disable:
/*
* Clear the KMC copy of the transmit-enable bit for this line
* and set up a unibus request to clear the corresponding bit
* in the DZ11
*/
mov enblbits,brg
add brg,r7,mar
mov %enblbits,%mar
mov mem,r0
mov actline,mar
mov %dzst,brg
add brg,r8,%mar
and mem,r0
xor mem,r0,mem
mov mem,odl
mov csrget,mar
mov mem,r0|mar++
mov mem,r1|mar++
mov mem,r2
mov 4,brg
add brg,r0,oal
adc r1,brg
mov brg,oah
adc r2
mov nprx,r0
mov VEC4,brg
and brg,r0
asl r2
asl r2,brg
or brg,r0,nprx
mov BYTE|OUT|NRQ,brg
mov brg,npr
/*
* Wait for the unibus transfer to complete.
* If an error occurs then go to buserr1.
*/
BUSWAIT(buserr1)
/*
* Go to dispret
*/
br dispret
/*
* This two entry point subroutine is called at oflush to
* flush any current output regardless of the current state
* of the line. Oflush is also called when the last character
* of normal output has been sent out and the dz is requesting
* another character. This simply bookkeeps the LTE. The
* entry point oqueue is called when the last character in
* the current output buffer is used so the host may reload
* another buffer before the dz requests another character.
*/
oflush:
mov %dzst,brg
add brg,r8,%mar
/*
* Clear output flags
*/
mov FLAGS,brg
add brg,r10,mar
mov ~(SENDSAVE|SENDHIGH|NLEXP),brg
mov brg,r0
and mem,r0,mem
mov FLAGS1,brg
add brg,r10,mar
mov mem,r0
mov ~(TTSTOP|PREVNB),brg
and brg,r0,mem
mov NCH,brg
add brg,r10,mar
mov 0,mem
/*
* Set state = 0
*/
mov STATE,brg
add brg,r10,mar
mov 0,mem
/*
* See if there is an output buffer
*/
oqueue:
mov %dzst,brg
add brg,r8,%mar
mov OUTBUF,brg
add brg,r10,mar
mov mem,r4
brz oqret
mov NIL,mem
mov 03,brg
and brg,r4,%mar
mov ~03,brg
and brg,r4,mar
/*
* Set link to next queue entry = NIL
*/
mov NIL,mem|mar++
/*
* Chain this queue entry to the end of the output-buffer-completion-
* report queue
*/
mov tailoutq,mar
mov %tailoutq,%mar
mov mem,r5
brz 1f
mov r4,mem
mov 3,brg
and brg,r5,%mar
mov ~3,brg
and brg,r5,mar
mov r4,mem
br 2f
1:
mov r4,mem
mov headoutq,mar
mov r4,mem
2:
/*
* Set a flag to indicate that the output-buffer-completion-report
* queue is non-empty
*/
mov CHKOUTQ,brg
or brg,r14
oqret:
RETURN
/*
* The unibus transfer failed to complete within a reasonable time
*/
buserr1:
/*
* Clear the non-existent memory bit
*/
mov nprx,r0
mov ~(BRQ|ACLO|NEM),brg
and brg,r0,nprx
ERROR(BUSERR1)
/*
* Go to dispret
*/
br dispret
/*
* Return to top of dispatcher loop in main segment
*/
dispret:
mov %disp,brg
mov brg,pcr
jmp disp
/*
* Error loops for debugging
*/
errh:
mov NIL,mem
ERROR(ERRH)
br dispret
endseg1: