#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 }
|
1.2.18