1004 lines
31 KiB
Plaintext
1004 lines
31 KiB
Plaintext
Virtual DMA Services (VDS)
|
|
Version 1.00
|
|
Printed July 16, 1990
|
|
Table Of Contents
|
|
|
|
|
|
Introduction..............................................1
|
|
|
|
Notes For Writing DMA Device Drivers......................2
|
|
|
|
Notes For DMA Service Environments........................3
|
|
|
|
Services..................................................6
|
|
Reserved Subfunctions.................................7
|
|
Get Version...........................................8
|
|
Lock DMA Region.......................................9
|
|
Unlock DMA Region....................................11
|
|
Scatter/Gather Lock Region...........................12
|
|
Scatter/Gather Unlock Region.........................14
|
|
Request DMA Buffer...................................15
|
|
Release DMA Buffer...................................16
|
|
Copy Into DMA Buffer.................................17
|
|
Copy Out Of DMA Buffer...............................18
|
|
Disable DMA Translation..............................19
|
|
Enable DMA Translation...............................20
|
|
|
|
Summary of Error Codes and Option Flags..................21
|
|
.End Table C.
|
|
|
|
|
|
INTRODUCTION
|
|
|
|
|
|
DOS device drivers which perform DMA, program a controller
|
|
with an address of a buffer region. All software running in
|
|
protected mode environments, whether running in virtual 8086
|
|
mode or in protected mode under a DOS extender, usually can
|
|
not determine the physical address of their DMA region. The
|
|
DMA controller also places further restrictions upon
|
|
acceptable DMA regions: they must be in contiguous physical
|
|
memory, on XTs they must be in the first 1Mb of memory and
|
|
on XTs, ATs and compatibles they must not cross 64Kb or
|
|
128Kb alignment boundaries. These services provide the
|
|
necessary support to allow a device driver or application
|
|
program to obtain the necessary information to program a DMA
|
|
transfer using either the on board DMA controller or a
|
|
busmaster DMA controller.
|
|
|
|
The services are provided through software interrupt 4Bh.
|
|
Programs must examine bit five (5) of the byte at
|
|
0040:007Bh. If the bit is set then they should use the DMA
|
|
services. Otherwise, the device can assume that all memory
|
|
is mapped linear = physical (probably running in real mode,
|
|
this can be a dangerous assumption, if the machine is
|
|
actually running in virtual mode, because the protected mode
|
|
software may not support this specification, and there is
|
|
not a method for checking for physical = linear).
|
|
|
|
An implementation of the DMA services must provide either
|
|
automatic remapping of pages to force regions of memory to
|
|
be physically contiguous or support a DMA buffer with a
|
|
minimum size of 16K, if paging is enabled by the system
|
|
software. Most 286 software can get by without supporting
|
|
either option.
|
|
|
|
With the exception of the AX register and unless otherwise
|
|
specified, all registers and flags are preserved across DMA
|
|
service calls. The AX register contents are undefined on
|
|
return unless the carry flag is set in which case AL
|
|
contains an error code.
|
|
|
|
NOTES FOR WRITING DMA DEVICE DRIVERS
|
|
|
|
|
|
DMA devices that use these services must continually monitor
|
|
bit five (5) of the byte at 0040:007Bh before programming
|
|
DMA. The services may be initialized or turned off at any
|
|
time.
|
|
|
|
For example, when a program begins using simulated expanded
|
|
memory a "LIMulator" will place the machine in Virtual 8086
|
|
mode and enable the DMA services. When all LIM memory has
|
|
been deallocated it will return the machine to real mode and
|
|
turn off the DMA services.
|
|
|
|
Note also that the type of DMA support provided may change
|
|
dynamically. For example, the user may run one protected
|
|
mode environment, exit it, and then run another protected
|
|
mode environment. In this case the services will be
|
|
provided by two different implementations.
|
|
|
|
There are various levels of support that device drivers can
|
|
have for DMA. These options are listed below in order from
|
|
best to worst:
|
|
|
|
Support scatter/gather on the hardware adaptor
|
|
Break DMA requests up in software so that a buffer is
|
|
never required
|
|
Break up DMA into 16K or smaller pieces so the default
|
|
buffer can be used
|
|
Force the user to override the buffer size
|
|
|
|
The last option is really not acceptable. At the very least
|
|
your software should chop up transfers into 16K pieces. For
|
|
example, it is acceptable to break hard disk transfers at
|
|
track boundaries. A normal hard disk track will fit into a
|
|
16K buffer.
|
|
|
|
DMA devices that are not as timing sensitive as disk drives
|
|
should break up transfers. Ideally, all DMA adaptors would
|
|
support scatter/gather in hardware.
|
|
|
|
In some situations a device driver has a real physical
|
|
address that it wants to use in a DMA transfer. These
|
|
physical addresses may be from memory allocated through XMS
|
|
or INT 15h before DMA services were provided, or may be for
|
|
memory that exists on an adapter card, etc. In these
|
|
situations, DMA lock calls should not be called, because the
|
|
service routines must interpret region addresses as linear
|
|
addresses. It is necessary, however to call the
|
|
Disable/Enable Translation services, if the standard DMA
|
|
controller is used for the transfer.
|
|
|
|
By convention, a buffer ID of zero in the DDS indicates that
|
|
no buffer has been allocated. Device driver software can
|
|
check this field to determine if a buffer was allocated.
|
|
|
|
|
|
NOTES FOR IMPLEMENTING DMA SERVICES
|
|
|
|
|
|
The recommended method of supporting these services is to
|
|
use a DMA buffer since it has been found to be faster than
|
|
attempting to remap memory on 386 machines. On 286 machines
|
|
it is possible to not implement a buffer; on these machines
|
|
the software calling the services must already know how to
|
|
split up transfers to deal with crossing alignment
|
|
boundaries. It is necessary to return the "No buffer
|
|
available" error (04h) for the Request DMA Buffer service
|
|
(07h).
|
|
|
|
All implementations of these services should provide
|
|
mechanisms for overriding the size of the DMA buffer or
|
|
remap region. Also, all implementations should provide a
|
|
mechanism for forcing the buffer or remap region to reside
|
|
in the first megabyte of physical memory. The actual
|
|
mechanism for doing this will be implementation dependent.
|
|
For example, some programs may use a configuration file
|
|
while others could use command line switches.
|
|
|
|
Lock calls for memory which is not "owned" by the provider
|
|
of these DMA services, memory allocated before the provider
|
|
started running including low memory, EBIOS data area and
|
|
extended memory allocated through INT 15h or XMS, must not
|
|
fail. If auto-remapping is supported, then pages must be
|
|
remapped to force contiguous regions. If auto-remapping is
|
|
not supported, then it is necessary for the provider to keep
|
|
these memory areas contiguous. Additionally, in some
|
|
environments, device drivers will exist which attempt long
|
|
term DMA transfers. In these environments it is necessary
|
|
to allow the user to configure the software so that such
|
|
transfers can take place. One solution is to force long
|
|
term DMA device drivers to be loaded after the provider
|
|
software. The other solution is to keep all "unowned"
|
|
memory mapped at the original location so linear equals
|
|
physical; this allows transfers started prior to DMA
|
|
services being provided to continue as normal.
|
|
|
|
Since other hardware/software services can be provided on
|
|
the INT 4Bh chain, it is necessary for provider software to
|
|
determine if they should chain interrupts when AH is not
|
|
81h. On Micro Channel machines this can be done by
|
|
examining bit three (3) in the byte at 0040:007Bh, if the
|
|
bit is set, then chaining is required, if it is clear, then
|
|
it is necessary to examine the vector contents. If the
|
|
vector contents are 0, or point to E000h or F000h ROM, then
|
|
the interrupt should not be chained, because it may go to a
|
|
default IRQ handler which may EOI an outstanding hardware
|
|
interrupt. Summary of bit 3 in 0040:007Bh:
|
|
|
|
|
|
Bit 3 Interrupt 4Bh Intercepted Indicator (Micro
|
|
Channel Only)
|
|
|
|
= 0 Interrupt vector not intercepted. check contents
|
|
of the interrupt vector. If contents are 0:0 or
|
|
segment values of E000h or F000h, chaining is not
|
|
permitted.
|
|
= 1 Interrupt vector intercepted, chaining required.
|
|
|
|
|
|
On other non-Micro Channel architectures examining the
|
|
vector value may be the only way to determine if interrupts
|
|
should be chained.
|
|
|
|
If not chaining, then the interrupt should be ignored with
|
|
an IRET without modifying registers or flags.
|
|
|
|
|
|
Determining Which Error Codes to Return
|
|
|
|
The following logic should be used for the Lock DMA Region
|
|
service (AX=8103h):
|
|
|
|
IF region contiguous THEN
|
|
IF region does not cross alignment boundary THEN
|
|
Lock region, set buffer ID to zero, and return
|
|
with carry clear
|
|
ELSE
|
|
DO Buffer/Remap
|
|
ENDIF
|
|
ELSE
|
|
DO Buffer/Remap
|
|
ENDIF
|
|
|
|
|
|
BUFFER/REMAP:
|
|
IF buffer supported THEN
|
|
IF buffer disable flag clear THEN
|
|
DO Buffer
|
|
ELSE
|
|
Return with carry flag set and AL=1, 2, or 3
|
|
ENDIF
|
|
ELSE
|
|
IF remap supported THEN
|
|
IF remap disable flag clear THEN
|
|
DO Remap
|
|
ELSE
|
|
Return with carry flag set and AL=1, 2, or 3
|
|
ENDIF
|
|
ELSE
|
|
Return with carry flag set and AL=1, 2, or 3
|
|
ENDIF
|
|
ENDIF
|
|
|
|
|
|
BUFFER:
|
|
IF buffer available THEN
|
|
IF region size <= buffer size THEN
|
|
Allocate buffer
|
|
IF copy flag set THEN
|
|
Copy data from linear region to buffer
|
|
ENDIF
|
|
Set buffer ID (non-zero), set physical address
|
|
field to buffer physical address, and return
|
|
with carry clear
|
|
ELSE
|
|
Return with carry flag set and AL=05h
|
|
ENDIF
|
|
ELSE
|
|
Return with carry flag set and AL=06h
|
|
ENDIF
|
|
|
|
|
|
|
|
REMAP:
|
|
IF region can be forced contiguous THEN
|
|
IF region will not cross specified boundary THEN
|
|
Force region contiguous, set physical address
|
|
field, set buffer ID to zero, and return with
|
|
carry clear
|
|
ELSE
|
|
Return with carry set and AL=02h
|
|
ENDIF
|
|
ELSE
|
|
Return with carry set and AL=01h
|
|
ENDIF
|
|
|
|
|
|
SERVICES
|
|
|
|
|
|
Most services take a pointer to a DMA descriptor structure
|
|
(DDS) as a parameter. The structure is defined as follows:
|
|
|
|
|
|
DESCRIPTION OFFSET
|
|
|
|
Region Size 00h
|
|
|
|
Offset 04h
|
|
|
|
Buffer ID Segment/Selector 08h
|
|
|
|
Physical Address 0Ch
|
|
|
|
|
|
Region Size is a dword at offset 0. It specifies the size
|
|
of the DMA region in bytes.
|
|
|
|
Offset and Segment/Selector are an fword pair at offset 04h.
|
|
They specify a 48-bit segment:offset pointer for
|
|
virtual 8086 mode, or a selector:offset pointer for
|
|
protected mode programs. Note that if the linear
|
|
address has already been determined then you may set
|
|
the segment/selector field to 0 and place the linear
|
|
address in the linear offset field. It is possible to
|
|
specify 32-bit offsets, even with real mode segment
|
|
values; this makes it much easier for device drivers to
|
|
split up DMA transfers, by simply modifying the offset
|
|
without having to modify the segment/selector.
|
|
|
|
Buffer ID is a word at offset 0Ah. This field is filled in
|
|
by the Request DMA Buffer service and possibly the Lock
|
|
DMA Region service.
|
|
|
|
Physical Address is a dword at offset 0Ch. This field is
|
|
filled in by the Lock DMA Region and Request DMA Buffer
|
|
services.
|
|
|
|
============================================================
|
|
|
|
Reserved Subfunctions
|
|
|
|
|
|
Functions 00h, 01h and 0Dh through 0FFh are reserved. If
|
|
called they will return with the Carry flag set and AL = 0Fh
|
|
(Function not supported).
|
|
|
|
Programmer's Notes
|
|
|
|
None
|
|
|
|
============================================================
|
|
|
|
Get Version
|
|
|
|
|
|
This service returns the version of DMA services as well as
|
|
information about the hardware, size of buffers, and support
|
|
of automatic memory remapping.
|
|
|
|
To Call
|
|
|
|
AH = 81h
|
|
AL = 02h
|
|
DX = Flags
|
|
All bits reserved and must be zero
|
|
|
|
Returns
|
|
|
|
If function was successful:
|
|
Carry clear
|
|
AH = Major specification version # (binary, currently
|
|
1)
|
|
AL = Minor specification version # (binary, currently
|
|
0)
|
|
BX = Product number
|
|
CX = Product revision number
|
|
SI:DI = Maximum DMA buffer size in bytes that can be
|
|
requested.
|
|
DX = Flags
|
|
Bit 0 = 1 if PC/XT bus architecture (DMA in first
|
|
meg only)
|
|
Bit 1 = 1 if physical buffer/remap region is in
|
|
first meg
|
|
Bit 2 = 1 if automatic remap supported
|
|
Bit 3 = 1 if all memory physically contiguous
|
|
Other flags reserved and must be zero
|
|
If function was not successful:
|
|
Carry flag set
|
|
AL = Error code
|
|
10h = Reserved flag bits set in DX
|
|
|
|
Programmer's Notes
|
|
|
|
o The version numbers returned in AH and AL are used
|
|
to determine the level of functionality supported
|
|
by the current implementation. The current driver
|
|
will return AX=0100h.
|
|
o Bit 3 of the flag word will only be set in
|
|
environments that run in protected mode but do not
|
|
use paging, such as 286 DOS extenders. In these
|
|
environments, the DMA services are only provided
|
|
to convert selector:offset linear address pairs
|
|
into physical addresses.
|
|
|
|
============================================================
|
|
|
|
Lock DMA Region
|
|
|
|
|
|
This service is used to determine if a target DMA region is
|
|
in contiguous physical memory. If it is contiguous, then
|
|
this service returns the physical address of the region so
|
|
that the software can program for the DMA. A locked DMA
|
|
region must always be unlocked once the DMA is complete.
|
|
|
|
If the DMA controller has memory placement restrictions
|
|
(i.e. below 1Mb), then it can compare the returned physical
|
|
address; if the address is not suitable, then the program
|
|
must unlock the region and request a DMA buffer.
|
|
|
|
Some implementations of the DMA services will attempt to
|
|
remap pages to force the region to be contiguous physical
|
|
memory. The caller can disable this behavior by setting bit
|
|
3 in DX. Normally, it is faster for a device to split
|
|
transfers or use a DMA buffer instead of going through the
|
|
remap process.
|
|
|
|
It is often convenient to use the automatic buffer
|
|
allocation option of this service. If the DMA region can
|
|
not be locked for any reason then the service will attempt
|
|
to allocate a DMA buffer. If desired, the data in the
|
|
region will be automatically copied into the buffer.
|
|
|
|
To Call
|
|
|
|
AH = 81h
|
|
AL = 03h
|
|
DX = Flags
|
|
Bit 1 = 1 if data should be copied into buffer
|
|
(ignored if bit 2 = 1)
|
|
Bit 2 = 1 if buffer should not be allocated if
|
|
region is not contiguous or crosses a
|
|
physical alignment boundary specified by bits
|
|
4 and 5
|
|
Bit 3 = 1 if automatic remap should not be
|
|
attempted
|
|
Bit 4 = 1 if region must not cross a 64K physical
|
|
alignment boundary
|
|
Bit 5 = 1 if region must not cross a 128K physical
|
|
alignment boundary
|
|
All other bits reserved and must be zero
|
|
ES:DI = Pointer to DMA Descriptor Structure
|
|
The caller must fill in the region size, linear
|
|
offset, and selector/segment fields before calling
|
|
this service
|
|
|
|
Returns
|
|
|
|
If function was successful:
|
|
Carry flag clear
|
|
Memory is locked
|
|
Physical address field of DDS contains the starting
|
|
physical address of the region.
|
|
The buffer ID field will contain the ID of the
|
|
allocated buffer or 0 if no buffer was allocated.
|
|
|
|
If function was not successful:
|
|
Carry flag set
|
|
Memory is not locked
|
|
Region size field of DDS contains the maximum
|
|
contiguous length in bytes.
|
|
AL = Error code
|
|
01h = Region specified was not contiguous memory
|
|
02h = Region crossed a physical alignment boundary
|
|
03h = Unable to lock pages (virtual memory systems
|
|
only)
|
|
05h = Region too large for buffer
|
|
06h = Buffer currently in use
|
|
07h = Invalid memory region
|
|
10h = Reserved flag bits set in DX
|
|
|
|
Programmer's Notes
|
|
|
|
o Memory is locked on a page granular basis. A
|
|
single page can be locked more than once, thus
|
|
allowing two DMA regions to overlap on a single
|
|
page. Page locking is maintained as a count.
|
|
Some systems need not maintain a count since
|
|
memory will never be discarded or moved. In these
|
|
systems, Unlock DMA Region will never fail.
|
|
o If the automatic buffer allocation option is
|
|
selected by clearing bit 2 of the flags in DX,
|
|
then a buffer will be automatically allocated if
|
|
the region could not be locked. If data should be
|
|
copied into the buffer for a memory read operation
|
|
then bit 1 of the flags in DX should be set. If
|
|
lock is going to fail and bit 2 is clear, but no
|
|
buffer is supported, then the actual cause of the
|
|
error is reported as the error message, rather
|
|
than returning a buffer not available error (4).
|
|
o You may want to wait in a loop if this function
|
|
returns a "Buffer in use" error to allow another
|
|
device time to release the buffer. For more
|
|
details refer to the documentation for Request DMA
|
|
Buffer on page 14.
|
|
o The buffer alignment mask should be used for
|
|
devices that have physical memory boundary
|
|
constraints. For example, on an AT architecture,
|
|
the standard DMA controllers will "wrap" at 64K or
|
|
128K physical boundaries. If the DMA controller
|
|
being programmed has an alignment constraint, then
|
|
the applicable bit in DX should be set.
|
|
|
|
===========================================================
|
|
|
|
Unlock DMA Region
|
|
|
|
|
|
Service to unlock a previously locked DMA region.
|
|
|
|
To Call
|
|
|
|
AH = 81h
|
|
AL = 04h
|
|
DX = Flags
|
|
Bit 1 = 1 if data should be copied out of buffer
|
|
All other bits reserved and must be zero
|
|
ES:DI = Pointer to DMA Descriptor Structure
|
|
The caller must fill in the region size, physical
|
|
address, and buffer ID fields before calling this
|
|
service (Usually the caller simply passes the same
|
|
structure which was filled in by the call to Lock
|
|
DMA Region).
|
|
|
|
Returns
|
|
|
|
If function was successful:
|
|
Carry flag clear
|
|
Memory is unlocked or no count maintained
|
|
|
|
If function was not successful:
|
|
Carry flag set
|
|
All memory remains locked
|
|
AL = Error code
|
|
08h = Memory was not locked
|
|
0Ah = Invalid Buffer ID
|
|
10h = Reserved flag bits set in DX
|
|
|
|
Programmer's Notes
|
|
|
|
o This service releases a DMA buffer, if one was
|
|
allocated by the Lock DMA Region call (if Buffer
|
|
ID is non-zero in the DDS), so any data in it will
|
|
be lost. If the DMA transfer was a memory write
|
|
operation, then setting bit 1 in the DX flags
|
|
parameter will copy the data out of the buffer
|
|
before it is released.
|
|
|
|
============================================================
|
|
|
|
Scatter/Gather Lock Region
|
|
|
|
|
|
This service is provided so that hardware devices that
|
|
support automatic scatter/gather can determine the actual
|
|
physical regions of and lock an entire linear address range
|
|
in one call. Device drivers that break up DMA requests may
|
|
also want to use this service instead of repeatedly calling
|
|
lock DMA region.
|
|
|
|
To Call
|
|
|
|
AH = 81h
|
|
AL = 05h
|
|
DX = Flags
|
|
Bit 6 = 1 if EDDS should be returned with page
|
|
table entries
|
|
Bit 7 = 1 if only present pages should be locked,
|
|
not present pages will be identified as a
|
|
page table entry of 0 (bit 7 is ignored, if
|
|
bit 6 = 0)
|
|
All other bits reserved and must be zero
|
|
ES:DI = Pointer to one of the following extended DDS:
|
|
|
|
If option bit 6 = 0 then return Extended DDS (EDDS)
|
|
with table of physical regions (address and size
|
|
pairs):
|
|
|
|
|
|
DESCRIPTION OFFSET
|
|
|
|
Region Size in Bytes 00h
|
|
|
|
Linear Offset 04h
|
|
|
|
Reserved Segment/Selector 08h
|
|
|
|
# Used # Avail 0Ch
|
|
|
|
Region 0 Physical Address 10h
|
|
|
|
Region 0 Size in Bytes 14h
|
|
|
|
Region 1 Physical Address 18h
|
|
|
|
Region 1 Size in Bytes 1Ch
|
|
|
|
. . . . . .
|
|
|
|
. . . . . .
|
|
|
|
Region n Physical Address 10h+n*8
|
|
|
|
|
|
|
|
|
|
Region n Size in Bytes 14h+n*8
|
|
|
|
If option bit 6 = 1 then return Extended DDS with table
|
|
of page table entries (1 entry per 4Kb page in the
|
|
same format as 80386 page table entries):
|
|
|
|
|
|
DESCRIPTION OFFSET
|
|
|
|
Region Size in Bytes 00h
|
|
|
|
Linear Offset 04h
|
|
|
|
Reserved Segment/Selector 08h
|
|
|
|
# Used # Avail 0Ch
|
|
|
|
Page table entry 0 10h
|
|
|
|
Page table entry 1 14h
|
|
|
|
. . . . . .
|
|
|
|
. . . . . .
|
|
|
|
Page table entry n 10h+n*4
|
|
|
|
|
|
Each page table entry contains the physical page number
|
|
in the upper 20 bits; the lower 12 bits are flag
|
|
bits:
|
|
|
|
Bit 0 = 1 if the page is present and locked
|
|
Bits 1..11 are reserved and will be zero
|
|
|
|
If option bit 7 = 1, then pages in the region which do
|
|
not have a physical page assigned will have a
|
|
page table entry of 0, and will not be locked by
|
|
this call.
|
|
|
|
The caller must fill in the region size, linear segment
|
|
and offset, and number available field. The #
|
|
Avail field specifies the number of physical
|
|
regions/page table entries in the data structure.
|
|
|
|
Returns
|
|
|
|
If function was successful:
|
|
Carry flag is clear
|
|
The # used field will contain the number of table
|
|
entires filled in with physical regions
|
|
information.
|
|
If bit 6 of option flags was 1 (page table copy) then
|
|
low twelve bits of BX = Offset in first page to
|
|
start of region (high 4 bits will be zero).
|
|
|
|
If function was not successful:
|
|
Carry flag is set
|
|
Memory is not locked
|
|
Region size field of DDS contains the maximum length in
|
|
bytes that can be locked and described in the DDS
|
|
table.
|
|
Table entries are undefined.
|
|
AL = Error code
|
|
03h = Unable to lock pages
|
|
07h = Invalid memory region
|
|
09h = Number of physical regions/pages was greater
|
|
than table length (The # used field will
|
|
contain the number of table entries needed to
|
|
describe the DMA region.)
|
|
10h = Reserved flag bits set in DX
|
|
|
|
Programmer's Notes
|
|
|
|
o The maximum number of physical regions required
|
|
can be computed as:
|
|
|
|
(Linear Address AND 0FFFh) + Region Size + 0FFFh
|
|
1000h
|
|
|
|
============================================================
|
|
|
|
Scatter/Gather Unlock Region
|
|
|
|
|
|
This service is used to unlock a region that was locked by
|
|
the Scatter/Gather Lock Region service.
|
|
|
|
To Call
|
|
|
|
AH = 81h
|
|
AL = 06h
|
|
DX = Flags
|
|
Bit 6 = 1 if EDDS contains page table entries
|
|
Bit 7 = 1 if EDDS may contain not present pages,
|
|
not present pages are identified as a page
|
|
table entry of 0 (bit 7 is ignored, if bit 6
|
|
= 0)
|
|
All other bits reserved and must be zero
|
|
ES:DI = Pointer to the extended DDS that was used when
|
|
calling the Scatter/Gather Lock Region service.
|
|
|
|
Returns
|
|
|
|
If function was successful:
|
|
Carry flag is clear
|
|
Memory is unlocked
|
|
|
|
If function was not successful:
|
|
Carry flag is set
|
|
AL = Error code
|
|
08h = Memory was not locked
|
|
10h = Reserved flag bits set in DX
|
|
|
|
Programmer's Notes
|
|
|
|
o Only the region size, linear offset and
|
|
segment/selector fields are used. Therefore, the
|
|
physical address/size or page table entries do not
|
|
need to be maintained, unless bits 6 and 7 were
|
|
set in DX in the call to Scatter/Gather Lock
|
|
Region. If this special form of page table lock
|
|
was used, then the table is required so that the
|
|
correct pages can be unlocked.
|
|
|
|
============================================================
|
|
|
|
Request DMA Buffer
|
|
|
|
|
|
Buffered DMA requires a device driver to request a DMA
|
|
buffer, copy data into the buffer (if a memory read
|
|
operation is required), start the DMA transfer with
|
|
programmed I/O, copy data from the buffer (if a memory write
|
|
operation is required), and release the DMA buffer. The
|
|
data must be copied to/from the DMA buffer before release is
|
|
called and the physical address of the buffer must be
|
|
considered invalid as soon as release is called.
|
|
|
|
To Call
|
|
|
|
AH = 81h
|
|
AL = 07h
|
|
DX = Flags
|
|
Bit 1 = 1 if data should be copied into buffer
|
|
All other bits reserved and must be zero
|
|
ES:DI = Pointer to DMA Descriptor Structure
|
|
The caller must fill in the region size field. If
|
|
automatic copy is selected (bit 1 set) then the
|
|
caller must also fill in the linear region segment
|
|
and region offset fields.
|
|
|
|
Returns
|
|
|
|
If function was successful:
|
|
Carry flag clear
|
|
The physical address field of the DDS contains the
|
|
starting physical address of the buffer.
|
|
The region size field specifies the size of the buffer.
|
|
The buffer ID field contains the ID of the allocated
|
|
buffer
|
|
If automatic copy was selected then data was copied
|
|
into the buffer.
|
|
|
|
If function was not successful:
|
|
Carry flag set
|
|
AL = Error code
|
|
04h = No buffer available
|
|
05h = Region too large for buffer
|
|
06h = Buffer currently in use
|
|
07h = Invalid memory region
|
|
10h = Reserved flag bits set in DX
|
|
|
|
Programmer's Notes
|
|
|
|
o Under Windows/386 devices will often want to enter
|
|
a Windows/386 critical section to prevent running
|
|
other VMs while they are using a DMA buffer.
|
|
o If the buffer is in use you may want to spin in a
|
|
loop with interrupts enabled and repeatedly
|
|
attempt to allocate the buffer to allow another
|
|
device time to complete its DMA.
|
|
o Your device driver must either spin in a wait loop
|
|
until the DMA is complete and then release
|
|
ownership of the buffer or it must release
|
|
ownership of the buffer from a hardware interrupt.
|
|
Releasing ownership from hardware interrupts will
|
|
allow other devices to wait for the buffer to be
|
|
freed as described above.
|
|
|
|
|
|
============================================================
|
|
|
|
Release DMA Buffer
|
|
|
|
|
|
Releases a DMA buffer that was previously requested. The
|
|
physical address should be considered invalid following this
|
|
call.
|
|
|
|
To Call
|
|
|
|
AH = 81h
|
|
AL = 08h
|
|
DX = Flags
|
|
Bit 1 = 1 if data should be copied out of buffer
|
|
All other bits reserved and must be zero
|
|
ES:DI = Pointer to DMA Descriptor Structure
|
|
The caller must fill in the buffer ID field of the
|
|
DDS before calling this service.
|
|
|
|
Returns
|
|
|
|
If function was successful:
|
|
Carry flag clear
|
|
|
|
If function was not successful:
|
|
Carry flag set
|
|
AL = Error code
|
|
0Ah = Invalid buffer ID
|
|
10h = Reserved flag bits set in DX
|
|
|
|
Programmer's Notes
|
|
|
|
None
|
|
|
|
============================================================
|
|
|
|
Copy Into DMA Buffer
|
|
|
|
|
|
Copy data from the user's buffer into the DMA buffer to
|
|
prepare for a memory read DMA transfer.
|
|
|
|
To Call
|
|
|
|
AH = 81h
|
|
AL = 09h
|
|
DX = Flags
|
|
All bits reserved and must be zero
|
|
ES:DI = Pointer to DMA Descriptor Structure
|
|
The caller must fill in the buffer ID field, the
|
|
fword segment/selector:linear offset fields to
|
|
specify the source address for the copy, and the
|
|
region size.
|
|
BX:CX = Starting offset in DMA buffer to copy
|
|
|
|
The size field of the DDS determines the number of
|
|
bytes that will be copied
|
|
|
|
Returns
|
|
|
|
If function was successful:
|
|
Carry flag clear
|
|
|
|
If function was not successful:
|
|
Carry flag set
|
|
AL = Error code
|
|
0Ah = Invalid buffer ID
|
|
0Bh = Copy count+offset is greater than buffer
|
|
size
|
|
10h = Reserved flag bits set in DX
|
|
|
|
============================================================
|
|
|
|
Copy Out Of DMA Buffer
|
|
|
|
|
|
Copy data from the DMA buffer into the user's buffer after a
|
|
memory write DMA transfer.
|
|
|
|
To Call
|
|
|
|
AH = 81h
|
|
AL = 0Ah
|
|
DX = Flags
|
|
All bits reserved and must be zero
|
|
ES:DI = Pointer to DMA Descriptor Structure
|
|
The caller must fill in the buffer ID field, the
|
|
fword segment/selector:linear offset fields to
|
|
specify the destination address for the copy, and
|
|
the region size.
|
|
BX:CX = Starting offset in DMA buffer to copy
|
|
|
|
The size field of the DDS determines the number of
|
|
bytes that will be copied
|
|
|
|
Returns
|
|
|
|
If function was successful:
|
|
Carry flag clear
|
|
|
|
If function was not successful:
|
|
Carry flag set
|
|
AL = Error code
|
|
0Ah = Invalid buffer ID
|
|
0Bh = Copy count+offset is greater than buffer
|
|
size
|
|
10h = Reserved flag bits set in DX
|
|
|
|
============================================================
|
|
|
|
Disable DMA Translation
|
|
|
|
Environments that support the DMA services will trap the
|
|
standard DMA I/O ports and attempt to remap the client's
|
|
addresses, which are assumed to be linear addresses, to the
|
|
appropriate physical address. However, programs which use
|
|
the DMA services to determine the physical address of their
|
|
DMA region must disable the automatic remapping of standard
|
|
DMA by calling this function.
|
|
|
|
A disable count is maintained so you must call Enable DMA
|
|
Translation for every call to this service before automatic
|
|
DMA translation will be enabled.
|
|
|
|
To Call
|
|
|
|
AH = 81h
|
|
AL = 0Bh
|
|
BX = DMA channel number
|
|
DX = Flags
|
|
All bits reserved and must be zero
|
|
|
|
Returns
|
|
|
|
If function was successful:
|
|
Carry flag clear
|
|
|
|
If function was not successful:
|
|
Carry flag set
|
|
AL = Error code
|
|
0Ch = Invalid DMA channel number
|
|
0Dh = Disable count overflow
|
|
10h = Reserved flag bits set in DX
|
|
|
|
Programmer's Notes
|
|
|
|
None
|
|
|
|
============================================================
|
|
|
|
Enable DMA Translation
|
|
|
|
|
|
This service must be called after calling Disable DMA
|
|
Translation to re-enable automatic DMA remapping.
|
|
|
|
A disable count is maintained so you must call this service
|
|
for every call to Disable DMA Translation before automatic
|
|
DMA translation will be enabled.
|
|
|
|
To Call
|
|
|
|
AH = 81h
|
|
AL = 0Ch
|
|
BX = DMA channel number
|
|
DX = Flags
|
|
All bits reserved and must be zero
|
|
|
|
Returns
|
|
|
|
If function was successful:
|
|
Carry flag clear
|
|
If disable count decremented to 0, then Zero flag set
|
|
|
|
If function was not successful:
|
|
Carry flag set
|
|
AL = Error code
|
|
0Ch = Invalid DMA channel number
|
|
0Eh = Disable count underflow (was not previously
|
|
disabled). Count not changed.
|
|
10h = Reserved flag bits set in DX
|
|
|
|
Programmer's Notes
|
|
|
|
None
|
|
|
|
|
|
SUMMARY OF ERROR CODES AND OPTION FLAGS
|
|
|
|
|
|
|
|
Error codes:
|
|
|
|
01h = Region not in contiguous memory
|
|
02h = Region crossed a physical alignment boundary
|
|
03h = Unable to lock pages
|
|
04h = No buffer available
|
|
05h = Region too large for buffer
|
|
06h = Buffer currently in use
|
|
07h = Invalid memory region
|
|
08h = Region was not locked
|
|
09h = Number of physical pages was greater than table
|
|
length
|
|
0Ah = Invalid buffer ID
|
|
0Bh = Copy out of buffer range
|
|
0Ch = Invalid DMA channel number
|
|
0Dh = Disable count overflow
|
|
0Eh = Disable count underflow
|
|
0Fh = Function not supported
|
|
10h = Reserved flag bits set in DX
|
|
|
|
|
|
Flags:
|
|
|
|
Bit 1 = Automatically copy to/from buffer
|
|
Bit 2 = Disable automatic buffer allocation
|
|
Bit 3 = Disable automatic remap feature
|
|
Bit 4 = Region must not cross 64K physical alignment
|
|
boundary
|
|
Bit 5 = Region must not cross 128K physical alignment
|
|
boundary
|
|
Bit 6 = Copy page table for scatter gather remap
|