mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
528 lines
16 KiB
528 lines
16 KiB
/*
|
|
* SoftPC-AT Revision 2.0
|
|
*
|
|
* Title : IBM PC-AT DMA Adaptor declarations
|
|
*
|
|
* Description : This module contains declarations that are used in
|
|
* accessing the DMA Adaptor emulation
|
|
*
|
|
* Author(s) : Ross Beresford
|
|
*
|
|
* Notes : For a detailed description of the IBM DMA Adaptor,
|
|
* and the INTEL DMA Controller chips refer to the following
|
|
* documents:
|
|
*
|
|
* - IBM PC/AT Technical Reference Manual
|
|
* (Section 1-9 Direct Memory Access)
|
|
* - INTEL Microsystems Components Handbook
|
|
* (Section 2-52 DMA Controller 8237A)
|
|
*
|
|
* A more succinct account of the DMA adaptor follows:
|
|
*
|
|
|
|
* DMA Adaptor:
|
|
* -----------
|
|
*
|
|
* The DMA "adaptor" is really just a part of the AT System Board. This
|
|
* is its block diagram:
|
|
*
|
|
* +-----------+
|
|
* 000-01F |8237A-5 | 0| A0-A7
|
|
* IOS <-+------> | DMA | 1| -------------------------------------+
|
|
* | | CNTRL | 2| +-------+ |
|
|
* | | 0 | 3| ---> |ALS 573| A8-A15|
|
|
* | +-----------+ | DMA | ----------------------+
|
|
* | ^ |ADDRESS| |
|
|
* | \ | LATCH | +-------+ |
|
|
* | \ cascade +-------+ | LS612 | |
|
|
* |080-09F \ | | A16-A23|
|
|
* +----------------------------------------> | DMA | -------+
|
|
* | \ | PAGE | A17-A23|
|
|
* | +-----------+ | REG | |
|
|
* | |8237A-5 | 4| +-------+ |
|
|
* +------> | DMA | 5| -------------------------------------+
|
|
* 0C0-0DF | CNTRL | 6| +-------+ A9-A16|
|
|
* | 1 | 7| ---> |ALS 573| |
|
|
* +-----------+ | DMA | ----------------------+-> SAS
|
|
* |ADDRESS| A1-A8
|
|
* | LATCH |
|
|
* +-------+
|
|
|
|
* DMA Controllers:
|
|
* ---------------
|
|
*
|
|
* The 8237A-5 DMA controller chips used are restricted to 4 DMA
|
|
* channels each: thus, 2 DMA controller chips are required to give the
|
|
* AT's 7 DMA channels.
|
|
*
|
|
* The 8237A-5 DMA controller chips support more than one device by
|
|
* "cascading" them: that is, connecting the control inputs of the
|
|
* "additional" device to the control outputs of the "initial" device.
|
|
* One channel in the initial device must be dedicated to serving
|
|
* each additional device by setting it to "cascade mode".
|
|
*
|
|
* On the AT system board, channel 4 of DMA Controller 1 is set to
|
|
* "cascade mode", and serves DMA Controller 0.
|
|
*
|
|
* Channels 0-3 (on DMA Controller 0) are used to support 8-bit I/O
|
|
* devices and provide transfers of up to 64K bytes: the 16-bit addresses
|
|
* generated by the DMA Controller are mapped directly onto bits A0-A15
|
|
* of a 24 bit system address.
|
|
*
|
|
* Channels 5-7 (on DMA Controller 1) are used to support 16-bit I/O
|
|
* devices and provide transfers of up to 128K bytes: the 16-bit addresses
|
|
* generated by the DMA Controller are mapped onto bits A1-A16 of a
|
|
* 24 bit system address, and bit A0 is set to 0.
|
|
*
|
|
* The state of a controller is defined by a set of internal registers
|
|
* and a flip-flop: the internal registers are used in setting up and
|
|
* performing a DMA transfer; the First/Last Flip-Flop controls which
|
|
* byte of a 16 bit address is accessed from the I/O bus.
|
|
*
|
|
* The state information for a controller is represented by a DMA_CNTRL
|
|
* object.
|
|
|
|
* DMA Address Latches:
|
|
* -------------------
|
|
*
|
|
* Each DMA Controller has an ALS573 DMA Address Latch associated with
|
|
* it. These are required because of a restriction in the design of the
|
|
* DMA Controller: in order to reduce its pin count it does not directly
|
|
* output bits A8-A15 onto the address bus, but uses an external latch.
|
|
*
|
|
* Since the address latches do not have any separate functional
|
|
* identity, their state and behaviour is included in with the
|
|
* controllers.
|
|
|
|
* DMA Page Registers:
|
|
* ------------------
|
|
*
|
|
* An LS612 DMA Page Register chip is used to establish the constant top
|
|
* bits of the system address for a DMA transfer; each DMA channel has a
|
|
* byte register in the chip for this purpose.
|
|
*
|
|
* In DMA channels 0-3, bits A16-A23 of the 24 bit system address are
|
|
* established from bits D0-D7 of the page register for the channel.
|
|
*
|
|
* In DMA channels 5-7, bits A17-A23 of the 24 bit system address are
|
|
* established from bits D1-D7 of the page register for the channel:
|
|
* Bit D0 is not used for these channels, since bit A16 of the system
|
|
* address is established by the DMA controller for these channels.
|
|
*
|
|
* The state information for the page register chip is represented
|
|
* by a DMA_PAGE object.
|
|
*/
|
|
|
|
/* SccsID[]="@(#)dma.h 1.7 11/10/92 Copyright Insignia Solutions Ltd."; */
|
|
|
|
/*
|
|
* ============================================================================
|
|
* Structure/Data definitions
|
|
* ============================================================================
|
|
*/
|
|
|
|
/*
|
|
* DMA CONTROLLER
|
|
*/
|
|
|
|
/* the number of channels per controller */
|
|
#define DMA_CONTROLLER_CHANNELS 4
|
|
|
|
/* a flip-flop; it toggles between the values 0 and 1 */
|
|
typedef unsigned int DMA_FLIP_FLOP;
|
|
|
|
/* a DMA address; it is indexed by the flip-flop value */
|
|
typedef half_word DMA_WORD[2];
|
|
|
|
/* a DMA command */
|
|
#ifdef BIT_ORDER1
|
|
typedef union
|
|
{
|
|
half_word all;
|
|
struct
|
|
{
|
|
HALF_WORD_BIT_FIELD DACK_high:1; /* not supported */
|
|
HALF_WORD_BIT_FIELD DREQ_high:1; /* not supported */
|
|
HALF_WORD_BIT_FIELD extended_write:1; /* not supported */
|
|
HALF_WORD_BIT_FIELD rotate_priority:1;
|
|
HALF_WORD_BIT_FIELD compressed_timing:1;/* not supported */
|
|
HALF_WORD_BIT_FIELD controller_disable:1;
|
|
HALF_WORD_BIT_FIELD ch0_address_hold:1;/* not supported */
|
|
HALF_WORD_BIT_FIELD mm_enable:1; /* not supported */
|
|
} bits;
|
|
} DMA_COMMAND;
|
|
#endif
|
|
#ifdef BIT_ORDER2
|
|
typedef union
|
|
{
|
|
half_word all;
|
|
struct
|
|
{
|
|
HALF_WORD_BIT_FIELD mm_enable:1; /* not supported */
|
|
HALF_WORD_BIT_FIELD ch0_address_hold:1;/* not supported */
|
|
HALF_WORD_BIT_FIELD controller_disable:1;
|
|
HALF_WORD_BIT_FIELD compressed_timing:1; /* not supported */
|
|
HALF_WORD_BIT_FIELD rotate_priority:1;
|
|
HALF_WORD_BIT_FIELD extended_write:1; /* not supported */
|
|
HALF_WORD_BIT_FIELD DREQ_high:1; /* not supported */
|
|
HALF_WORD_BIT_FIELD DACK_high:1; /* not supported */
|
|
} bits;
|
|
} DMA_COMMAND;
|
|
#endif
|
|
|
|
/* a DMA mode */
|
|
#ifdef BIT_ORDER1
|
|
typedef union
|
|
{
|
|
half_word all;
|
|
struct
|
|
{
|
|
HALF_WORD_BIT_FIELD mode:2; /* single/block/demand/cascade */
|
|
HALF_WORD_BIT_FIELD address_dec:1; /* inc or dec count */
|
|
HALF_WORD_BIT_FIELD auto_init:1; /* autoinitialize ? */
|
|
HALF_WORD_BIT_FIELD transfer_type:2; /* read/write/verify */
|
|
HALF_WORD_BIT_FIELD scratch:2; /* channel select mapped here */
|
|
} bits;
|
|
} DMA_MODE;
|
|
#endif
|
|
#ifdef BIT_ORDER2
|
|
typedef union
|
|
{
|
|
half_word all;
|
|
struct
|
|
{
|
|
HALF_WORD_BIT_FIELD scratch:2; /* channel select mapped here */
|
|
HALF_WORD_BIT_FIELD transfer_type:2; /* read/write/verify */
|
|
HALF_WORD_BIT_FIELD auto_init:1; /* autoinitialize ? */
|
|
HALF_WORD_BIT_FIELD address_dec:1; /* inc or dec count */
|
|
HALF_WORD_BIT_FIELD mode:2; /* single/block/demand/cascade */
|
|
} bits;
|
|
} DMA_MODE;
|
|
#endif
|
|
|
|
/* DMA Mode register mode bit settings */
|
|
#define DMA_DEMAND_MODE 0
|
|
#define DMA_SINGLE_MODE 1
|
|
#define DMA_BLOCK_MODE 2
|
|
#define DMA_CASCADE_MODE 3
|
|
|
|
/* DMA Mode register transfer type bit settings */
|
|
#define DMA_VERIFY_TRANSFER 0
|
|
#define DMA_WRITE_TRANSFER 1
|
|
#define DMA_READ_TRANSFER 2
|
|
#define DMA_ILLEGAL_TRANSFER 3
|
|
|
|
/* a DMA status */
|
|
#ifdef BIT_ORDER1
|
|
typedef union
|
|
{
|
|
half_word all;
|
|
struct
|
|
{
|
|
HALF_WORD_BIT_FIELD request:4; /* request pending */
|
|
HALF_WORD_BIT_FIELD terminal_count:4; /* terminal count reached */
|
|
} bits;
|
|
} DMA_STATUS;
|
|
#endif
|
|
#ifdef BIT_ORDER2
|
|
typedef union
|
|
{
|
|
half_word all;
|
|
struct {
|
|
HALF_WORD_BIT_FIELD terminal_count:4; /* terminal count reached */
|
|
HALF_WORD_BIT_FIELD request:4; /* request pending */
|
|
} bits;
|
|
} DMA_STATUS;
|
|
#endif
|
|
|
|
/* a DMA mask register (only the bottom 4 bits are meaningful) */
|
|
typedef half_word DMA_MASK;
|
|
|
|
/* a DMA Controller state */
|
|
typedef struct
|
|
{
|
|
DMA_WORD base_address[DMA_CONTROLLER_CHANNELS];
|
|
DMA_WORD base_count[DMA_CONTROLLER_CHANNELS];
|
|
DMA_WORD current_address[DMA_CONTROLLER_CHANNELS];
|
|
DMA_WORD current_count[DMA_CONTROLLER_CHANNELS];
|
|
DMA_WORD temporary_address[DMA_CONTROLLER_CHANNELS];
|
|
DMA_WORD temporary_count[DMA_CONTROLLER_CHANNELS];
|
|
DMA_STATUS status;
|
|
DMA_COMMAND command;
|
|
half_word temporary;
|
|
DMA_MODE mode[DMA_CONTROLLER_CHANNELS];
|
|
DMA_MASK mask;
|
|
half_word request;
|
|
DMA_FLIP_FLOP first_last;
|
|
} DMA_CNTRL;
|
|
|
|
/*
|
|
* DMA PAGE REGISTERS
|
|
*/
|
|
|
|
/* the number of channels per page register chip */
|
|
#define DMA_PAGE_CHANNELS 16
|
|
|
|
/* a DMA Page Register chip state */
|
|
typedef struct
|
|
{
|
|
half_word page[DMA_PAGE_CHANNELS];
|
|
} DMA_PAGE;
|
|
|
|
/*
|
|
* DMA ADAPTOR
|
|
*/
|
|
|
|
/* the number of controllers per adaptor */
|
|
#define DMA_ADAPTOR_CONTROLLERS 2
|
|
|
|
/* the numbering convention for the controllers */
|
|
#define DMA_CONTROLLER 0
|
|
#define DMA1_CONTROLLER 1
|
|
|
|
/* a DMA adaptor state */
|
|
typedef struct
|
|
{
|
|
DMA_CNTRL controller[DMA_ADAPTOR_CONTROLLERS];
|
|
DMA_PAGE pages;
|
|
} DMA_ADAPT;
|
|
|
|
/* the number of logical channels per adaptor */
|
|
#define DMA_ADAPTOR_CHANNELS \
|
|
(DMA_ADAPTOR_CONTROLLERS * DMA_CONTROLLER_CHANNELS)
|
|
|
|
/* macros for converting between logical and physical channel numbers */
|
|
#define dma_logical_channel(controller, channel) \
|
|
(controller*DMA_CONTROLLER_CHANNELS + channel)
|
|
#define dma_physical_channel(channel) \
|
|
(channel%DMA_CONTROLLER_CHANNELS)
|
|
#define dma_physical_controller(channel) \
|
|
(channel/DMA_CONTROLLER_CHANNELS)
|
|
|
|
/* macro for building a system address dependent on the channel */
|
|
#define dma_system_address(channel, page, offset) \
|
|
( (channel < 4) \
|
|
? (((sys_addr)(page & 0xff) << 16) | ((sys_addr)(offset & 0xffff) << 0)) \
|
|
: (((sys_addr)(page & 0xfe) << 16) | ((sys_addr)(offset & 0xffff) << 1)) )
|
|
|
|
/* macro for determining the DMA unit size dependent on the channel */
|
|
#define dma_unit_size(channel) ( (channel < 4) ? 1 : 2)
|
|
|
|
/* the channel assignments */
|
|
#define DMA_RESERVED_CHANNEL_0 0
|
|
#define DMA_SDLC_CHANNEL 1
|
|
#define DMA_DISKETTE_CHANNEL 2
|
|
#define DMA_DISK_CHANNEL 3
|
|
#define DMA_CASCADE_CHANNEL 4
|
|
#define DMA_RESERVED_CHANNEL_5 5
|
|
#define DMA_RESERVED_CHANNEL_6 6
|
|
#define DMA_RESERVED_CHANNEL_7 7
|
|
#define DMA_FAKE_CHANNEL_1 8
|
|
#define DMA_FAKE_CHANNEL_2 9
|
|
#define DMA_FAKE_CHANNEL_3 10
|
|
#define DMA_FAKE_CHANNEL_4 11
|
|
#define DMA_FAKE_CHANNEL_5 12
|
|
#define DMA_FAKE_CHANNEL_6 13
|
|
#define DMA_FAKE_CHANNEL_7 14
|
|
#define DMA_REFRESH_CHANNEL 15
|
|
|
|
/* these masks define the redundant bits of the I/O addresses */
|
|
#define DMA_REDUNDANT_BITS 0x10
|
|
#define DMA1_REDUNDANT_BITS 0x01
|
|
#define DMA_PAGE_REDUNDANT_BITS 0x10
|
|
|
|
/*
|
|
* DMA Address - the following union is used only in the BIOS functions
|
|
* to help determine how a system address should be expressed in terms
|
|
* of its component parts.
|
|
* It is not used within the DMA emulation
|
|
*/
|
|
#ifdef BIGEND
|
|
typedef union
|
|
{
|
|
sys_addr all;
|
|
half_word array[4];
|
|
struct
|
|
{
|
|
half_word pad;
|
|
half_word page;
|
|
half_word high;
|
|
half_word low;
|
|
} parts;
|
|
struct
|
|
{
|
|
word high;
|
|
word low;
|
|
} words;
|
|
} DMA_ADDRESS;
|
|
#endif
|
|
#ifdef LITTLEND
|
|
typedef union
|
|
{
|
|
sys_addr all;
|
|
half_word array[4];
|
|
struct
|
|
{
|
|
half_word low;
|
|
half_word high;
|
|
half_word page;
|
|
half_word pad;
|
|
} parts;
|
|
struct
|
|
{
|
|
word low;
|
|
word high;
|
|
} words;
|
|
} DMA_ADDRESS;
|
|
#endif
|
|
|
|
/*
|
|
* ============================================================================
|
|
* External declarations and macros
|
|
* ============================================================================
|
|
*/
|
|
|
|
/*
|
|
* void dma_init()
|
|
* {
|
|
* This function performs several distinct initialisation
|
|
* tasks associated with the DMA adaptor:
|
|
*
|
|
* the DMA Controller chips and the DMA Page Register chip
|
|
* are connected to the I/O bus;
|
|
*
|
|
* a hardware reset is performed for each DMA Controller
|
|
* chip;
|
|
* }
|
|
*/
|
|
IMPORT VOID dma_init IPT0();
|
|
|
|
/*
|
|
* void dma_post()
|
|
* {
|
|
* the mode register for each DMA channel is set up to the
|
|
* normal value for an AT.
|
|
* }
|
|
*/
|
|
IMPORT VOID dma_post IPT0();
|
|
|
|
/*
|
|
* void dma_inb(port, value)
|
|
* io_addr port;
|
|
* half_word *value;
|
|
* {
|
|
* This function is invoked when a read is performed on an
|
|
* I/O address "port" in the range of one of the DMA
|
|
* Controller chips. dma_inb() may also be called directly
|
|
* from the BIOS.
|
|
*
|
|
* The function maps the I/O address to the particular DMA
|
|
* controller and returns the value of the requested
|
|
* register in "*value".
|
|
* }
|
|
*/
|
|
IMPORT VOID dma_inb IPT2(io_addr, port, half_word *, value);
|
|
|
|
/*
|
|
* void dma_outb(port, value)
|
|
* io_addr port;
|
|
* half_word value;
|
|
* {
|
|
* This function is invoked when a write is performed to an
|
|
* I/O address "port" in the range of one of the DMA
|
|
* Controller chips. dma_outb() may also be called directly
|
|
* from the BIOS.
|
|
*
|
|
* The function maps the I/O address to the particular DMA
|
|
* controller and sets the requested register to "value".
|
|
* }
|
|
*/
|
|
IMPORT VOID dma_outb IPT2(io_addr, port, half_word, value);
|
|
|
|
/*
|
|
* void dma_page_inb(port, value)
|
|
* io_addr port;
|
|
* half_word *value;
|
|
* {
|
|
* This function is invoked when a read is performed on an
|
|
* I/O address "port" in the range of the DMA Page Register
|
|
* chip. dma_page_inb() may also be called directly from the
|
|
* BIOS.
|
|
*
|
|
* The function maps the I/O address to a particular DMA
|
|
* page register and returns its value in "*value".
|
|
* }
|
|
*/
|
|
IMPORT VOID dma_page_inb IPT2(io_addr, port, half_word *, value);
|
|
|
|
/*
|
|
* void dma_page_outb(port, value)
|
|
* io_addr port;
|
|
* half_word value;
|
|
* {
|
|
* This function is invoked when a write is performed to an
|
|
* I/O address "port" in the range of the DMA Page Register
|
|
* chip. dma_page_outb() may also be called directly from the
|
|
* BIOS.
|
|
*
|
|
* The function maps the I/O address to a particular DMA
|
|
* page register and sets it to "value".
|
|
* }
|
|
*/
|
|
IMPORT VOID dma_page_outb IPT2(io_addr, port, half_word, value);
|
|
|
|
/*
|
|
* dma_request(channel, hw_buffer, length)
|
|
* half_word channel;
|
|
* char *hw_buffer;
|
|
* word length;
|
|
* {
|
|
* I/O devices call this function to initiate a DMA
|
|
* transfer. It is analogous to raising the DREQ line
|
|
* on the DMA controller for the channel.
|
|
*
|
|
* The DMA channel to be used is passed in "channel";
|
|
* "hw_buffer" is the address in the device's memory
|
|
* space of the buffer that should be read from or written
|
|
* into the system address space; "length" is the maximum
|
|
* number of units to be transferred: the unit is a
|
|
* half_word for channels 0-3 and a word for channels 5-7.
|
|
*
|
|
* The function returns TRUE if more transfers can be
|
|
* accepted or FALSE if the terminal count has been
|
|
* reached.
|
|
* }
|
|
*/
|
|
IMPORT int dma_request IPT3(half_word, port, char *, hw_buffer, word, length);
|
|
|
|
/*
|
|
* void dma_enquire(channel, address, length)
|
|
* half_word channel;
|
|
* sys_addr *address;
|
|
* word *length;
|
|
* {
|
|
* I/O devices call this function to find out how the
|
|
* DMA controller has been programmed up to do a transfer.
|
|
*
|
|
* The DMA channel to be accessed is passed in "channel";
|
|
* the address in system address space that will be read
|
|
* or written in the transfer is returned in "*address";
|
|
* "length" is the number of units that have been
|
|
* requested: the unit is a half_word for channels 0-3
|
|
* and a word for channels 5-7.
|
|
* }
|
|
*/
|
|
IMPORT VOID dma_enquire IPT3(half_word, channel, sys_addr *, address, word *, length);
|
|
|
|
#ifdef NTVDM
|
|
/*
|
|
* BOOL dmaGetAdaptor
|
|
*
|
|
* Used by MS for third party Vdds to retrieve current DMA settings
|
|
*
|
|
* entry: void
|
|
* exit : DMA_ADAPT * , pointer to the DMA_ADAPT structure
|
|
*
|
|
*/
|
|
DMA_ADAPT *dmaGetAdaptor();
|
|
#endif /* NTVDM */
|