mirror of
https://github.com/livingcomputermuseum/Darkstar.git
synced 2026-03-04 10:45:41 +00:00
39 lines
13 KiB
Plaintext
39 lines
13 KiB
Plaintext
head 1.1;
|
||
branch 1.1.1;
|
||
access ;
|
||
symbols start:1.1.1.1 Xerox:1.1.1;
|
||
locks ; strict;
|
||
comment @;; @;
|
||
|
||
|
||
1.1
|
||
date 2001.08.12.22.22.21; author freier; state Exp;
|
||
branches 1.1.1.1;
|
||
next ;
|
||
|
||
1.1.1.1
|
||
date 2001.08.12.22.22.21; author freier; state Exp;
|
||
branches ;
|
||
next ;
|
||
|
||
|
||
desc
|
||
@@
|
||
|
||
|
||
|
||
1.1
|
||
log
|
||
@Initial revision
|
||
@
|
||
text
|
||
@{ File: [Iris]<WMicro>DLion>DmaSubs.asm
|
||
Modification History:
|
||
Dennis DEG 1-Sep-84 16:46:18: Added copyright notice.
|
||
Added copyright noticeJim JXF May 21, 1982 9:01 AM: Change DmaControlBlock Format and Port Control Block format to be compatible with each other. Save mode bits in DmaActive.
|
||
Changed StartDmaChannel so DmaChannel cannot be destroyed by
|
||
interrupting subroutine (April 3, 1981 7:04 AM).
|
||
Changed di/ei to use subroutines (March 25, 1981 9:34 PM)
|
||
Leave Floppy Channel enabled while StartDmaChannel enables another
|
||
channel in an effort to reduce the LostData errors
|
||
(January 26, 1981 11:52 AM)
|
||
protected StartDmaChannel, ClearDmaChannel, ReadDmaCompletion from
|
||
interference by the Floppy Interrupt (January 25, 1981 4:00 PM)
|
||
Shortened critical section in StartDmaChannel (January 20, 1981 1:56 PM)
|
||
Removed DmaCompletion, changed ClearDmaChannel (December 18, 1980 2:09 PM)
|
||
Shortened critical section in StartDmaChannel (October 31, 1980 12:11 PM)
|
||
Created by Roy RXO (June 17, 1980 1:48 PM)
|
||
}
|
||
|
||
{ Copyright (C) 1980, 1981, 1982 by Xerox Corporation. All rights reserved.}
|
||
|
||
|
||
; DEFINITION FILES:
|
||
|
||
get "SysDefs" ;system defs
|
||
get "CommonDefs" ;Common defs
|
||
|
||
|
||
; IMPORTS/EXPORTS:
|
||
|
||
IMP ErrorReport
|
||
|
||
EXP ClearDmaChannel
|
||
EXP DmaActive
|
||
EXP FloppyActiveSwitch1
|
||
EXP FloppyActiveSwitch2
|
||
EXP FloppyActiveSwitch3
|
||
EXP ReadDmaCompletion
|
||
EXP StartCPDmaChannel
|
||
EXP StartDmaChannel
|
||
EXP StartFloppyChannel
|
||
|
||
{ NOTES:
|
||
|
||
These are the subroutines which handle the Dma Controller. Clients using the Dma Controller should use them to set up, start, or disable a particular channel.
|
||
|
||
DmaControlBlock Format:
|
||
byte 0: Byte count low,
|
||
byte 1: Byte count high,
|
||
byte 2: Memory Address Low,
|
||
byte 3: Memory Address high,
|
||
|
||
NOTE: the DmaControlBlock is the same as the last two words of the PortControlBlock.
|
||
|
||
The following are the subroutines available to clients:
|
||
- StartDmaChannel:
|
||
[H,L: POINTER to DmaControlBlock,
|
||
A: Function/DmaChannelMask]
|
||
|
||
- Function/DmaChannelMask:
|
||
Function (bits 0,1) : 0 = Verify, 1 = write, 2 = read, 3 = undefined
|
||
DmaChannelMask (bits 4..7): EN3, EN2, EN1, EN0
|
||
|
||
Set up the address, count, and operation for the particular Dma channels. Other channels are not affected. Channels which have completed are removed from DmaActive. "DmaActive" is updated in memory. Returns StartError =0 for no error, StartError#0 for error in channel mask.
|
||
|
||
- ReadDmaCompletion [A: DmaChannelMask] RETURNS [A: ~DmaActive AND DmaChannelMask]
|
||
|
||
Read Dma Status, and update DmaActive.Return ~DmaActive AND DmaChannelMask.
|
||
|
||
- ClearDmaChannel [A: DmaChannelMask]
|
||
|
||
Determine if any channels have completed, and update DmaActive. Clear the Active bits in DmaActive as indicated by DmaChannelMask. Re-enable the DmaComtroller with the new Active bits.
|
||
|
||
Questions:
|
||
- what if channel is active and a StartChannel is received?
|
||
}
|
||
|
||
|
||
|
||
; Internal definitions:
|
||
ChannelMask equ 0FH ;Mask of Channel field in Function/ChannelMask byte
|
||
nChannelMask equ 0FFH-ChannelMask ;Complement of ChannelMask
|
||
FunctionMask equ 0C0H ;Mask of Function field in Function/ChannelMask byte
|
||
DisableDma equ 0 ;Dma Mode value to disable all channels
|
||
|
||
;
|
||
; PUBLIC Dma Subroutines.
|
||
|
||
|
||
{ Subroutine: StartCPDmaChannel [H,L: POINTER to DmaControlBlock].
|
||
Set up the address, count, Dma function of the CP channel.
|
||
Enable the Dma Channel. Note: TCS and EW are set in Mode automatically.
|
||
|
||
Assumption: Byte count is only 14 bits, i.e. high 2 bits are zero. NO DMA CHANNEL SHALL BE RESTARTED WITHOUT USING ReadDmaCompletion OR ClearDmaChannel TO ENSURE THE CHANNEL'S TERMINAL COUNT BIT IS OFF WHEN StartDmaChannel ACCESSES THE DMA CHIP. If the TC bit is on, the channel will not be restarted.
|
||
On entry:
|
||
A = function: DmaRead or DmaWrite
|
||
HL = pointer to Dma Control Block (format described above).
|
||
byte 0: Byte count low,
|
||
byte 1: Byte count high,
|
||
byte 2: Memory Address Low,
|
||
byte 3: Memory Address high,
|
||
}
|
||
|
||
StartCPDmaChannel:
|
||
MOV E,M ;E ¬ low byte count
|
||
INX H ;Point to High count
|
||
MOV D,M ;D ¬ High byte count
|
||
DCX D ;Decrement for Dma controller
|
||
ORA D ;OR in Dma function
|
||
MOV D,A
|
||
MOV A,E
|
||
OUT DmaCh1Count ;Send low count
|
||
MOV A,D
|
||
OUT DmaCh1Count ;Send high count
|
||
INX H ;Point to Low address
|
||
MOV A,M ;E ¬ Memory Address Low
|
||
OUT DmaCh1Addr ;Send low address
|
||
INX H
|
||
MOV A,M ;D ¬ Memory Address High
|
||
OUT DmaCh1Addr ;Send high address
|
||
{Now we are ready to start the DMA for the CP channel. When we send the command to the DMA controller, the low 4 bits of the command specify which channels to start. We must start the CP channel as well as any other channels that are currently busy.
|
||
|
||
The problem is to know what channels are currently busy so we can send the proper command to the controller. DmaActive is the command we last sent to the DMA to start one or more channels. The low 4 bits of this command indicate which channels were last started. Some of these channels may have completed since then.
|
||
|
||
In order to find out what channels have completed, we must read the Status Register. The low 4 bits of this register indicate what channels have completed. However, we cannot read this register and use this information to restart channels that have not completed, because a channel could complete in this interval. To leave a channel enabled is like pointing a loaded gun at our memory. So what me must do is to stop all channels except for the floppy channel before we read the Status Register. We must not stop the floppy channel if it is busy because it cannot afford the time.}
|
||
RIM
|
||
ANI InterruptEnbMsk ;A#0 => interrupts were enabled
|
||
|
||
{If the floppy and RS232C are running at the same time, we must disable interrupts when DmaActive is being updated. The following op code will be a JMP whenever the floppy is NOT active. It will be JZ whenever the floppy IS active. If the floppy is active AND interrupts are enabled, we will disable interrupts.}
|
||
FloppyActiveSwitch1:
|
||
DB opJMP
|
||
DW StartCPDmaChannelNoDisable
|
||
|
||
{Come here if the floppy is running and interrupts are enabled.}
|
||
DI
|
||
|
||
{Set up A with the ModeSetRegister contents. If the floppy was busy, we will set the floppy active and turn all other channels off. If the floppy was not busy, we will turn off all channels.}
|
||
LDA DmaActive
|
||
MOV D,A ;Save DmaActive in D
|
||
ANI DmaCh0Mask ;A ¬ 1 if floppy was busy
|
||
OUT DmaMode ;Disable channels
|
||
IN DmaStatus ;Read TerminalCount flags
|
||
CMA ;A ¬ inverted TerminalCount Flags
|
||
|
||
{Now A contains zero in bit positions of channels that have completed and ones in all other bit positions. We AND this with DmaActive. This gives us a command to restart all channels that need to be restarted. We then OR in the bit for the CP channel, send the command to the DMA, and save DmaActive.}
|
||
ANA D
|
||
ORI CPChannelMask
|
||
OUT DmaMode ;Start Dma
|
||
STA DmaActive ;Store back in DmaActive
|
||
EI
|
||
RET
|
||
|
||
StartCPDmaChannelNoDisable:
|
||
{Come here if the floppy is not running or if the floppy is running and interrupts are disabled.}
|
||
DB opMVIA ;A ¬ DmaActive
|
||
DmaActive:
|
||
DB DmaModeExtra
|
||
MOV D,A ;Save DmaActive in D
|
||
ANI DmaCh0Mask ;A ¬ 1 if floppy was busy
|
||
OUT DmaMode ;Disable channels
|
||
IN DmaStatus ;Read TerminalCount flags
|
||
CMA ;A ¬ inverted TerminalCount Flags
|
||
|
||
{Now A contains zero in bit positions of channels that have completed and ones in all other bit positions. We AND this with DmaActive. This gives us a command to restart all channels that need to be restarted. We then OR in the bit for the CP channel, send the command to the DMA, and save DmaActive.}
|
||
ANA D
|
||
ORI CPChannelMask
|
||
OUT DmaMode ;Start Dma
|
||
STA DmaActive ;Store back in DmaActive
|
||
RET
|
||
|
||
|
||
ReadDmaCompletion:
|
||
|
||
{Read Dma Status, and update DmaActive. Return updated ~DmaActive masked by DmaChannelMask.
|
||
On entry:
|
||
E = DmaChannel Mask
|
||
On exit:
|
||
A = ~DmaActive AND DmaChannelMask, condition code is set}
|
||
|
||
RIM
|
||
ANI InterruptEnbMsk ;A#0 => interrupts were enabled
|
||
|
||
{If the floppy and RS232C are running at the same time, we must disable interrupts when DmaActive is being updated. The following op code will be a JMP whenever the floppy is NOT active. It will be JZ whenever the floppy IS active. If the floppy is active AND interrupts are enabled, we will disable interrupts.}
|
||
FloppyActiveSwitch2:
|
||
DB opJMP
|
||
DW ReadDmaCompletionNoDisable
|
||
|
||
{Come here if the floppy is running and interrupts are enabled.}
|
||
DI
|
||
LDA DmaActive ;D ¬ DmaActive
|
||
MOV D,A
|
||
IN DmaStatus ;Get the completed channels
|
||
CMA ;Form complement mask of completed channels
|
||
ANA D ;Clear channels in DmaActive
|
||
STA DmaActive ;Store back in DmaActive
|
||
EI
|
||
CMA
|
||
ANA E ;Mask channels of interest
|
||
RET
|
||
|
||
ReadDmaCompletionNoDisable:
|
||
{Come here if the floppy is not running or if the floppy is running and interrupts are disabled.}
|
||
LDA DmaActive ;D ¬ DmaActive
|
||
MOV D,A
|
||
IN DmaStatus ;Get the completed channels
|
||
CMA ;Form complement mask of completed channels
|
||
ANA D ;Clear channels in DmaActive
|
||
STA DmaActive ;Store back in DmaActive
|
||
CMA
|
||
ANA E ;Mask channels of interest
|
||
RET
|
||
|
||
ClearDmaChannel:
|
||
{Read the completed channels in DmaStatus, and remove from DmaActive. Remove the channels specified by DmaChannelMask and re-enable the Dma controller. Note that a hardware channel is automatically cleared at a terminal count condition.
|
||
On entry: A = DmaChannel Mask}
|
||
|
||
CMA ;Complement channel mask
|
||
MOV E,A ;E ¬ Complemented mask of channels to be disabled
|
||
RIM
|
||
ANI InterruptEnbMsk ;A#0 => interrupts were enabled
|
||
|
||
{If the floppy and RS232C are running at the same time, we must disable interrupts when DmaActive is being updated. The following op code will be a JMP whenever the floppy is NOT active. It will be JZ whenever the floppy IS active. If the floppy is active AND interrupts are enabled, we will disable interrupts.}
|
||
FloppyActiveSwitch3:
|
||
DB opJMP
|
||
DW ClearDmaChannelNoDisable
|
||
|
||
{Come here if the floppy is running and interrupts are enabled.}
|
||
DI
|
||
LDA DmaActive
|
||
ANA E ;A ¬ mask of channels to be active
|
||
MOV D,A ;D ¬ DmaActive
|
||
ANI DmaCh0Mask
|
||
OUT DmaMode ;Disable Dma
|
||
IN DmaStatus ;Read Terminal Count Flags
|
||
CMA ;A ¬ inverted Terminal Count Flags
|
||
ANA D ;Clear completed channels in DmaActive
|
||
OUT DmaMode ;Restart DMA
|
||
STA DmaActive ;Store back in DmaActive
|
||
EI
|
||
RET
|
||
|
||
ClearDmaChannelNoDisable:
|
||
{Come here if the floppy is not running or if the floppy is running and interrupts are disabled.}
|
||
LDA DmaActive
|
||
ANA E ;A ¬ mask of channels to be active
|
||
MOV D,A ;D ¬ DmaActive
|
||
ANI DmaCh0Mask
|
||
OUT DmaMode ;Disable Dma
|
||
IN DmaStatus ;Read Terminal Count Flags
|
||
CMA ;A ¬ inverted Terminal Count Flags
|
||
ANA D ;Clear completed channels in DmaActive
|
||
OUT DmaMode ;Restart DMA
|
||
STA DmaActive ;Store back in DmaActive
|
||
RET
|
||
;
|
||
{ Subroutine: StartFloppyChannel [H,L: POINTER to DmaControlBlock].
|
||
Set up the address, count, Dma function of the CP channel.
|
||
Enable the Dma Channel. Note: TCS and EW are set in Mode automatically.
|
||
|
||
On entry:
|
||
A = function: DmaRead or DmaWrite
|
||
HL = pointer to Dma Control Block (format described above).
|
||
byte 0: Byte count low,
|
||
byte 1: Byte count high,
|
||
byte 2: Memory Address Low,
|
||
byte 3: Memory Address high,
|
||
}
|
||
|
||
StartDmaChannel:
|
||
StartFloppyChannel:
|
||
MOV E,M ;E ¬ low byte count
|
||
INX H ;Point to High count
|
||
MOV D,M ;D ¬ High byte count
|
||
DCX D ;Decrement for Dma controller
|
||
ORA D ;OR in Dma function
|
||
MOV D,A
|
||
MOV A,E
|
||
OUT DmaCh0Count ;Send low count
|
||
MOV A,D
|
||
OUT DmaCh0Count ;Send high count
|
||
INX H ;Point to Low address
|
||
MOV A,M ;E ¬ Memory Address Low
|
||
OUT DmaCh0Addr ;Send low address
|
||
INX H
|
||
MOV A,M ;D ¬ Memory Address High
|
||
OUT DmaCh0Addr ;Send high address
|
||
{Now we are ready to start the DMA for the Floppy channel. When we send the command to the DMA controller, the low 4 bits of the command specify which channels to start. We must start the Floppy channel as well as any other channels that are currently busy.
|
||
|
||
The problem is to know what channels are currently busy so we can send the proper command to the controller. DmaActive is the command we last sent to the DMA to start one or more channels. The low 4 bits of this command indicate which channels were last started. Some of these channels may have completed since then.
|
||
|
||
In order to find out what channels have completed, we must read the Status Register. The low 4 bits of this register indicate what channels have completed. However, we cannot read this register and use this information to restart channels that have not completed, because a channel could complete in this interval. To leave a channel enabled is like pointing a loaded gun at our memory. So what me must do is to stop all channels before we read the Status Register.}
|
||
LDA DmaActive
|
||
MOV D,A ;Save DmaActive in D
|
||
XRA A
|
||
OUT DmaMode ;Disable channels
|
||
IN DmaStatus ;Read TerminalCount flags
|
||
CMA ;A ¬ inverted TerminalCount Flags
|
||
|
||
{Now A contains zero in bit positions of channels that have completed and ones in all other bit positions. We AND this with DmaActive. This gives us a command to restart all channels that need to be restarted. We then OR in the bit for the CP channel, send the command to the DMA, and save DmaActive.}
|
||
ANA D
|
||
ORI DmaCh0Mask
|
||
OUT DmaMode ;Start Dma
|
||
STA DmaActive ;Store back in DmaActive
|
||
RET
|
||
|
||
|
||
END DmaSubs
|
||
@
|
||
|
||
|
||
1.1.1.1
|
||
log
|
||
@first add
|
||
@
|
||
text
|
||
@@
|