Windows NT 4.0 source code leak
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

/*
* 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 */