root/Whitix/trunk/memory/dma.c

Revision 2015, 2.8 KB (checked in by mwhitworth, 3 years ago)

Add new DMA pool API.

Line 
1#include <dma.h>
2#include <fs/vfs.h>
3#include <vmm.h>
4#include <print.h>
5#include <module.h>
6
7#define ALIGN(n, a) ALIGN_MASK(n, a-1)
8#define ALIGN_MASK(n, mask) (((n)+(mask)) & ~(mask))
9
10void* DmaAllocConsistent(struct PciDevice* device, unsigned int size, DWORD* dmaAddr)
11{
12        void* ret;
13       
14        if (size > 4096)
15        {
16                KePrint("PciAllocConsistent: more than one page. TODO\n");
17                return NULL;
18        }
19       
20        ret = VirtMapPhysPage(0xC2000000, 0xD0000000, 3);
21       
22        *dmaAddr = VirtToPhys(ret);
23       
24        return ret;
25}
26
27SYMBOL_EXPORT(DmaAllocConsistent);
28
29/* TODO: Have DmaPool cache. */
30
31struct DmaPool* DmaPoolCreate(const char* name, unsigned int size, int align,
32        int boundary)
33{
34        struct DmaPool* retVal;
35        unsigned long allocation;
36       
37        if (!align)
38                align = 1;
39        /* align must be a power of two. */
40        else if (align & (align - 1))
41                return NULL;
42               
43        if (!size)
44                return NULL;
45        else if (size < 4)
46                size = 4;
47               
48        if ((size % align))
49                size = ALIGN(size, align);
50               
51        allocation = MAX(size, PAGE_SIZE);
52               
53        if (!boundary)
54                boundary = allocation;
55        else if ((boundary < size) || (boundary & (boundary - 1)))
56                return NULL;
57               
58        retVal = (struct DmaPool*)MemAlloc(sizeof(struct DmaPool));
59               
60        INIT_LIST_HEAD(&retVal->pageList);
61        retVal->name = name;
62        retVal->size = size;
63        retVal->boundary = boundary;
64        retVal->allocation = allocation;
65       
66        return retVal;
67}
68
69SYMBOL_EXPORT(DmaPoolCreate);
70
71static void DmaPoolPageInit(struct DmaPool* pool, struct DmaPage* page)
72{
73        unsigned int offset = 0;
74        unsigned int boundNext = pool->boundary;
75       
76        do
77        {
78                unsigned int next = offset + pool->size;
79               
80                if (pool->size + next >= boundNext)
81                {
82                        next = boundNext;
83                        boundNext += pool->boundary;
84                }
85               
86                *(int*)(page->virtAddr + offset) = next;
87                offset = next;
88        } while (offset < pool->allocation);
89}
90
91static struct DmaPage* DmaPoolAllocPage(struct DmaPool* pool)
92{
93        struct DmaPage* page;
94       
95        page = (struct DmaPage*)MemAlloc(sizeof(struct DmaPage));
96
97        ZeroMemory(page, sizeof(struct DmaPage));
98       
99        page->virtAddr = DmaAllocConsistent(NULL, pool->allocation, &page->dmaAddr);
100       
101        DmaPoolPageInit(pool, page);
102       
103        ListAdd(&page->next, &pool->pageList);
104        page->inUse = 0;
105        page->offset = 0;
106       
107        return page;
108}
109
110void* DmaPoolAlloc(struct DmaPool* pool, unsigned long* dmaAddr)
111{
112        unsigned long flags;
113        struct DmaPage* page;
114        void* retVal;
115        int offset;
116       
117        IrqSaveFlags(flags);
118               
119        ListForEachEntry(page, &pool->pageList, next)
120                if (page->offset < pool->allocation)
121                        goto found;
122       
123        page = DmaPoolAllocPage(pool);
124       
125found:
126        page->inUse++;
127        offset = page->offset;
128        page->offset = *(int*)(page->virtAddr + offset);
129        retVal = page->virtAddr + offset;
130        *dmaAddr = page->dmaAddr + offset;
131               
132        IrqRestoreFlags(flags);
133       
134        return retVal;
135}
136
137SYMBOL_EXPORT(DmaPoolAlloc);
138
139void DmaPoolFree(struct DmaPool* pool, void* ptr)
140{
141}
142
143SYMBOL_EXPORT(DmaPoolFree);
144
145void DmaPoolDestroy(struct DmaPool* pool)
146{
147}
148
149SYMBOL_EXPORT(DmaPoolDestroy);
Note: See TracBrowser for help on using the browser.