--- /dev/null
+; MMURTL Operating System Source Code\r
+; Copyright 1991,1992,1993,1994 Richard A. Burgess\r
+; ALL RIGHTS RESERVED Version 1.0\r
+.DATA\r
+\r
+.INCLUDE MOSEDF.INC\r
+\r
+.CODE\r
+;========== DMA Equates for DMA amd PAGE registers =========\r
+;NOTES: With 8 bit DMA, the lower WORD (bits 15-0) are placed into\r
+; the address registers of the DMA, and the Page register is the next\r
+; most significant byte (bits 23-16). With WORD DMA moves (channels 5-7),\r
+; address bits 16-1 are placed in the address registers, while 23-17 are\r
+; put in the page register. Bit 16 is ignored by the page register.\r
+;\r
+;\r
+; DMA 1 Port addresses and page registers\r
+\r
+DMA10Add EQU 00h ;Ch 0 Address\r
+DMA10Cnt EQU 01h ;Ch 0 Word Count\r
+DMA11Add EQU 02h ;Ch 1 Address\r
+DMA11Cnt EQU 03h ;Ch 1 Word Count\r
+DMA12Add EQU 04h ;Ch 2 Address\r
+DMA12Cnt EQU 05h ;Ch 2 Word Count\r
+DMA13Add EQU 06h ;Ch 3 Address\r
+DMA13Cnt EQU 07h ;Ch 3 Word Count\r
+DMA1StatCmd EQU 08h ;Read Status/Write Command\r
+DMA1RqReg EQU 09h ;Read/Write DMA Rq Register\r
+DMA1RCmdWbm EQU 0Ah ;Read Command/Write Single bit mask\r
+DMA1Mode EQU 0Bh ;Read/Write Mode register\r
+DMA1FF EQU 0Ch ;Writing this address clears byte ptr flip flop\r
+DMA1Clear EQU 0Dh ;Write causes MASTER Clear (Read from Temp Reg)\r
+DMA1ClrMode EQU 0Eh ;Rd clears mode reg count/Wr Clr ALL mask bits\r
+DMA1MskBts EQU 0Fh ;Read/Write DMA Rq Mask Register\r
+\r
+; DMA 2 Port addresses\r
+\r
+DMA20Add EQU 0C0h ;Ch 0 Address\r
+DMA20Cnt EQU 0C2h ;Ch 0 Word Count\r
+DMA21Add EQU 0C4h ;Ch 1 Address\r
+DMA21Cnt EQU 0C6h ;Ch 1 Word Count\r
+DMA22Add EQU 0C8h ;Ch 2 Address\r
+DMA22Cnt EQU 0CAh ;Ch 2 Word Count\r
+DMA23Add EQU 0CCh ;Ch 3 Address\r
+DMA23Cnt EQU 0CEh ;Ch 3 Word Count\r
+DMA2StatCmd EQU 0D0h ;Read Status/Write Command\r
+DMA2RqReg EQU 0D2h ;Read/Write DMA Rq Register\r
+DMA2RCmdWbm EQU 0D4h ;Read Command/Write Single bit mask\r
+DMA2Mode EQU 0D6h ;Read/Write Mode register\r
+DMA2FF EQU 0D8h ;Writing this address clears byte ptr flip flop\r
+DMA2Clear EQU 0DAh ;Write causes MASTER Clear (Read from Temp Reg)\r
+DMA2ClrMode EQU 0DCh ;Rd clears mode reg count/Wr Clr ALL mask bits\r
+DMA2MskBts EQU 0DEh ;Read/Write DMA Rq Mask Register\r
+\r
+;DMA Page register by DRQ/DACK number\r
+\r
+DMAPage0 EQU 87h ;DMA DACK0 Page register\r
+DMAPage1 EQU 83h ; DACK1 (etc. etc. etc.)\r
+DMAPage2 EQU 81h\r
+DMAPage3 EQU 82h\r
+DMAPage5 EQU 8Bh\r
+DMAPage6 EQU 89h\r
+DMAPage7 EQU 8Ah\r
+;\r
+; The following code sets up the initial DMA channel values for\r
+; both chips to most probable use. Includes cascade mode for CH4\r
+; which is DMA channel 0 on chip 2\r
+;\r
+PUBLIC InitDMA:\r
+ MOV AL, 04 ;Master disable\r
+ OUT DMA1StatCmd, AL\r
+ OUT DMA2StatCmd, AL\r
+\r
+ XOR AL, AL ;MASTER CLEAR (same as hardware reset)\r
+ OUT DMA1Clear, AL\r
+ OUT DMA2Clear, AL\r
+\r
+ XOR AL, AL ;All commands set to default (0)\r
+ OUT DMA1StatCmd, AL\r
+ OUT DMA2StatCmd, AL\r
+\r
+ MOV AL, 40h ;CH 0 DMA 1\r
+ OUT DMA1Mode, AL ;\r
+ MOV AL, 0C0h ;CH 0 DMA 2 (Cascade Mode)\r
+ OUT DMA2Mode, AL ;\r
+\r
+ MOV AL, 41h ;CH 1 DMA 1 & 2\r
+ OUT DMA1Mode, AL ;\r
+ OUT DMA2Mode, AL ;\r
+\r
+ MOV AL, 42h ;CH 2 DMA 1 & 2\r
+ OUT DMA1Mode, AL ;\r
+ OUT DMA2Mode, AL ;\r
+\r
+ MOV AL, 43h ;CH 3 DMA 1 & 2\r
+ OUT DMA1Mode, AL ;\r
+ OUT DMA2Mode, AL ;\r
+\r
+ XOR AL,AL\r
+ OUT DMA1ClrMode, AL ;Enable ALL DMA 1 Channels\r
+ OUT DMA2ClrMode, AL ;Enable ALL DMA 2 Channels\r
+ RETN\r
+\r
+;\r
+;-----------------------------------------------------------\r
+; The following code sets up a single DMA channel for the caller.\r
+; DMA is crippled because it can't move across 64K physical\r
+; boundries. It's the caller's responsibility to know if he is\r
+; crossing a boundry! If he does, this will wrap around over the segment!!!\r
+; This code is completely reentrant.\r
+; There is only one call for DMA set up.\r
+\r
+; The caller sets the type of DMA operation (In, Out, Verify).\r
+; For channels 5,6 & 7, the address & count must be divided by\r
+; two for the DMA hardware. This routine does this for you!\r
+; Algorythm - Put mode byte bits (except channel bits) in BL, then jump to\r
+; correct routine for that channel. The call will allow set up of\r
+; all the differnet types of DMA modes for read and write with this\r
+; single call. The call:\r
+;\r
+; DmaSetUp(dPhyMem, sdMem, dChannel, dType, dMode)\r
+; EBP+ 28 24 20 16 12\r
+;\r
+; dPhyMem is physical memory address\r
+; sdMem is nBytes to move (STILL bytes for word xfers, we do math)\r
+; dChannel (0,1,2,3,5,6,7)\r
+; dType - 0 = Verify, 1 = In (Write Mem), 2 = Out (Read memory)\r
+; dMode - 0 Demand Mode, 1 Single Cycle, (Disk I/O uses 1)\r
+; 2 Block, 3 Cascade\r
+;\r
+;\r
+PUBLIC __DMASetUp:\r
+ PUSH EBP ;\r
+ MOV EBP,ESP ;\r
+ MOV EAX, [EBP+12] ; dMode\r
+ CMP EAX, 04 ; Mode must be < 4\r
+ JB DMAModeOK\r
+ MOV EAX, ErcDMAMode\r
+ JMP DMAEnd\r
+DMAModeOK:\r
+ SHL EAX, 6 ; Move Mode bits to 6 and 7\r
+ MOV BL, AL ; Put it in BL\r
+ MOV EAX, [EBP+16] ; get dType\r
+ AND BL, 0C0h ; Set to Verify by default (low bits 0)\r
+ CMP EAX, 0 ; Check fType (Verify?)\r
+ JE DMASelect ; Yes\r
+ CMP EAX, 1 ; In? (Write)\r
+ JE DMAWrite ; Yes (if no then fall thru to Read)\r
+DMARead:\r
+ OR BL, 00001000b ; OR read command to BL (OUT)\r
+ JMP DMASelect\r
+DMAWrite:\r
+ OR BL, 00000100b ; OR write command to BL (IN)\r
+\r
+DMASelect:\r
+ MOV EAX, [EBP+20] ;Jump table for channel selection\r
+ CMP EAX, 0 ;\r
+ JE DMA0\r
+ CMP EAX, 1\r
+ JE DMA1\r
+ CMP EAX, 2\r
+ JE DMA2\r
+ CMP EAX, 3\r
+ JE DMA3\r
+ CMP EAX, 5\r
+ JE DMA5\r
+ CMP EAX, 6\r
+ JE DMA6\r
+ CMP EAX, 7\r
+ JE DMA7\r
+ MOV EAX, ErcDMAChannel\r
+ JMP DMAEnd\r
+\r
+DMA0:\r
+ CLI\r
+ MOV AL, 00000100b ; channel 0 Set Mask for DRQ\r
+ OUT DMA1RCmdWbm, AL ;\r
+ MOV AL, 00000000b ; CH0 (CH is last 2 bits)\r
+ OR AL, BL ; OR with MODE\r
+ OUT DMA1Mode, AL\r
+ OUT DMA1FF, AL ; Clear FlipFLop (Val in AL irrelevent)\r
+ MOV EAX, [EBP+28] ; dPhyMem\r
+ OUT DMA10Add, AL ; Lo byte address\r
+ SHR EAX, 8\r
+ OUT DMA10Add, AL ; Hi Byte\r
+ SHR EAX, 8\r
+ OUT DMAPage0, AL ; Highest byte (to page register)\r
+ MOV EAX, [EBP+24]\r
+ DEC EAX\r
+ OUT DMA10Cnt, AL\r
+ SHR EAX, 8\r
+ OUT DMA10Cnt, AL\r
+ MOV AL, 00000000b ; channel 0 Clear Mask for DRQ\r
+ OUT DMA1RcmdWbm, AL\r
+ STI\r
+ XOR EAX, EAX\r
+ JMP DMAEnd\r
+\r
+DMA1:\r
+ CLI\r
+ MOV AL, 00000101b ; channel 1 Set Mask for DRQ\r
+ OUT DMA1RCmdWbm, AL\r
+ MOV AL, 00000001b ; CH1\r
+ OR AL, BL ; OR with MODE/TYPE\r
+ OUT DMA1Mode, AL\r
+ OUT DMA1FF, AL ; Clear FlipFLop (Val in AL irrelevent)\r
+ MOV EAX, [EBP+28] ; dPhyMem\r
+ OUT DMA11Add, AL ; Lo byte address\r
+ SHR EAX, 8\r
+ OUT DMA11Add, AL ; Hi Byte\r
+ SHR EAX, 8\r
+ OUT DMAPage1, AL ; Highest byte (to page register)\r
+ MOV EAX, [EBP+24] ; sdMem\r
+ DEC EAX\r
+ OUT DMA11Cnt, AL\r
+ SHR EAX, 8\r
+ OUT DMA11Cnt, AL\r
+ MOV AL, 00000001b ; channel 1 Clear Mask for DRQ\r
+ OUT DMA1RcmdWbm, AL\r
+ STI\r
+ XOR EAX, EAX\r
+ JMP DMAEnd\r
+\r
+DMA2:\r
+ CLI\r
+ MOV AL, 00000110b ; channel 2 Set Mask for DRQ\r
+ OUT DMA1RCmdWbm, AL\r
+ MOV AL, 00000010b ; CH2\r
+ OR AL, BL ; OR with MODE\r
+ OUT DMA1Mode, AL\r
+ OUT DMA1FF, AL ; Clear FlipFLop (Val in AL irrelevent)\r
+ MOV EAX, [EBP+28] ; dPhyMem\r
+ OUT DMA12Add, AL ; Lo byte address\r
+ SHR EAX, 8\r
+ OUT DMA12Add, AL ; Hi Byte\r
+ SHR EAX, 8\r
+ OUT DMAPage2, AL ; Highest byte (to page register)\r
+ MOV EAX, [EBP+24] ; sdMem\r
+ DEC EAX\r
+ OUT DMA12Cnt, AL\r
+ SHR EAX, 8\r
+ OUT DMA12Cnt, AL\r
+ MOV AL, 00000010b ; channel 2 Clear Mask for DRQ\r
+ OUT DMA1RcmdWbm, AL\r
+ STI\r
+ XOR EAX, EAX\r
+ JMP DMAEnd\r
+\r
+DMA3:\r
+ CLI\r
+ MOV AL, 00000111b ; channel 3 Set Mask for DRQ\r
+ OUT DMA1RCmdWbm, AL\r
+ MOV AL, 00000011b ; CH3\r
+ OR AL, BL ; OR with MODE\r
+ OUT DMA1Mode, AL\r
+ OUT DMA1FF, AL ; Clear FlipFLop (Val in AL irrelevent)\r
+ MOV EAX, [EBP+28] ; dPhyMem\r
+ OUT DMA13Add, AL ; Lo byte address\r
+ SHR EAX, 8\r
+ OUT DMA13Add, AL ; Hi Byte\r
+ SHR EAX, 8\r
+ OUT DMAPage3, AL ; Highest byte (to page register)\r
+ MOV EAX, [EBP+24] ; sdMem\r
+ DEC EAX\r
+ OUT DMA13Cnt, AL\r
+ SHR EAX, 8\r
+ OUT DMA13Cnt, AL\r
+ MOV AL, 00000011b ; channel 3 Clear Mask for DRQ\r
+ OUT DMA1RcmdWbm, AL\r
+ STI\r
+ XOR EAX, EAX\r
+ JMP DMAEnd\r
+\r
+;NOTE: DMA channels 5-7 are on DMA2 and numbered 1-3 for chip select purposes\r
+\r
+DMA5:\r
+ CLI\r
+ MOV AL, 00000101b ; channel 1 DMA2 Set Mask for DRQ\r
+ OUT DMA2RCmdWbm, AL\r
+ MOV AL, 00000001b ; CH1 on DMA 2\r
+ OR AL, BL ; OR with MODE\r
+ OUT DMA2Mode, AL\r
+ OUT DMA2FF, AL ; Clear FlipFLop (Val in AL irrelevent)\r
+ MOV EAX, [EBP+28] ; dPhyMem\r
+ MOV EBX, EAX ; Save EBX for page\r
+ AND EAX, 0FFFFh ; Rid of all but lower 16\r
+ SHR EAX, 1 ; DIV by 2 for WORD Xfer (bits 16-1)\r
+ OUT DMA21Add, AL ; Lo byte address\r
+ SHR EAX, 8\r
+ OUT DMA21Add, AL ; Hi Byte\r
+ MOV EAX, EBX\r
+ SHR EAX, 15 ; We only need 23-17 for the page\r
+ OUT DMAPage5, AL ; Highest byte (to page register)\r
+ MOV EAX, [EBP+24] ; sdMem\r
+ SHR EAX, 1 ; DIV by 2 for WORD Xfer\r
+ DEC EAX ; One less word\r
+ OUT DMA21Cnt, AL\r
+ SHR EAX, 8\r
+ OUT DMA21Cnt, AL\r
+ MOV AL, 00000001b ; channel 1 Clear Mask for DRQ\r
+ OUT DMA2RcmdWbm, AL\r
+ STI\r
+ XOR EAX, EAX\r
+ JMP DMAEnd\r
+;\r
+DMA6:\r
+ CLI\r
+ MOV AL, 00000110b ; channel 2 Set Mask for DRQ\r
+ OUT DMA2RCmdWbm, AL\r
+ MOV AL, 00000010b ; CH2 on DMA 2\r
+ OR AL, BL ; OR with MODE\r
+ OUT DMA2Mode, AL\r
+ OUT DMA2FF, AL ; Clear FlipFLop (Val in AL irrelevent)\r
+ MOV EAX, [EBP+28] ; dPhyMem\r
+ MOV EBX, EAX\r
+ AND EAX, 0FFFFh ; Rid of all but lower 16\r
+ SHR EAX, 1 ; DIV by 2 for WORD Xfer\r
+ OUT DMA22Add, AL ; Lo byte address\r
+ SHR EAX, 8\r
+ OUT DMA22Add, AL ; Hi Byte\r
+ MOV EAX, EBX\r
+ SHR EAX, 15\r
+ OUT DMAPage6, AL ; Highest byte (to page register)\r
+ MOV EAX, [EBP+24] ; sdMem\r
+ SHR EAX, 1 ; DIV by 2 for WORD Xfer\r
+ DEC EAX\r
+ OUT DMA22Cnt, AL\r
+ SHR EAX, 8\r
+ OUT DMA22Cnt, AL\r
+ MOV AL, 00000010b ; channel 2 Clear Mask for DRQ\r
+ OUT DMA2RcmdWbm, AL\r
+ STI\r
+ XOR EAX, EAX\r
+ JMP DMAEnd\r
+;\r
+DMA7:\r
+ CLI\r
+ MOV AL, 00000111b ; channel 3 Set Mask for DRQ\r
+ OUT DMA2RCmdWbm, AL\r
+ MOV AL, 00000011b ; CH3 on DMA 2\r
+ OR AL, BL ; OR with MODE\r
+ OUT DMA2Mode, AL\r
+ OUT DMA2FF, AL ; Clear FlipFLop (Val in AL irrelevent)\r
+ MOV EAX, [EBP+28] ; dPhyMem\r
+ MOV EBX, EAX\r
+ AND EAX, 0FFFFh ; Rid of all but lower 16\r
+ SHR EAX, 1 ; DIV by 2 for WORD Xfer\r
+ OUT DMA23Add, AL ; Lo byte address\r
+ SHR EAX, 8\r
+ OUT DMA23Add, AL ; Hi Byte\r
+ MOV EAX, EBX\r
+ SHR EAX, 15\r
+ OUT DMAPage6, AL ; Highest byte (to page register)\r
+ MOV EAX, [EBP+24] ; sdMem\r
+ SHR EAX, 1 ; DIV by 2 for WORD Xfer\r
+ DEC EAX\r
+ OUT DMA23Cnt, AL\r
+ SHR EAX, 8\r
+ OUT DMA23Cnt, AL\r
+ MOV AL, 00000011b ; channel 3 Clear Mask for DRQ\r
+ OUT DMA2RcmdWbm, AL\r
+ STI\r
+ XOR EAX, EAX\r
+DMAEnd:\r
+ MOV ESP,EBP ;\r
+ POP EBP ;\r
+ RETF 20 ; 20 bytes of crap to dump\r
+\r
+;------------------------------------------------------------\r
+; GetDMACount returns the number of bytes or words left in the\r
+; DMA count register for the channel specified. For channels\r
+; 5-7 this will be the number of WORDS. For 0-3 this will be BYTES!\r
+; Programmers should note (I should tell them) this value will read\r
+; one less byte/word than is really in the channel. This is because\r
+; 0 = 1 for set purposes. to move 64K, you actually set the\r
+; channel 65,535.\r
+;\r
+; GetDMACount(dChannel, pwCountRet)\r
+; EBP+ 16 12\r
+;\r
+; dChannel (0,1,2,3,5,6,7)\r
+; pwCountRet is a pointer to a Word (2 byte unsigned value) where\r
+; the count will be returned. The count is number of WORDS-1\r
+; for channels 5-7 and BYTES-1 for channels 0-3.\r
+\r
+PUBLIC __GetDMACount:\r
+ PUSH EBP ;\r
+ MOV EBP,ESP ;\r
+ MOV EAX, [EBP+16] ;Channel\r
+ MOV ESI, [EBP+12] ;Return address for count\r
+DMACSelect:\r
+ CMP EAX, 0 ;\r
+ JNE SHORT DMAC1\r
+ MOV DX, DMA10Cnt ;\r
+ JMP SHORT DMACDoIt\r
+DMAC1:\r
+ CMP EAX, 1\r
+ JNE SHORT DMAC2\r
+ MOV DX, DMA11Cnt ;\r
+ JMP SHORT DMACDoIt\r
+DMAC2:\r
+ CMP EAX, 2\r
+ JNE SHORT DMAC3\r
+ MOV DX, DMA12Cnt ;\r
+ JMP SHORT DMACDoIt\r
+DMAC3:\r
+ CMP EAX, 3\r
+ JNE SHORT DMAC5\r
+ MOV DX, DMA13Cnt ;\r
+ JMP SHORT DMACDoIt\r
+DMAC5:\r
+ CMP EAX, 5\r
+ JNE SHORT DMAC6\r
+ MOV DX, DMA21Cnt ;\r
+ JMP SHORT DMACDoIt\r
+DMAC6:\r
+ CMP EAX, 6\r
+ JNE SHORT DMAC7\r
+ MOV DX, DMA22Cnt ;\r
+ JMP SHORT DMACDoIt\r
+DMAC7:\r
+ MOV DX, DMA23Cnt ;\r
+ CMP EAX, 7\r
+ JE SHORT DMACDoIt\r
+ MOV EAX, ErcDMAChannel ;No such channel!\r
+ MOV ESP,EBP ;\r
+ POP EBP ;\r
+ RETF 8 ; 20 bytes of junk to dump\r
+\r
+DMACDoIt:\r
+ CLI\r
+ IN AL,DX ;\r
+ MOV CL,AL ;\r
+ IN AL,DX ;\r
+ MOV CH,AL ;CX has words/bytes left in DMA\r
+ STI ;\r
+ MOV WORD PTR [ESI], CX ;\r
+ XOR EAX, EAX ; No Error\r
+ MOV ESP,EBP ;\r
+ POP EBP ;\r
+ RETF 8 ; 8 bytes to dump from the stack\r
+\r
+;=========== module end ==============\r