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.
 
 
 
 
 
 

1021 lines
29 KiB

#include "insignia.h"
#include "host_def.h"
/*[
* Name: ios.c
*
* Author: Wayne Plummer
*
* Created: 7th February 1991
*
* Sccs ID: @(#)ios.c 1.29 09/27/94
*
* Purpose: This module provides a routing mechanism for Input and Ouput
* requests.
*
* (c)Copyright Insignia Solutions Ltd., 1991. All rights reserved.
]*/
#ifdef SEGMENTATION
/*
* The following #include specifies the code segment into which this
* module will by placed by the MPW C compiler on the Mac II running
* MultiFinder.
*/
#include "SOFTPC_IOS.seg"
#endif
#include <stdio.h>
#include <stdlib.h>
/*
* SoftPC include files
*/
#include "xt.h"
#include CpuH
#include "ios.h"
#include "trace.h"
#include "debug.h"
#include "sas.h"
#include MemoryH
#if defined(SPC386) && !defined(GISP_CPU)
#define VIRTUALISATION
#endif
#ifdef NTVDM
#define getIOInAdapter(ioaddr) (Ios_in_adapter_table[ioaddr & (PC_IO_MEM_SIZE-1)])
#define getIOOutAdapter(ioaddr) (Ios_out_adapter_table[ioaddr & (PC_IO_MEM_SIZE-1)])
#endif
/*
*
* ============================================================================
* Global data
* ============================================================================
*
*/
/*
* Ios_in_adapter_table & Ios_out_adapter_table - These tables give the association
* between the IO address used for an IO and the SoftPC adapter ID associated with the
* IO subroutines.
*
* Note that there are two tables here to allow for memory mapped IO locations which
* have an input functionality which is unrelated to the output functionality...
* In these cases, two connect port calls to the same IO address would be made, one with
* only the IO_READ flag set, the other with only the IO_WRITE flag set.
*/
#ifdef MAC68K
GLOBAL char *Ios_in_adapter_table = NULL;
GLOBAL char *Ios_out_adapter_table = NULL;
#else
GLOBAL char Ios_in_adapter_table[PC_IO_MEM_SIZE];
GLOBAL char Ios_out_adapter_table[PC_IO_MEM_SIZE];
#endif /* MAC68K */
#ifndef PROD
GLOBAL IU32 *ios_empty_in = (IU32 *)0;
GLOBAL IU32 *ios_empty_out = (IU32 *)0;
#endif /* PROD */
/*
* Ios_xxx_function - These tables are indexed by the adapter ID obtained
* from the Ios_in_adapter_table or Ios_in_adapter_table to yield a pointer
* to the IO routine to call.
*/
typedef void (*IOS_FUNC_INB) IPT2(io_addr, io_address, half_word *, value);
typedef void (*IOS_FUNC_INW) IPT2(io_addr, io_address, word *, value);
typedef void (*IOS_FUNC_INSB) IPT3(io_addr, io_address, half_word *, valarray, word, count);
typedef void (*IOS_FUNC_INSW) IPT3(io_addr, io_address, word *, valarray, word, count);
typedef void (*IOS_FUNC_OUTB) IPT2(io_addr, io_address, half_word, value);
typedef void (*IOS_FUNC_OUTW) IPT2(io_addr, io_address, word, value);
typedef void (*IOS_FUNC_OUTSB) IPT3(io_addr, io_address, half_word *, valarray, word, count);
typedef void (*IOS_FUNC_OUTSW) IPT3(io_addr, io_address, word *, valarray, word, count);
#ifdef SPC386
typedef void (*IOS_FUNC_IND) IPT2(io_addr, io_address, double_word *, value);
typedef void (*IOS_FUNC_INSD) IPT3(io_addr, io_address, double_word *, valarray, word, count);
typedef void (*IOS_FUNC_OUTD) IPT2(io_addr, io_address, double_word, value);
typedef void (*IOS_FUNC_OUTSD) IPT3(io_addr, io_address, double_word *, valarray, word, count);
#endif
LOCAL void generic_inw IPT2(io_addr, io_address, word *, value);
LOCAL void generic_insb IPT3(io_addr, io_address, half_word *, valarray, word, count);
LOCAL void generic_insw IPT3(io_addr, io_address, word *, valarray, word, count);
LOCAL void generic_outw IPT2(io_addr, io_address, word, value);
LOCAL void generic_outsb IPT3(io_addr, io_address, half_word *, valarray, word, count);
LOCAL void generic_outsw IPT3(io_addr, io_address, word *, valarray, word, count);
#ifdef SPC386
LOCAL void generic_ind IPT2(io_addr, io_address, double_word *, value);
LOCAL void generic_insd IPT3(io_addr, io_address, double_word *, valarray, word, count);
LOCAL void generic_outd IPT2(io_addr, io_address, double_word, value);
LOCAL void generic_outsd IPT3(io_addr, io_address, double_word *, valarray, word, count);
#endif
GLOBAL IOS_FUNC_INB Ios_inb_function [IO_MAX_NUMBER_ADAPTORS];
GLOBAL IOS_FUNC_INW Ios_inw_function [IO_MAX_NUMBER_ADAPTORS];
GLOBAL IOS_FUNC_INSB Ios_insb_function [IO_MAX_NUMBER_ADAPTORS];
GLOBAL IOS_FUNC_INSW Ios_insw_function [IO_MAX_NUMBER_ADAPTORS];
GLOBAL IOS_FUNC_OUTB Ios_outb_function [IO_MAX_NUMBER_ADAPTORS];
GLOBAL IOS_FUNC_OUTW Ios_outw_function [IO_MAX_NUMBER_ADAPTORS];
GLOBAL IOS_FUNC_OUTSB Ios_outsb_function[IO_MAX_NUMBER_ADAPTORS];
GLOBAL IOS_FUNC_OUTSW Ios_outsw_function[IO_MAX_NUMBER_ADAPTORS];
#ifdef SPC386
GLOBAL IOS_FUNC_IND Ios_ind_function [IO_MAX_NUMBER_ADAPTORS];
GLOBAL IOS_FUNC_INSD Ios_insd_function [IO_MAX_NUMBER_ADAPTORS];
GLOBAL IOS_FUNC_OUTD Ios_outd_function [IO_MAX_NUMBER_ADAPTORS];
GLOBAL IOS_FUNC_OUTSD Ios_outsd_function[IO_MAX_NUMBER_ADAPTORS];
#endif
/*
*
* ============================================================================
* Local Subroutines
* ============================================================================
*
*/
#define BIT_NOT_SET(vector, bit) \
((vector == (IU32 *)0) ? FALSE: ((((vector[(bit) >> 5]) >> ((bit) & 0x1f)) & 1) == 0))
#define SET_THE_BIT(vector, bit) \
{ \
if (vector != (IU32 *)0) \
{ \
vector[(bit) >> 5] |= (1 << ((bit) & 0x1f)); \
} \
}
/*
============================== io_empty_inb ==================================
PURPOSE:
To simulate an INB to an empty io_addr.
INPUT:
OUTPUT:
==============================================================================
*/
LOCAL void io_empty_inb IFN2(io_addr, io_address, half_word *, value)
{
#ifdef PROD
UNUSED(io_address);
#else
if (BIT_NOT_SET(ios_empty_in, (IU16)io_address))
{
/* First time for this port */
always_trace1 ("INB attempted on empty port 0x%x", io_address);
SET_THE_BIT(ios_empty_in, (IU16)io_address);
}
#endif /* PROD */
*value = IO_EMPTY_PORT_BYTE_VALUE;
}
/*
============================== io_empty_outb ==================================
PURPOSE:
To simulate an OUTB to an empty io_addr.
INPUT:
OUTPUT:
==============================================================================
*/
LOCAL void io_empty_outb IFN2(io_addr, io_address, half_word, value)
{
UNUSED(value);
#ifdef PROD
UNUSED(io_address);
#else
if (BIT_NOT_SET(ios_empty_out, (IU16)io_address))
{
/* First time for this port */
always_trace1 ("OUTB attempted on empty port 0x%x", io_address);
SET_THE_BIT(ios_empty_out, (IU16)io_address);
}
#endif /* PROD */
/* Do nothing! */
}
/*
=============================== generic_inw ==================================
PURPOSE:
To simulate an INW using the appropriate INB routine.
INPUT:
OUTPUT:
==============================================================================
*/
LOCAL void generic_inw IFN2(io_addr, io_address, word *, value)
{
reg temp;
(*Ios_inb_function[Ios_in_adapter_table[io_address & (PC_IO_MEM_SIZE-1)]])
(io_address, &temp.byte.low);
io_address++;
(*Ios_inb_function[Ios_in_adapter_table[io_address & (PC_IO_MEM_SIZE-1)]])
(io_address, &temp.byte.high);
#ifdef LITTLEND
*((half_word *) value + 0) = temp.byte.low;
*((half_word *) value + 1) = temp.byte.high;
#endif /* LITTLEND */
#ifdef BIGEND
*((half_word *) value + 0) = temp.byte.high;
*((half_word *) value + 1) = temp.byte.low;
#endif /* BIGEND */
}
/*
=============================== generic_outw ==================================
PURPOSE:
To simulate an OUTW using the appropriate OUTB routine.
INPUT:
OUTPUT:
Notes: GLOBAL for JOKER.
==============================================================================
*/
LOCAL void generic_outw IFN2(io_addr, io_address, word, value)
{
reg temp;
temp.X = value;
(*Ios_outb_function[Ios_out_adapter_table[io_address & (PC_IO_MEM_SIZE-1)]])
(io_address, temp.byte.low);
++io_address;
(*Ios_outb_function[Ios_out_adapter_table[io_address & (PC_IO_MEM_SIZE-1)]])
(io_address, temp.byte.high);
}
#ifdef SPC386
/*
=============================== generic_ind ==================================
PURPOSE:
To simulate an IND using the appropriate INW routine.
INPUT:
OUTPUT:
==============================================================================
*/
LOCAL void generic_ind IFN2(io_addr, io_address, double_word *, value)
{
word low, high;
(*Ios_inw_function[Ios_in_adapter_table[io_address & (PC_IO_MEM_SIZE-1)]]) (io_address, &low);
io_address += 2;
(*Ios_inw_function[Ios_in_adapter_table[io_address & (PC_IO_MEM_SIZE-1)]]) (io_address, &high);
#ifdef LITTLEND
*((word *) value + 0) = low;
*((word *) value + 1) = high;
#endif /* LITTLEND */
#ifdef BIGEND
*((word *) value + 0) = high;
*((word *) value + 1) = low;
#endif /* BIGEND */
}
#endif /* SPC386 */
#ifdef SPC386
/*
=============================== generic_outd ==================================
PURPOSE:
To simulate an OUTD using the appropriate OUTW routine.
INPUT:
OUTPUT:
Notes: GLOBAL for JOKER.
==============================================================================
*/
LOCAL void generic_outd IFN2(io_addr, io_address, double_word, value)
{
word low, high;
low = value & 0xffff;
high = (value & 0xffff0000) >> 16;
(*Ios_outw_function[Ios_out_adapter_table[io_address & (PC_IO_MEM_SIZE-1)]]) (io_address, low);
io_address += 2;
(*Ios_outw_function[Ios_out_adapter_table[io_address & (PC_IO_MEM_SIZE-1)]]) (io_address, high);
}
#endif /* SPC386 */
/*
=============================== generic_insb ==================================
PURPOSE:
To simulate an INSB using the appropriate INB routine.
INPUT:
OUTPUT:
==============================================================================
*/
/* MS NT monitor uses these string routines {in,out}s{b,w} string io support */
#if defined(NTVDM) && defined(MONITOR)
#undef LOCAL
#define LOCAL
#endif /* NTVDM & MONITOR */
LOCAL void generic_insb IFN3(io_addr, io_address, half_word *, valarray,
word, count)
{
IOS_FUNC_INB func = Ios_inb_function[Ios_in_adapter_table[io_address & (PC_IO_MEM_SIZE-1)]];
while (count--){
(*func) (io_address, valarray++);
}
}
/*
=============================== generic_outsb =================================
PURPOSE:
To simulate an OUTSB using the appropriate OUTB routine.
INPUT:
OUTPUT:
==============================================================================
*/
LOCAL void generic_outsb IFN3(io_addr, io_address, half_word *, valarray, word, count)
{
IOS_FUNC_OUTB func = Ios_outb_function[Ios_out_adapter_table[io_address & (PC_IO_MEM_SIZE-1)]];
while (count--){
(*func) (io_address, *valarray++);
}
}
/*
=============================== generic_insw ==================================
PURPOSE:
To simulate an INSW using the appropriate INW routine.
INPUT:
OUTPUT:
==============================================================================
*/
LOCAL void generic_insw IFN3(io_addr, io_address, word *, valarray, word, count)
{
IOS_FUNC_INW func = Ios_inw_function[Ios_in_adapter_table[io_address & (PC_IO_MEM_SIZE-1)]];
while (count--){
(*func) (io_address, valarray++);
}
}
/*
=============================== generic_outsw =================================
PURPOSE:
To simulate an OUTSW using the appropriate OUTW routine.
INPUT:
OUTPUT:
==============================================================================
*/
LOCAL void generic_outsw IFN3(io_addr, io_address, word *, valarray, word, count)
{
IOS_FUNC_OUTW func = Ios_outw_function[Ios_out_adapter_table[io_address & (PC_IO_MEM_SIZE-1)]];
while (count--){
(*func) (io_address, *valarray++);
}
}
#ifdef SPC386
/*
=============================== generic_insd ==================================
PURPOSE:
To simulate an INSD using the appropriate IND routine.
INPUT:
OUTPUT:
==============================================================================
*/
LOCAL VOID generic_insd IFN3(io_addr, io_address, double_word *, valarray, word, count)
{
IOS_FUNC_IND func = Ios_ind_function[Ios_in_adapter_table[io_address & (PC_IO_MEM_SIZE-1)]];
while (count--){
(*func) (io_address, valarray++);
}
}
#endif
#ifdef SPC386
/*
=============================== generic_outsd =================================
PURPOSE:
To simulate an OUTSD using the appropriate OUTD routine.
INPUT:
OUTPUT:
==============================================================================
*/
LOCAL VOID generic_outsd IFN3(io_addr, io_address, double_word *, valarray, word, count)
{
IOS_FUNC_OUTD func = Ios_outd_function[Ios_out_adapter_table[io_address & (PC_IO_MEM_SIZE-1)]];
while (count--){
(*func) (io_address, *valarray++);
}
}
#endif
/* ensure any more LOCAL routines remain LOCAL */
#if defined(NTVDM) && defined(MONITOR)
#undef LOCAL
#define LOCAL static
/*
* string byte handlers for monitor
*/
VOID insb IFN3(io_addr, io_address, half_word *, valarray, word, count)
{
(*Ios_insb_function[getIOInAdapter(io_address)])
(io_address, valarray, count);
}
VOID outsb IFN3(io_addr, io_address, half_word *, valarray,word, count)
{
(*Ios_outsb_function[getIOInAdapter(io_address)])
(io_address, valarray, count);
}
VOID insw IFN3(io_addr, io_address, word *, valarray, word, count)
{
(*Ios_insw_function[getIOInAdapter(io_address)])
(io_address, valarray, count);
}
VOID outsw IFN3(io_addr, io_address, word *, valarray, word, count)
{
(*Ios_outsw_function[getIOInAdapter(io_address)])
(io_address, valarray, count);
}
#endif /* NTVDM & MONITOR */
/*
*
* ============================================================================
* Global Subroutines
* ============================================================================
*
*/
/*(
=================================== inb ======================================
PURPOSE:
To perform an INB - i.e. call the appropriate SoftPC adapter's INB
IO routine. Note that this routine is not intended to be used by
the assembler CPU directly - it is intended that the assembler CPU
access the data tables above directly to discover which routine to call.
This also needs to be true of 386 CPU, or you'll get into a very
nasty virtualisation loop.
INPUT:
OUTPUT:
==============================================================================
)*/
GLOBAL void inb IFN2(io_addr, io_address, half_word *, value)
{
#ifdef VIRTUALISATION
IU32 value32;
#endif /* VIRTUALISATION */
#ifdef EGA_DUMP
if (io_address >= MDA_PORT_START && io_address <= CGA_PORT_END)
dump_inb(io_address);
#endif
#ifdef VIRTUALISATION
#ifdef SYNCH_TIMERS
value32 = 0;
#endif /* SYNCH_TIMERS */
if (IOVirtualised(io_address, &value32, BIOS_INB_OFFSET, (sizeof(IU8))))
{
*value = (IU8)value32;
}
else
#endif /* VIRTUALISATION */
{
(*Ios_inb_function
[Ios_in_adapter_table[io_address & (PC_IO_MEM_SIZE-1)]])
(io_address, value);
}
}
/*(
================================== outb ======================================
PURPOSE:
To perform an OUTB - i.e. call the appropriate SoftPC adapter's OUTB
IO routine. Note that this routine is not intended to be used by
the assembler CPU directly - it is intended that the assembler CPU
access the data tables above directly to discover which routine to call.
INPUT:
OUTPUT:
==============================================================================
)*/
GLOBAL void outb IFN2(io_addr, io_address, half_word, value)
{
#ifdef VIRTUALISATION
IU32 value32;
#endif /* VIRTUALISATION */
#ifdef EGA_DUMP
if (io_address >= MDA_PORT_START && io_address <= CGA_PORT_END)
dump_outb(io_address, value);
#endif
sub_note_trace2( IOS_VERBOSE, "outb( %x, %x )", io_address, value );
#ifdef VIRTUALISATION
value32 = value;
if (IOVirtualised(io_address, &value32, BIOS_OUTB_OFFSET, (sizeof(IU8))))
return;
else
#endif /* VIRTUALISATION */
{
(*Ios_outb_function[Ios_out_adapter_table[io_address & (PC_IO_MEM_SIZE-1)]])
(io_address, value);
}
}
/*(
=================================== inw ======================================
PURPOSE:
To perform an INW - i.e. call the appropriate SoftPC adapter's INW
IO routine. Note that this routine is not intended to be used by
the assembler CPU directly - it is intended that the assembler CPU
access the data tables above directly to discover which routine to call.
INPUT:
OUTPUT:
==============================================================================
)*/
GLOBAL void inw IFN2(io_addr, io_address, word *, value)
{
#ifdef VIRTUALISATION
IU32 value32;
#endif /* VIRTUALISATION */
#ifdef EGA_DUMP
if (io_address >= MDA_PORT_START && io_address <= CGA_PORT_END)
dump_inw(io_address);
#endif
#ifdef VIRTUALISATION
#ifdef SYNCH_TIMERS
value32 = 0;
#endif /* SYNCH_TIMERS */
if (IOVirtualised(io_address, &value32, BIOS_INW_OFFSET, (sizeof(IU16))))
{
*value = (IU16)value32;
}
else
#endif /* VIRTUALISATION */
{
(*Ios_inw_function[Ios_in_adapter_table[io_address & (PC_IO_MEM_SIZE-1)]])
(io_address, value);
}
}
/*(
================================== outw ======================================
PURPOSE:
To perform an OUTW - i.e. call the appropriate SoftPC adapter's OUTW
IO routine. Note that this routine is not intended to be used by
the assembler CPU directly - it is intended that the assembler CPU
access the data tables above directly to discover which routine to call.
INPUT:
OUTPUT:
==============================================================================
)*/
GLOBAL void outw IFN2(io_addr, io_address, word, value)
{
#ifdef VIRTUALISATION
IU32 value32;
#endif /* VIRTUALISATION */
#ifdef EGA_DUMP
if (io_address >= EGA_AC_INDEX_DATA && io_address <= EGA_IPSTAT1_REG)
dump_outw(io_address, value);
#endif
sub_note_trace2( IOS_VERBOSE, "outw( %x, %x )", io_address, value );
#ifdef VIRTUALISATION
value32 = value;
if (IOVirtualised(io_address, &value32, BIOS_OUTW_OFFSET, (sizeof(IU16))))
return;
else
#endif /* VIRTUALISATION */
{
(*Ios_outw_function[Ios_out_adapter_table[io_address & (PC_IO_MEM_SIZE-1)]])
(io_address, value);
}
}
#ifdef SPC386
/*(
=================================== ind ======================================
PURPOSE:
To perform an IND - i.e. call the appropriate SoftPC adapter's IND
IO routine. Note that this routine is not intended to be used by
the assembler CPU directly - it is intended that the assembler CPU
access the data tables above directly to discover which routine to call.
INPUT:
OUTPUT:
==============================================================================
)*/
GLOBAL void ind IFN2(io_addr, io_address, IU32 *, value)
{
IU16 temp;
#ifdef VIRTUALISATION
IU32 value32;
#ifdef SYNCH_TIMERS
value32 = 0;
#endif /* SYNCH_TIMERS */
if (IOVirtualised(io_address, &value32, BIOS_IND_OFFSET, (sizeof(IU32))))
{
*value = value32;
}
else
#endif /* VIRTUALISATION */
{
inw(io_address,&temp);
*value = (IU32)temp;
io_address +=2;
inw(io_address,&temp);
*value |= ((IU32)temp << 16);
}
}
/*(
================================== outd ======================================
PURPOSE:
To perform an OUTD - i.e. call the appropriate SoftPC adapter's OUTD
IO routine. Note that this routine is not intended to be used by
the assembler CPU directly - it is intended that the assembler CPU
access the data tables above directly to discover which routine to call.
INPUT:
OUTPUT:
==============================================================================
)*/
GLOBAL void outd IFN2(io_addr, io_address, IU32, value)
{
sub_note_trace2( IOS_VERBOSE, "outd( %x, %x )", io_address, value );
#ifdef VIRTUALISATION
if (IOVirtualised(io_address, &value, BIOS_OUTD_OFFSET, (sizeof(IU32))))
return;
else
#endif /* VIRTUALISATION */
{
word temp;
temp = value & 0xffff;
outw(io_address,temp);
io_address +=2;
temp = (value >> 16);
outw(io_address,temp);
}
}
#endif /* SPC386 */
/*(
============================== io_define_inb =================================
PURPOSE:
To declare the address of the INB IO routine for the given adapter.
INPUT:
OUTPUT:
==============================================================================
)*/
GLOBAL void
#ifdef ANSI
io_define_inb(half_word adapter,
void (*func) IPT2(io_addr, io_address, half_word *, value))
#else
io_define_inb(adapter, func)
half_word adapter;
void (*func) ();
#endif /* ANSI */
{
Ios_inb_function[adapter] = FAST_FUNC_ADDR(func);
Ios_inw_function[adapter] = FAST_FUNC_ADDR(generic_inw);
Ios_insb_function[adapter] = generic_insb;
Ios_insw_function[adapter] = generic_insw;
#ifdef SPC386
Ios_ind_function[adapter] = generic_ind;
Ios_insd_function[adapter] = generic_insd;
#endif /* SPC386 */
}
/*(
========================== io_define_in_routines =============================
PURPOSE:
To declare the address of the input IO routine for the given adapter.
INPUT:
OUTPUT:
==============================================================================
)*/
GLOBAL void io_define_in_routines IFN5(half_word, adapter,
IOS_FUNC_INB, inb_func,
IOS_FUNC_INW, inw_func,
IOS_FUNC_INSB, insb_func,
IOS_FUNC_INSW, insw_func)
{
/*
* Preset defaultable entries to default value.
*/
Ios_inw_function[adapter] = FAST_FUNC_ADDR(generic_inw);
Ios_insb_function[adapter] = generic_insb;
Ios_insw_function[adapter] = generic_insw;
#ifdef SPC386
Ios_ind_function[adapter] = generic_ind;
Ios_insd_function[adapter] = generic_insd;
#endif /* SPC386 */
/*
* Process args into table entries
*/
Ios_inb_function[adapter] = FAST_FUNC_ADDR(inb_func);
if (inw_func) Ios_inw_function[adapter] = FAST_FUNC_ADDR(inw_func);
if (insb_func) Ios_insb_function[adapter] = insb_func;
if (insw_func) Ios_insw_function[adapter] = insw_func;
}
/*(
============================= io_define_outb =================================
PURPOSE:
To declare the address of the OUTB IO routine for the given adapter.
INPUT:
OUTPUT:
==============================================================================
)*/
GLOBAL void io_define_outb IFN2(half_word, adapter, IOS_FUNC_OUTB, func)
{
Ios_outb_function[adapter] = FAST_FUNC_ADDR(func);
Ios_outw_function[adapter] = FAST_FUNC_ADDR(generic_outw);
Ios_outsb_function[adapter] = generic_outsb;
Ios_outsw_function[adapter] = generic_outsw;
#ifdef SPC386
Ios_outd_function[adapter] = generic_outd;
Ios_outsd_function[adapter] = generic_outsd;
#endif /* SPC386 */
}
/*(
========================= io_define_out_routines =============================
PURPOSE:
To declare the address of the output IO routine for the given adapter.
INPUT:
OUTPUT:
==============================================================================
)*/
GLOBAL VOID io_define_out_routines IFN5(half_word, adapter,
IOS_FUNC_OUTB, outb_func,
IOS_FUNC_OUTW, outw_func,
IOS_FUNC_OUTSB, outsb_func,
IOS_FUNC_OUTSW, outsw_func)
{
/*
* Preset defaultable entries to default value.
*/
Ios_outw_function[adapter] = FAST_FUNC_ADDR(generic_outw);
Ios_outsb_function[adapter] = generic_outsb;
Ios_outsw_function[adapter] = generic_outsw;
#ifdef SPC386
Ios_outd_function[adapter] = generic_outd;
Ios_outsd_function[adapter] = generic_outsd;
#endif /* SPC386 */
/*
* Process args into table entries
*/
Ios_outb_function[adapter] = FAST_FUNC_ADDR(outb_func);
if (outw_func) Ios_outw_function[adapter] = FAST_FUNC_ADDR(outw_func);
if (outsb_func) Ios_outsb_function[adapter] = outsb_func;
if (outsw_func) Ios_outsw_function[adapter] = outsw_func;
}
#ifdef SPC386
/*(
========================= io_define_outd_routine =============================
PURPOSE:
To declare the address of the output IO routine for the given adapter.
INPUT:
OUTPUT:
==============================================================================
)*/
GLOBAL VOID io_define_outd_routine IFN3(half_word, adapter,
IOS_FUNC_OUTD, outd_func, IOS_FUNC_OUTSD, outsd_func)
{
/*
* Preset defaultable entries to default value.
*/
Ios_outb_function[adapter] = io_empty_outb;
Ios_outw_function[adapter] = generic_outw;
Ios_outd_function[adapter] = generic_outd;
Ios_outsb_function[adapter] = generic_outsb;
Ios_outsw_function[adapter] = generic_outsw;
Ios_outsd_function[adapter] = generic_outsd;
/*
* Process args into table entries
*/
if (outd_func) Ios_outd_function[adapter] = outd_func;
if (outsd_func) Ios_outsd_function[adapter] = outsd_func;
}
#endif /* SPC386 */
#ifdef SPC386
/*(
========================= io_define_ind_routine =============================
PURPOSE:
To declare the address of the output IO routine for the given adapter.
INPUT:
OUTPUT:
==============================================================================
)*/
GLOBAL VOID io_define_ind_routine IFN3(half_word, adapter,
IOS_FUNC_IND, ind_func, IOS_FUNC_INSD, insd_func)
{
/*
* Preset defaultable entries to default value.
*/
Ios_inb_function[adapter] = io_empty_inb;
Ios_inw_function[adapter] = generic_inw;
Ios_ind_function[adapter] = generic_ind;
Ios_insb_function[adapter] = generic_insb;
Ios_insw_function[adapter] = generic_insw;
Ios_insd_function[adapter] = generic_insd;
/*
* Process args into table entries
*/
if (ind_func) Ios_ind_function[adapter] = ind_func;
if (insd_func) Ios_insd_function[adapter] = insd_func;
}
#endif /* SPC386 */
/*(
============================= io_connect_port ================================
PURPOSE:
To associate a SoftPC IO adapter with the given IO address.
INPUT:
OUTPUT:
==============================================================================
)*/
#ifdef NTVDM
GLOBAL BOOL io_connect_port IFN3(io_addr, io_address, half_word, adapter,
half_word, mode)
{
if (mode & IO_READ){
Ios_in_adapter_table[io_address & (PC_IO_MEM_SIZE-1)] = adapter;
}
if (mode & IO_WRITE){
Ios_out_adapter_table[io_address & (PC_IO_MEM_SIZE-1)] = adapter;
}
return TRUE;
}
#else
GLOBAL void io_connect_port IFN3(io_addr, io_address, half_word, adapter,
half_word, mode)
{
if (mode & IO_READ){
Ios_in_adapter_table[io_address & (PC_IO_MEM_SIZE-1)] = adapter;
}
if (mode & IO_WRITE){
Ios_out_adapter_table[io_address & (PC_IO_MEM_SIZE-1)] = adapter;
}
}
#endif
/*(
=========================== io_disconnect_port ===============================
PURPOSE:
To associate the empty adapter with the given IO address.
INPUT:
OUTPUT:
==============================================================================
)*/
#ifdef NTVDM
GLOBAL void io_disconnect_port IFN2(io_addr, io_address, half_word, adapter)
{
if (adapter != Ios_in_adapter_table[io_address & (PC_IO_MEM_SIZE-1)] &&
adapter != Ios_out_adapter_table[io_address & (PC_IO_MEM_SIZE-1)])
{
return;
}
Ios_in_adapter_table[io_address & (PC_IO_MEM_SIZE-1)] = EMPTY_ADAPTOR;
Ios_out_adapter_table[io_address & (PC_IO_MEM_SIZE-1)] = EMPTY_ADAPTOR;
}
#else
GLOBAL void io_disconnect_port IFN2(io_addr, io_address, half_word, adapter)
{
UNUSED(adapter);
Ios_in_adapter_table[io_address] = EMPTY_ADAPTOR;
Ios_out_adapter_table[io_address] = EMPTY_ADAPTOR;
}
#endif /* NTVDM */
/*(
=========================== get_inb_ptr ======================================
PURPOSE:
To return address of inb routine for the given port
INPUT:
OUTPUT:
==============================================================================
)*/
GLOBAL IOS_FUNC_INB *get_inb_ptr IFN1(io_addr, io_address)
{
return(&Ios_inb_function[Ios_in_adapter_table[io_address & (PC_IO_MEM_SIZE-1)]]);
}
/*(
=========================== get_outb_ptr =====================================
PURPOSE:
To return address of outb routine for the given port
INPUT:
OUTPUT:
==============================================================================
)*/
GLOBAL IOS_FUNC_OUTB *get_outb_ptr IFN1(io_addr, io_address)
{
return(&Ios_outb_function[Ios_out_adapter_table[io_address & (PC_IO_MEM_SIZE-1)]]);
}
#ifdef SEGMENTATION
/*
* The following #include specifies the code segment into which this
* function will by placed by the MPW C compiler on the Mac II running
* MultiFinder.
*/
#include "SOFTPC_INIT.seg"
#endif
/*(
================================ io_init ===================================
PURPOSE:
To initialise the SoftPC IO subsystem.
INPUT:
OUTPUT:
==============================================================================
)*/
GLOBAL void io_init IFN0()
{
IU32 i; /* on some ports, PC_IO_MEM_SIZE == 0x10000, so this
must be a type with more than 16 bits */
/*
* Set up all IO address ports with the "empty" adapter
*/
io_define_inb (EMPTY_ADAPTOR, io_empty_inb);
io_define_outb(EMPTY_ADAPTOR, io_empty_outb);
#ifdef MAC68K
if (Ios_in_adapter_table == NULL) { /* First time around -- allocate */
Ios_in_adapter_table = host_malloc(PC_IO_MEM_SIZE);
Ios_out_adapter_table = host_malloc(PC_IO_MEM_SIZE);
}
#endif /* MAC68K */
#ifndef PROD
if (host_getenv("EMPTY_IO_VERBOSE") != NULL)
{
/* User does want empty I/O messages,
* so we must allocate bitmaps with one bit for every
* possible port number.
*/
ios_empty_in = (IU32 *)host_malloc((64*1024)/8);
ios_empty_out = (IU32 *)host_malloc((64*1024)/8);
memset((char *)ios_empty_in, 0, (64*1024)/8);
memset((char *)ios_empty_out, 0, (64*1024)/8);
}
#endif /* PROD */
for (i = 0; i < PC_IO_MEM_SIZE; i++){
Ios_in_adapter_table[i] = EMPTY_ADAPTOR;
Ios_out_adapter_table[i] = EMPTY_ADAPTOR;
}
}
#ifdef NTVDM
GLOBAL char GetExtIoInAdapter (io_addr ioaddr)
{
#ifndef PROD
printf("GetExtIoInAdapter(%x) called\n",ioaddr);
#endif
return EMPTY_ADAPTOR;
}
GLOBAL char GetExtIoOutAdapter (io_addr ioaddr)
{
#ifndef PROD
printf("GetExtIoOutAdapter(%x) called\n",ioaddr);
#endif
return EMPTY_ADAPTOR;
}
#endif /* NTVDM */