#include <const.h>
#include <arch/i386.h>
#include <arch/mem.h>
#include <arch/paging.h>
#include <kernel/kernel_map.h>
#include <kernel/kmalloc.h>
#include <kernel/task.h>
#include <kernel/dma.h>
Go to the source code of this file.
Defines | |||||||||
#define | DMA_MEMORY_DIM (DMA_MEMORY_END-DMA_MEMORY_START) | ||||||||
The size of the DMA memory area. | |||||||||
#define | DMA_FREE_FRAME 0 | ||||||||
The DMA-memory frame is marked as free. | |||||||||
#define | DMA_BUSY_FRAME 1 | ||||||||
The DMA-memory frame is marked as busy. | |||||||||
Functions | |||||||||
void | dma_xfer (unsigned channel, addr_t physaddr, size_t length, bool read) | ||||||||
Set up a DMA transfer between a device and memory.
| |||||||||
void | dma_alloc_init () | ||||||||
Initialize the DMA memory allocator. | |||||||||
void * | dma_phys_alloc (size_t len) | ||||||||
Return a pointer of len contiguous bytes into the DMA address space.
| |||||||||
bool | dma_phys_free (size_t dma_start, size_t len) | ||||||||
Free the DMA memory area from dma_start to dma_start+len address.
| |||||||||
Variables | |||||||||
dma_channel_t | dmainfo [] | ||||||||
Definition of DMA channels. | |||||||||
byte * | dma_free_frames | ||||||||
DMA free frames vector. It maps every frame into the DMA memory area. On i386 we have to reserve the first 16MB of physical memory to the DMA, because on the bus we have a 24-bit register dedicated to the addressing (2^24=16MB). |
Definition in file dma.c.
|
Initialize the DMA memory allocator.
Definition at line 116 of file dma.c.
00117 { 00118 uint32_t i; 00119 extern dword *K_VIR_END; 00120 00121 // Initialize the DMA free frames vector // 00122 dma_free_frames = kmalloc(DMA_MEMORY_DIM/PAGE_SIZE); 00123 memset(dma_free_frames, DMA_FREE_FRAME, DMA_MEMORY_DIM/PAGE_SIZE); 00124 00125 // Set the kernel physical space busy // 00126 for (i=0; i<=(uint32_t)K_VIR_END-K_VIR_START; i+=PAGE_SIZE) 00127 dma_free_frames[K_PHYS_ADDR+i] = DMA_BUSY_FRAME; 00128 } |
|
Return a pointer of
Definition at line 141 of file dma.c.
00142 { 00143 dword i, j, ret; 00144 char flag=0; 00145 00146 // len must be not null! // 00147 if (!len) return(NULL); 00148 00149 // Round up len to frames boundary // 00150 len = PAGE_ALIGN_UP(len); 00151 00152 sched_enter_critical_region(); 00153 00154 // Search for a free dma page // 00155 for(i=0; i<(DMA_MEMORY_DIM/PAGE_SIZE); i++) 00156 { 00157 if (dma_free_frames[i] == DMA_FREE_FRAME) 00158 { 00159 // Found a free frame! // 00160 // OK, now I require (len/PAGE_SIZE-1) // 00161 // others free frames // 00162 for(j=1, flag=0; j<len/PAGE_SIZE; j++) 00163 { 00164 if (dma_free_frames[i+j] == DMA_BUSY_FRAME) 00165 { 00166 // Nooo! Found a busy frame! // 00167 flag = 1; 00168 break; 00169 } 00170 } 00171 if (flag == 1) 00172 { 00173 // Not a valid contiguous free space. // 00174 // Continue after j position... // 00175 i += j; 00176 } 00177 else 00178 { 00179 // Found a valid contiguous free // 00180 // space, so mark it // 00181 for(j=0; j<len/PAGE_SIZE; j++) 00182 dma_free_frames[i+j] = DMA_BUSY_FRAME; 00183 break; 00184 } 00185 } 00186 } 00187 // Check if we have found the free DMA location // 00188 if (flag == 0) 00189 // We found it!!! // 00190 ret = (i * PAGE_SIZE + DMA_MEMORY_START); 00191 else 00192 // Not found!!! // 00193 ret = NULL; 00194 00195 sched_leave_critical_region(); 00196 return((void *)ret); 00197 } |
|
Free the DMA memory area from
Definition at line 210 of file dma.c.
00211 { 00212 int i; 00213 00214 if (!len) return(FALSE); 00215 00216 // Round up len to frames boundary // 00217 len = PAGE_ALIGN_UP(len); 00218 00219 if ( 00220 (dma_start >= DMA_MEMORY_START) && (dma_start < DMA_MEMORY_END) && 00221 ((dma_start + len) < DMA_MEMORY_END) 00222 ) 00223 { 00224 sched_enter_critical_region(); 00225 00226 // Mark the DMA region as free // 00227 for(i=(dma_start-DMA_MEMORY_START)/PAGE_SIZE; i<DMA_MEMORY_DIM/PAGE_SIZE; i++) 00228 dma_free_frames[i] = DMA_FREE_FRAME; 00229 00230 sched_leave_critical_region(); 00231 00232 return(TRUE); 00233 } 00234 else 00235 // Invalid DMA memory range // 00236 return(FALSE); 00237 } |
|
Set up a DMA transfer between a device and memory.
Definition at line 47 of file dma.c.
00048 { 00049 int page, offset; 00050 00051 if (channel > 3) return; 00052 00053 // calculate dma page and offset // 00054 page = physaddr >> 16; 00055 offset = physaddr & 0xFFFF; 00056 length -= 1; // with dma, if you want k bytes, you ask for k-1 // 00057 00058 disable(); 00059 00060 // set the mask bit for the channel // 00061 outportb(0x0A, channel | 0x04); 00062 00063 // clear flipflop // 00064 outportb(0x0C, 0x00); 00065 00066 // set DMA mode (write+single+r/w) // 00067 outportb(0x0B, (read ? 0x48 : 0x44) + channel); 00068 00069 // set DMA page // 00070 outportb(dmainfo[channel].page, page); 00071 00072 // set DMA offset // 00073 outportb(dmainfo[channel].offset, offset & 0xFF); // low byte // 00074 outportb(dmainfo[channel].offset, offset >> 8); // high byte // 00075 00076 // set DMA length // 00077 outportb(dmainfo[channel].length, length & 0xFF); // low byte // 00078 outportb(dmainfo[channel].length, length >> 8); // high byte // 00079 00080 // clear DMA mask bit // 00081 outportb(0x0A, channel); 00082 00083 enable(); 00084 } |