/* * util.c * * Assorted IRQ/DMA utility functions for DJGPP 2.01 * * Copyright (C) 1998 Fabian Nunez * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * The author can be reached by email at: fabian@cs.uct.ac.za * * or by airmail at: Fabian Nunez * 10 Eastbrooke * Highstead Road * Rondebosch 7700 * South Africa */ #include <kernel/kernel.h> #include <kernel/driver.h> #include <kernel/memory.h> #include "util.h" /* definition of DMA channels */ const static DmaChannel dmainfo[] = { { 0x87, 0x00, 0x01 }, { 0x83, 0x02, 0x03 }, { 0x81, 0x04, 0x05 }, { 0x82, 0x06, 0x07 } }; /* * this allocates a 4KB buffer in the < 1M range, maps it and returns the * linear address, also setting the physical in the integer pointed at */ long alloc_dma_buffer() { addr_t phys; phys = memAllocLow(); assert(phys + PAGE_SIZE < 0x100000); assert(((phys + PAGE_SIZE) & 0xffff) >= ((phys + PAGE_SIZE) & 0xffff)); wprintf(L"DMA transfer buffer is at 0x%x\n", phys); return phys; } /* * this sets up a DMA trasfer between a device and memory. Pass the DMA * channel number (0..3), the physical address of the buffer and transfer * length. If 'read' is TRUE, then transfer will be from memory to device, * else from the device to memory. */ void dma_xfer(int channel,long physaddr,int length,BOOL read) { long page,offset; assert(channel < 4); /* calculate dma page and offset */ page = physaddr >> 16; offset = physaddr & 0xffff; length -= 1; /* with dma, if you want k bytes, you ask for k - 1 */ disable(); /* disable irq's */ /* set the mask bit for the channel */ out(0x0a,channel | 4); /* clear flipflop */ out(0x0c,0); /* set DMA mode (write+single+r/w) */ out(0x0b,(read ? 0x48 : 0x44) + channel); /* set DMA page */ out(dmainfo[channel].page,page); /* set DMA offset */ out(dmainfo[channel].offset,offset & 0xff); /* low byte */ out(dmainfo[channel].offset,offset >> 8); /* high byte */ /* set DMA length */ out(dmainfo[channel].length,length & 0xff); /* low byte */ out(dmainfo[channel].length,length >> 8); /* high byte */ /* clear DMA mask bit */ out(0x0a,channel); enable(); /* enable irq's */ }