Article 5642 of alt.sb.programmer: Path: news.doit.wisc.edu!brodskye From: brodskye at cae.wisc.edu Newsgroups: alt.sb.programmer,rec.games.programmer Subject: Re: SB with Watcom Date: 23 Apr 1997 01:53:52 GMT Organization: University of Wisconsin, Madison Lines: 70 Message-ID: <5jjq3g$c22@news.doit.wisc.edu> References: Reply-To: ebrodsky@pobox.com NNTP-Posting-Host: hp-4.cae.wisc.edu Originator: brodskye at hp-4.cae.wisc.edu Xref: news.doit.wisc.edu alt.sb.programmer:5642 rec.games.programmer:125722 In article , Lennart Benoot wrote: >I've got a small problem. Here's the situation: I've been programming >16-bit Borland c++. Recently I moved to Watcom and had to rewrite some >code for 32-bit flat memory model. Most of it is converted now except the >Sound blaster stuff. What I want to do is sending a sample to the dsp >using DMA. How do I calculate the adress to be send to the dma chip? >Essentialy I don't know how to program DMA in 32-bit mode. Is there >anybody out there willing to share this info? The biggest difference is in memory addressing. DMA only works easily with buffers in the first megabyte of physical memory. This isn't a problem in real-mode, as everything is there, but in protected mode, memory allocated with malloc may be anywhere in physical memory. The Watcom C run-time libraries don't provide a function for allocating conventional memory, but you can ask the DPMI server (dos4gw) to give you a buffer. There are three calls that are relevant to conventional memory, 100h/101h/102h, which are for allocating, freeing, and resizing buffers of conventional memory. I don't remember which is which, but you can find the information in any DPMI reference. I use the official documentation, which Intel will send out for free, but you can download an electronic version from x2ftp.oulu.fi The allocate call returns two bits of information: a "selector" and a "segment." The selector is a protected mode handle to the memory's descriptor and isn't necessary for dealing with the memory, except when you want to free it. The segment is the DOS real-mode segment, or the address divided by 16. Unlike real-mode, you cannot simply load this segment a segment register and access the memory (if you want to do it that way, you can access the memory using the selector and 48-bit far pointers). Watcom has a split memory model, with the first megabyte of physical memory mapped to the first megabyte of its logical address space and the data segment and the rest of memory mapped starting at 0x400000. Therefore, when dealing with buffers in the first megabyte of memory, the physical address can simply be typecasted to a near pointer. The physical address is sixteen times the segment, so "char *buf = (char *)(16*seg)". This is not portable, and it does not work with Borland's 32RTM and other extenders. The finally issue is telling the DMA controller where your buffer is. The method is no different than in real-mode; it is in fact easier, since you already have the physical address and don't need to mess with segment:offset addressing. I haven't written any DMA code for several months, but I believe that the best ways to find the page and offset are: 8-bit: page = addr >> 16; offset = addr - (page<<16); 16-bit: page = (addr >> 17) << 1; offset = (addr - (page<<16)) >> 2; [NOTE: please correct the 16-bit offset to: offset = (addr - (page<<16)) >> 1;] Other than DMA addressing, no major changes should be required for protected mode, except the removal of any code put in to deal with segment:offset nonsense. With Watcom C, interrupts are handled automatically, and a routine installed with _dos_setvect will automatically handle interrupts whether the machine is in real-mode or protected-mode. The Watcom version of my MIDILib uses exactly the same code as the Borland real-mode version. If this all seems terribly complicated, consider my Watcom C DOS/4GW version of SMIX to be the example code accompanying this message. The lowmem module and the init_mixing routine in smix contains the code you are interested in. Ethan Brodsky -- ----