|
|
1.1 root 1: /*
2: * UAE - The Un*x Amiga Emulator
3: *
4: * DOS DMA interface.
5: *
6: * (c) 1996 Peter Remmers
7: */
8:
9: #include <stdlib.h>
10: #include <pc.h>
11: #include <dpmi.h>
12:
13: #include "dos-dma.h"
14:
15: /* some useful macros */
16: #define LOBYTE(x) ((unsigned char)(((unsigned short)(x)) & 0xFF))
17: #define HIBYTE(x) ((unsigned char)(((unsigned short)(x)) >> 8))
18: #define LOWORD(x) ((unsigned short)(((unsigned long)(x)) & 0xFFFF))
19: #define HIWORD(x) ((unsigned short)(((unsigned long)(x)) >> 16))
20:
21: const unsigned short DMA_Address [8] = {0x00,0x02,0x04,0x06,0xC0,0xC4,0xC8,0xCC};
22: const unsigned short DMA_Count [8] = {0x01,0x03,0x05,0x07,0xC2,0xC6,0xCA,0xCE};
23:
24: const unsigned short DMA_PageLo[8]= { 0x87, 0x83, 0x81, 0x82, 0x8F, 0x8B, 0x89, 0x8A};
25: const unsigned short DMA_PageHi[8]= {0x487,0x483,0x481,0x482,0x48F,0x48B,0x489,0x48A};
26:
27: #define DMA_Status(ch) ((ch)<4 ? 0x08 : 0xD0) /* Read */
28: #define DMA_Command(ch) ((ch)<4 ? 0x08 : 0xD0) /* Write */
29: #define DMA_Request(ch) ((ch)<4 ? 0x09 : 0xD2)
30: #define DMA_MaskSingle(ch) ((ch)<4 ? 0x0A : 0xD4)
31: #define DMA_Mode(ch) ((ch)<4 ? 0x0B : 0xD6)
32: #define DMA_ClearFF(ch) ((ch)<4 ? 0x0C : 0xD8)
33: #define DMA_Latch(ch) ((ch)<4 ? 0x0D : 0xDA) /* Read */
34: #define DMA_MasterClear(ch) ((ch)<4 ? 0x0D : 0xDA) /* Write */
35: #define DMA_ClearMask(ch) ((ch)<4 ? 0x0E : 0xDC)
36: #define DMA_MaskAll(ch) ((ch)<4 ? 0x0F : 0xDE)
37:
38:
39: /* allocate DOS memory that does not cross a physical 64k boundary */
40: unsigned long DMA_AllocDMABuf (_go32_dpmi_seginfo *info)
41: {
42: unsigned long Phys;
43: unsigned long bytes;
44:
45: /* first allocate requested size */
46: if (_go32_dpmi_allocate_dos_memory (info)) return (NULL);
47:
48: Phys = (info->rm_segment) << 4;
49: bytes = (info->size) << 4;
50:
51: /* if memory does not cross boundary we are lucky and that's it */
52: if (HIWORD(Phys + bytes) == HIWORD (Phys)) return (Phys);
53:
54: /* if not, free memory */
55: _go32_dpmi_free_dos_memory (info);
56:
57: /* and allocate twice the requested size */
58: bytes <<= 1;
59: info->size <<= 1;
60: if (_go32_dpmi_allocate_dos_memory (info)) return (NULL);
61:
62: /* and take the half that does not cross a boundary */
63: Phys = (info->rm_segment) << 4;
64: if (HIWORD(Phys + bytes) == HIWORD (Phys)) return (Phys);
65:
66: return (Phys + (bytes>>1));
67: }
68:
69: void DMA_Mask (unsigned char channel)
70: {
71: outportb(DMA_MaskSingle(channel), 4 + (channel&3));
72: }
73:
74: void DMA_UnMask (unsigned char channel)
75: {
76: outportb(DMA_MaskSingle(channel), channel&3);
77: }
78:
79: void DMA_InitTransfer (unsigned char channel, unsigned char Mode,
80: unsigned long PhysAddr, unsigned short Count)
81: {
82: unsigned short Page;
83: unsigned short Addr;
84:
85: if (channel & 4) Count >>= 1;
86: Count--;
87:
88: Page = HIWORD(PhysAddr);
89: if (channel & 4) PhysAddr >>= 1;
90: Addr = LOWORD (PhysAddr);
91:
92: outportb (DMA_MaskSingle(channel), (channel&3) + 0x04);
93: outportb (DMA_Mode (channel), (channel&3) | (Mode&0xFC));
94: outportb (DMA_ClearFF (channel), 0);
95: outportb (DMA_Count [channel], LOBYTE(Count));
96: outportb (DMA_Count [channel], HIBYTE(Count));
97: outportb (DMA_Address [channel], LOBYTE(Addr));
98: outportb (DMA_Address [channel], HIBYTE(Addr));
99: outportb (DMA_PageLo [channel], LOBYTE(Page));
100: outportb (DMA_PageHi [channel], HIBYTE(Page));
101: outportb (DMA_MaskSingle(channel), channel&3);
102: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.