home *** CD-ROM | disk | FTP | other *** search
- {****************************************************************************}
- { }
- { MODULE: Hardware }
- { }
- { DESCRIPTION: An UNIT that provides general support to generic Hardware, }
- { like the PIC, the DMA controller, etc... }
- { }
- { AUTHOR: Juan Carlos Arévalo }
- { }
- { MODIFICATIONS: Nobody (yet ;-) }
- { }
- { HISTORY: 18-Nov-1992 Documentation. }
- { }
- { (C) 1992 VangeliSTeam }
- {____________________________________________________________________________}
-
- UNIT Hardware;
-
- INTERFACE
-
-
-
-
- PROCEDURE EnableIRQ (i: WORD);
- PROCEDURE DisableIRQ (i: WORD);
- FUNCTION SetIRQVector(i: WORD; Vec: POINTER) : POINTER;
-
- PROCEDURE DMASet (Channel, Mode: WORD ; Buf: POINTER; Size: WORD);
- PROCEDURE DMARawSet(Channel, Mode, Page: BYTE; Offs, Size: WORD);
- PROCEDURE DMASetAsm;
-
-
-
-
- IMPLEMENTATION
-
- USES Dos;
-
-
-
-
- {----------------------------------------------------------------------------}
- { PIC routines. }
- {____________________________________________________________________________}
-
- PROCEDURE EnableIRQ(i: WORD);
- BEGIN
- IF i < 8 THEN
- PORT[$21] := PORT[$21] AND (NOT (1 SHL i))
- ELSE
- BEGIN
- PORT[$A1] := PORT[$A1] AND (NOT (1 SHL (i-8)));
- PORT[$21] := PORT[$21] AND (NOT (1 SHL 2))
- END;
- END;
-
-
- PROCEDURE DisableIRQ(i: WORD);
- BEGIN
- IF i < 8 THEN
- PORT[$21] := PORT[$21] OR (1 SHL i)
- ELSE
- BEGIN
- PORT[$A1] := PORT[$A1] OR (1 SHL (i-8))
- END;
- END;
-
-
- FUNCTION SetIRQVector(i: WORD; Vec: POINTER) : POINTER;
- VAR
- p : POINTER;
- j : WORD;
- BEGIN
- IF i < 8 THEN j := i + $08
- ELSE j := i + $68;
-
- GetIntVec(j, p);
- SetIntVec(j, Vec);
- SetIRQVector := p;
- END;
-
-
-
-
- {----------------------------------------------------------------------------}
- { DMA routines. }
- {____________________________________________________________________________}
-
- {
- AH = Channel
- CH = Mode
- CL = Page
- BX = Offset
- SI = Size
- }
-
- PROCEDURE DMA16Set; ASSEMBLER;
- CONST
- PageRegTable : ARRAY[0..3] OF WORD = ( $00, $8B, $89, $8A );
- ASM
-
- AND AH,3
-
- SHR CL,1
- RCR BX,1
- ADD CL,CL
-
- MOV AL,AH; ADD AL,$04; OUT $D4,AL { Disable DMA channel. }
- XOR AL,AL; OUT $D8,AL { Clear BYTE POINTER flip-flop to lower byte. }
- MOV AL,AH; ADD AL,CH; OUT $D6,AL { DMA Mode register. }
- XOR DH,DH
- MOV DL,AH
- ADD DX,DX
- ADD DX,DX { Calculate DMA base port. }
- ADD DX,$C0
-
- MOV AL,BL; OUT DX,AL { Offset of the buffer, low & high bytes. }
- MOV AL,BH; OUT DX,AL
-
- PUSH DX
-
- MOV DL,AH
- ADD DX,DX
- MOV BX,OFFSET PageRegTable
- ADD BX,DX { Calculate page register port. }
- MOV DX,[BX]
- MOV AL,CL; OUT DX,AL { Set DMA page. }
-
- POP DX
- INC DX
- INC DX { Calculate DMA counter port. }
-
- MOV BX,SI
- MOV AL,BL; OUT DX,AL { Size of the buffer minus 1, low & high byte. }
- MOV AL,BH; OUT DX,AL
- MOV AL,AH; OUT $D4,AL { Enable DMA channel. }
-
- END;
-
-
- PROCEDURE DMA8Set; ASSEMBLER;
- CONST
- PageRegTable : ARRAY[0..3] OF WORD = ( $87, $83, $81, $82 );
- ASM
-
- MOV AL,AH; ADD AL,$04; OUT $A,AL { Disable DMA channel. }
- XOR AL,AL; OUT $C,AL { Clear BYTE POINTER flip-flop to lower byte. }
- MOV AL,AH; ADD AL,CH; OUT $B,AL { DMA Mode register. }
- XOR DH,DH
- MOV DL,AH
- ADD DX,DX { Calculate DMA base port. }
-
- MOV AL,BL; OUT DX,AL { Offset of the buffer, low & high bytes. }
- MOV AL,BH; OUT DX,AL
-
- PUSH DX
-
- MOV BX,OFFSET PageRegTable
- ADD BX,DX { Calculate page register port. }
- MOV DX,[BX]
- MOV AL,CL; OUT DX,AL { Set DMA page. }
-
- POP DX
- INC DX { Calculate DMA counter port. }
-
- MOV BX,SI
- MOV AL,BL; OUT DX,AL { Size of the buffer minus 1, low & high byte. }
- MOV AL,BH; OUT DX,AL
- MOV AL,AH; OUT $A,AL { Enable DMA channel. }
-
- END;
-
-
- PROCEDURE DMASetAsm; ASSEMBLER;
- ASM
-
- CMP AH,2
- JZ @@Fin
- CMP AH,4
- JZ @@Fin
- JB @@8bit
- CALL DMA16Set
- JMP @@Fin
- @@8bit: CALL DMA8Set
-
- @@Fin:
-
- END;
-
-
- PROCEDURE DMARawSet(Channel, Mode, Page: BYTE; Offs, Size: WORD); ASSEMBLER;
- ASM
-
- MOV AH,[Channel]
- MOV CH,[Mode]
- MOV CL,[Page]
- MOV BX,[Offs]
- MOV SI,[Size]
-
- CALL DMASetAsm
-
- END;
-
-
- PROCEDURE DMASet(Channel, Mode: WORD ; Buf: POINTER; Size: WORD);
- VAR
- Segm : WORD;
- Offs : WORD;
- BEGIN
-
- Segm := SEG(Buf^) AND $F000;
- Offs := SEG(Buf^) AND $0FFF;
-
- IF Offs > 65535 - OFS(Buf^) THEN
- BEGIN
- INC(Segm, $1000);
- Offs := WORD(Offs - 65536 + OFS(Buf^));
- END
- ELSE
- BEGIN
- Offs := Offs + OFS(Buf^);
- END;
-
- DEC(Size);
-
- DMARawSet(Channel, Mode, Segm SHR 12, Offs, Size);
-
- END;
-
-
-
-
- END.
-