unit DMA;

interface

TYPE DMAarray = array[0..7] of byte;

CONST
 { DMA controller addresses }
 DMA_Address           : DMAarray = ($00,$02,$04,$06,$C0,$C4,$C8,$CC);
 DMA_Count             : DMAarray = ($01,$03,$05,$07,$C2,$C6,$CA,$CE);
 DMARead_status_Reg    : DMAarray = ($08,$08,$08,$08,$D0,$D0,$D0,$D0);
 DMAWrite_status_Reg   : DMAarray = ($08,$08,$08,$08,$D0,$D0,$D0,$D0);
 DMAWrite_requ_Reg     : DMAarray = ($09,$09,$09,$09,$D2,$D2,$D2,$D2);
 DMAWr_single_mask_Reg : DMAarray = ($0A,$0A,$0A,$0A,$D4,$D4,$D4,$D4);
 DMAWr_mode_Reg        : DMAarray = ($0B,$0B,$0B,$0B,$D6,$D6,$D6,$D6);
 DMAClear_Flipflop     : DMAarray = ($0C,$0C,$0C,$0C,$D8,$D8,$D8,$D8);
 DMARead_Temp_Reg      : DMAarray = ($0D,$0D,$0D,$0D,$DA,$DA,$DA,$DA);
 DMAMaster_Clear       : DMAarray = ($0D,$0D,$0D,$0D,$DA,$DA,$DA,$DA);
 DMA_Clear_Mask_Reg    : DMAarray = ($0E,$0E,$0E,$0E,$DC,$DC,$DC,$DC);
 DMA_Wr_All_Mask_Reg   : DMAarray = ($0F,$0F,$0F,$0F,$DE,$DE,$DE,$DE);
 DMA_Lower_Page        : DMAarray = ($87,$83,$81,$82,$00,$8B,$89,$8A);
 DMA_Higher_Page       : Array[0..7] of word
                            = ($487,$483,$481,$482,$0,$48B,$489,$48A);

 { Mode Register  DMA_Wr_mode_Reg }
 Request_mode  = $00;
 Single_mode         = $40;
 Block_mode          = $80;
 Cascade_mode = $C0;
 Addresses_Decrement = $20;
 Addresses_Increment = $00;
 Autoinit_Enable     = $10;
 Autoinit_Disable    = $00;
 Check_transfer      = $00;
 Write_Transfer      = $04;
 Read_Transfer       = $08;

 Set_Request_Bit     = $04;
 Clear_Request_Bit   = $00;
 Set_Mask_Bit        = $04;
 Clear_Mask_Bit      = $00;

procedure DMA_Mode_set(Channel,Mode : byte);
procedure DMA_NormMode_set(Channel,Mode : byte);
procedure DMA_Clear_Flipflop(Channel : byte);
procedure DMA_Startaddress(Channel : byte; Start : pointer);
procedure DMA_Blocksize(Channel : byte; size : word);
procedure DMA_Channel_maskon(Channel : byte);
procedure DMA_Channel_maskoff(Channel : byte);
procedure DMA_Init_Transfer(Channel,Mode : byte; p : pointer; s : word);

implementation

TYPE
  pt = record                           { makes simple pointer    }
    ofs,sgm  :  word;                   { handling possible    }
  end;

procedure DMA_Mode_set(Channel,Mode : byte);
begin;
  port[DMAWr_Mode_Reg[Channel]] := Mode;
end;

procedure DMA_NormMode_set(Channel,Mode : byte);
begin;
  port[DMAWr_Mode_Reg[Channel]] := Mode+Addresses_Increment+Read_Transfer+
                                 Autoinit_Disable+Channel;
end;

procedure DMA_Clear_Flipflop(Channel : byte);
begin;
  port[DMAClear_Flipflop[Channel]] := 0;
end;

procedure DMA_Startaddress(Channel : byte; Start : pointer);
var l : longint;
    pn,offs : word;
begin;
  l := 16*longint(pt(Start).sgm)+pt(Start).ofs;
  pn := pt(l).sgm;
  offs := pt(l).ofs;
  port[DMA_Address[Channel]] := lo(offs);
  port[DMA_Address[Channel]] := hi(offs);
  port[DMA_Lower_Page[Channel]] := lo(pn);
  port[DMA_Higher_Page[Channel]] := hi(pn);
end;

procedure DMA_Blocksize(Channel : byte; size : word);
begin;
  DMA_Clear_Flipflop(Channel);
  port[DMA_Count[Channel]]:= lo(size);
  port[DMA_Count[Channel]] := hi(size);
end;

procedure DMA_Channel_maskon(Channel : byte);
begin;
 port[DMAWr_single_mask_Reg[Channel]] := Channel + Set_Mask_Bit;
end;

procedure DMA_Channel_maskoff(Channel : byte);
begin;
 port[DMAWr_single_mask_Reg[Channel]] := Channel + Clear_Mask_Bit;
end;

procedure DMA_Init_Transfer(Channel,Mode : byte; p : pointer; s : word);
begin;
  DMA_Channel_maskon(Channel);
  DMA_Startaddress(Channel,p);
  DMA_Blocksize(Channel,s);
  DMA_NormMode_Set(Channel,Mode+Channel);
  DMA_Channel_maskoff(Channel);
end;

begin;
end.








