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.
 
 
 
 
 
 

771 lines
20 KiB

#include "insignia.h"
#include "host_def.h"
/*[
======================================================================
SoftPC Revision 3.0
Title:
v7_ports.c
Description:
Code for the extended registers of the Video 7 VGA.
Based on the V7 VGA Technical Reference Manual.
Author:
Phil Taylor
Date:
26 September 1990
SccsID "@(#)v7_ports.c 1.19 01/13/95 Copyright Insignia Solutions Ltd."
======================================================================
]*/
#ifdef V7VGA
#include "xt.h"
#include "gvi.h"
#include "gmi.h"
#include "ios.h"
#include "gfx_upd.h"
#include "debug.h"
#include "egacpu.h"
#include "egaports.h"
#include "egagraph.h"
#include "egaread.h"
#include "vgaports.h"
#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_VGA.seg"
#endif
IMPORT byte crtc_0_7_protect;
IMPORT byte crtc_0_8_protect;
IMPORT byte crtc_9_b_protect;
IMPORT byte crtc_c_protect;
FORWARD void draw_v7ptr();
GLOBAL ULONG fg_latches;
GLOBAL UTINY fg_bg_control;
GLOBAL void remove_v7ptr IPT0();
SAVED word curr_v7ptr_x;
SAVED word curr_v7ptr_y;
/*(
----------------------------------------------------------------------
Function:
vga_seq_extn_control( io_addr port, half_word value )
Purpose:
To emulate writing to the Extensions Control Register.
Input:
port - the V7VGA I/O port (should always be 0x3c5)
value - the value to be written to the register
Output:
The Extensions Control Register is set to the correct value.
----------------------------------------------------------------------
)*/
GLOBAL VOID
vga_seq_extn_control(port, value)
io_addr port;
half_word value;
{
NON_PROD(if(io_verbose & EGA_PORTS_VERBOSE)fprintf(trace_file,"seq(6,%#x)\n",value);)
note_entrance2("vga_seq_extn_control(%x,%x)", port, value);
if (value == 0xea)
sequencer.extensions_control.as_bfld.extension_enable = 1;
else if (value == 0xae)
sequencer.extensions_control.as_bfld.extension_enable = 0;
}
GLOBAL VOID
v7_get_banks( rd_bank, wrt_bank )
UTINY *rd_bank;
UTINY *wrt_bank;
{
if( get_seq_chain4_mode() && get_chain4_mode() ) {
set_v7_bank_for_seq_chain4( rd_bank, wrt_bank );
}
else {
/*
1.4.92 MG
Note that we and off the top bit of the bank selects. This means
that accesses to the top 512k (which we don't have) get mapped into
the bottom 512k, rather than being thrown away. This prevents SEGVs
and saves complications in the write routines, but causes other
problems.
Further explanation is in draw_v7ptr() at the end of this file.
*/
*rd_bank=(extensions_controller.ram_bank_select.as_bfld.cpu_read_bank_select&1);
*wrt_bank=(extensions_controller.ram_bank_select.as_bfld.cpu_write_bank_select&1);
}
}
/*(
----------------------------------------------------------------------
Function:
vga_extn_outb( io_addr port, half_word value )
Purpose:
To emulate writing to the V7VGA Extension Registers
Input:
port - the V7VGA I/O port (should always be 0x3c5)
value - the value to be written to the register
Output:
The Extension Registers are set to the correct value, and
any other required actions are emulated.
----------------------------------------------------------------------
)*/
GLOBAL VOID
vga_extn_outb(port, value)
io_addr port;
half_word value;
{
half_word old_value;
note_entrance2("vga_extn_outb(%x,%x)", port, value);
NON_PROD(if(io_verbose & EGA_PORTS_VERBOSE)fprintf(trace_file,"seq ext (%#x,%#x)\n",
sequencer.address.as.abyte,value);)
switch (sequencer.address.as.abyte) {
case 0x83:
note_entrance0("attribute controller index");
attribute_controller.address.as.abyte = value;
break;
case 0x94:
note_entrance0("pointer pattern");
extensions_controller.pointer_pattern = value;
host_start_update ();
(*clear_v7ptr)(curr_v7ptr_x, curr_v7ptr_y);
draw_v7ptr();
host_end_update ();
break;
case 0x9c:
note_entrance0("pointer horiz position hi");
extensions_controller.ptr_horiz_posn_hi.as.abyte = value;
break;
case 0x9d:
note_entrance0("pointer horiz position lo");
extensions_controller.ptr_horiz_posn_lo = value;
break;
case 0x9e:
note_entrance0("pointer vert position hi");
extensions_controller.ptr_vert_posn_hi.as.abyte = value;
break;
case 0x9f:
note_entrance0("pointer vert position lo");
extensions_controller.ptr_vert_posn_lo = value;
host_start_update ();
(*clear_v7ptr)(curr_v7ptr_x, curr_v7ptr_y);
draw_v7ptr();
host_end_update ();
break;
case 0xa0:
note_entrance0("graphics controller mem latch 0");
/* Direct access to memory data latch 0 */
put_latch0(value);
break;
case 0xa1:
note_entrance0("graphics controller mem latch 1");
/* Direct access to memory data latch 1 */
put_latch1(value);
break;
case 0xa2:
note_entrance0("graphics controller mem latch 2");
/* Direct access to memory data latch 2 */
put_latch2(value);
break;
case 0xa3:
note_entrance0("graphics controller mem latch 3");
/* Direct access to memory data latch 3 */
put_latch3(value);
break;
case 0xa4:
note_entrance0("clock select");
extensions_controller.clock_select.as.abyte = value;
/* Typically set to 0x10 for extended hi-res modes */
break;
case 0xa5:
note_entrance0("cursor attributes");
old_value=extensions_controller.cursor_attrs.as.abyte;
extensions_controller.cursor_attrs.as.abyte = value;
/*
8.6.92 MG
We need to check that the pointer was disabled
before we redraw it when it is enabled. Otherwise
we can get old pointers left on the screen in
Windows.
*/
/* Not doing cursor mode stuff (whatever that means) */
if (value&0x80!=old_value&0x80) {
host_start_update ();
if (value & 0x80) {
/* Enable hardware graphics pointer */
draw_v7ptr();
}
else {
/* Disable hardware graphics pointer */
(*clear_v7ptr)(curr_v7ptr_x, curr_v7ptr_y);
}
host_end_update ();
}
break;
/*
31.3.92 MG Register c1 is an undocumented DAC control
register, bit 0 switches between 6 and 8 bit data in
the DAC.
*/
case 0xc1:
extensions_controller.dac_control.as.abyte=value;
if (extensions_controller.dac_control.as_bfld.dac_8_bits) {
DAC_data_bits=8;
DAC_data_mask=0xff;
}
else {
DAC_data_bits=6;
DAC_data_mask=0x3f;
}
break;
case 0xea:
note_entrance0("switch strobe");
/* loads up switch readback with some CPU data lines */
extensions_controller.switch_readback = 0xff;
/* This is hard coded for the jumper/switch settings, and might not be right */
break;
case 0xeb:
note_entrance0("emulation_control");
extensions_controller.emulation_control.as.abyte = value;
if (extensions_controller.emulation_control.as_bfld.write_prot_2)
crtc_0_8_protect = TRUE;
else
crtc_0_8_protect = FALSE;
if (extensions_controller.emulation_control.as_bfld.write_prot_1)
crtc_9_b_protect = TRUE;
else
crtc_9_b_protect = FALSE;
if (extensions_controller.emulation_control.as_bfld.write_prot_0)
crtc_c_protect = TRUE;
else
crtc_c_protect = FALSE;
break;
case 0xec:
note_entrance0("foreground latch 0");
extensions_controller.foreground_latch_0 = value;
SET_FG_LATCH( 0, value );
break;
case 0xed:
note_entrance0("foreground latch 1");
extensions_controller.foreground_latch_1 = value;
SET_FG_LATCH( 1, value );
break;
case 0xee:
note_entrance0("foreground latch 2");
extensions_controller.foreground_latch_2 = value;
SET_FG_LATCH( 2, value );
break;
case 0xef:
note_entrance0("foreground latch 3");
extensions_controller.foreground_latch_3 = value;
SET_FG_LATCH( 3, value );
break;
case 0xf0:
note_entrance0("fast foreground latch load");
switch (extensions_controller.fast_latch_load_state.as_bfld.fg_latch_load_state)
{
case 0:
extensions_controller.foreground_latch_0 = value;
extensions_controller.fast_latch_load_state.as_bfld.fg_latch_load_state = 1;
SET_FG_LATCH( 0, value );
break;
case 1:
extensions_controller.foreground_latch_1 = value;
extensions_controller.fast_latch_load_state.as_bfld.fg_latch_load_state = 2;
SET_FG_LATCH( 1, value );
break;
case 2:
extensions_controller.foreground_latch_2 = value;
extensions_controller.fast_latch_load_state.as_bfld.fg_latch_load_state = 3;
SET_FG_LATCH( 2, value );
break;
case 3:
extensions_controller.foreground_latch_3 = value;
extensions_controller.fast_latch_load_state.as_bfld.fg_latch_load_state = 0;
SET_FG_LATCH( 3, value );
break;
}
break;
case 0xf1:
note_entrance0("fast latch load state");
extensions_controller.fast_latch_load_state.as.abyte = value;
break;
case 0xf2:
note_entrance0("fast background latch load");
switch (extensions_controller.fast_latch_load_state.as_bfld.bg_latch_load_state)
{
case 0:
put_latch0(value);
extensions_controller.fast_latch_load_state.as_bfld.bg_latch_load_state = 1;
break;
case 1:
put_latch1(value);
extensions_controller.fast_latch_load_state.as_bfld.bg_latch_load_state = 2;
break;
case 2:
put_latch2(value);
extensions_controller.fast_latch_load_state.as_bfld.bg_latch_load_state = 3;
break;
case 3:
put_latch3(value);
extensions_controller.fast_latch_load_state.as_bfld.bg_latch_load_state = 0;
break;
}
break;
case 0xf3:
note_entrance0("masked write control");
extensions_controller.masked_write_control.as.abyte = value;
break;
case 0xf4:
note_entrance0("masked write mask");
extensions_controller.masked_write_mask = value;
break;
case 0xf5:
note_entrance0("foreground/background pattern");
extensions_controller.fg_bg_pattern = value;
break;
case 0xf6:
note_entrance0("1Mb RAM bank select");
extensions_controller.ram_bank_select.as.abyte = value;
update_banking();
break;
case 0xf7:
note_entrance0("switch readback");
extensions_controller.switch_readback = value;
break;
case 0xf8:
note_entrance0("clock control");
extensions_controller.clock_control.as.abyte = value;
/* Hope we don't have to do anything here */
break;
case 0xf9:
note_entrance0("page select");
extensions_controller.page_select.as.abyte = value;
update_banking();
break;
case 0xfa:
note_entrance0("foreground color");
extensions_controller.foreground_color.as.abyte = value;
break;
case 0xfb:
note_entrance0("background color");
extensions_controller.background_color.as.abyte = value;
break;
case 0xfc:
note_entrance0("compatibility control");
{
BOOL now_seqchain4;
BOOL now_seqchain;
now_seqchain4 = get_seq_chain4_mode();
now_seqchain = get_seq_chain_mode();
extensions_controller.compatibility_control.as.abyte = value;
set_seq_chain4_mode(extensions_controller.compatibility_control.as_bfld.sequential_chain4);
set_seq_chain_mode(extensions_controller.compatibility_control.as_bfld.sequential_chain);
if (get_chain4_mode() && (now_seqchain4 != get_seq_chain4_mode()))
{
/* do we need to change the read/write routines here?? */
ega_read_routines_update();
ega_write_routines_update( CHAINED );
}
}
break;
case 0xfd:
note_entrance0("timing select");
extensions_controller.timing_select.as.abyte = value;
/* Used to select timing states for V-RAM hi-res modes */
/* Hope we don't have to do anything here */
break;
case 0xfe:
note_entrance0("foreground/background control");
extensions_controller.fg_bg_control.as.abyte = value;
fg_bg_control = value;
ega_read_routines_update();
ega_write_routines_update( WRITE_MODE );
/***
set_fg_bg_mode();
***/
break;
case 0xff:
note_entrance0("16-bit interface control");
extensions_controller.interface_control.as.abyte = value;
/***
sort_out_memory_stuff();
sort_out_interface_stuff();
***/
break;
default:
NON_PROD(if(io_verbose & EGA_PORTS_VERBOSE)
fprintf(trace_file,"Bad extensions index %x\n",
sequencer.address.as.abyte);)
break;
}
}
/*(
----------------------------------------------------------------------
Function:
vga_extn_inb( io_addr port, half_word *value )
Purpose:
To emulate reading from the V7VGA Extension Registers
Input:
port - the V7VGA I/O port (should always be 0x3c5)
Output:
value - the value read from the register
Any other required actions are emulated.
----------------------------------------------------------------------
)*/
GLOBAL VOID
vga_extn_inb(port, value)
io_addr port;
half_word *value;
{
note_entrance1("vga_extn_inb(%x)", port);
switch (sequencer.address.as.abyte) {
case 0x83:
*value = attribute_controller.address.as.abyte;
break;
case 0x8e:
case 0x8f:
/* chip revision 3 */
*value = 0x70;
break;
case 0x94:
*value = extensions_controller.pointer_pattern;
break;
case 0x9c:
*value = extensions_controller.ptr_horiz_posn_hi.as.abyte;
break;
case 0x9d:
*value = extensions_controller.ptr_horiz_posn_lo;
break;
case 0x9e:
*value = extensions_controller.ptr_vert_posn_hi.as.abyte;
break;
case 0x9f:
*value = extensions_controller.ptr_vert_posn_lo;
break;
case 0xa0:
/* Direct access to memory data latch 0 */
*value = get_latch0;
break;
case 0xa1:
/* Direct access to memory data latch 1 */
*value = get_latch1;
break;
case 0xa2:
/* Direct access to memory data latch 2 */
*value = get_latch2;
break;
case 0xa3:
/* Direct access to memory data latch 3 */
*value = get_latch3;
break;
case 0xa4:
*value = extensions_controller.clock_select.as.abyte;
break;
case 0xa5:
*value = extensions_controller.cursor_attrs.as.abyte & 0x89;
break;
/*
31.3.92 MG Register C1 controls 6/8 bit data in the DAC.
*/
case 0xc1:
*value=extensions_controller.dac_control.as.abyte;
break;
case 0xeb:
*value = extensions_controller.emulation_control.as.abyte;
break;
case 0xec:
*value = extensions_controller.foreground_latch_0;
break;
case 0xed:
*value = extensions_controller.foreground_latch_1;
break;
case 0xee:
*value = extensions_controller.foreground_latch_2;
break;
case 0xef:
*value = extensions_controller.foreground_latch_3;
break;
case 0xf0:
switch (extensions_controller.fast_latch_load_state.as_bfld.fg_latch_load_state)
{
case 0:
*value = extensions_controller.foreground_latch_0;
break;
case 1:
*value = extensions_controller.foreground_latch_1;
break;
case 2:
*value = extensions_controller.foreground_latch_2;
break;
case 3:
*value = extensions_controller.foreground_latch_3;
break;
}
extensions_controller.fast_latch_load_state.as_bfld.fg_latch_load_state = 0;
break;
case 0xf1:
*value = extensions_controller.fast_latch_load_state.as.abyte;
break;
case 0xf2:
switch (extensions_controller.fast_latch_load_state.as_bfld.bg_latch_load_state)
{
case 0:
*value = get_latch0;
break;
case 1:
*value = get_latch1;
break;
case 2:
*value = get_latch2;
break;
case 3:
*value = get_latch3;
break;
}
extensions_controller.fast_latch_load_state.as_bfld.bg_latch_load_state = 0;
break;
case 0xf3:
*value = extensions_controller.masked_write_control.as.abyte & 3;
break;
case 0xf4:
*value = extensions_controller.masked_write_mask;
break;
case 0xf5:
*value = extensions_controller.fg_bg_pattern;
break;
case 0xf6:
*value = extensions_controller.ram_bank_select.as.abyte;
break;
case 0xf7:
*value = extensions_controller.switch_readback;
break;
case 0xf8:
*value = extensions_controller.clock_control.as.abyte;
break;
case 0xf9:
*value = extensions_controller.page_select.as_bfld.extended_page_select;
break;
case 0xfa:
*value = extensions_controller.foreground_color.as.abyte;
break;
case 0xfb:
*value = extensions_controller.background_color.as.abyte;
break;
case 0xfc:
*value = extensions_controller.compatibility_control.as.abyte;
break;
case 0xfd:
*value = extensions_controller.timing_select.as.abyte;
break;
case 0xfe:
*value = extensions_controller.fg_bg_control.as.abyte & 0xe;
break;
case 0xff:
*value = extensions_controller.interface_control.as.abyte;
break;
default:
NON_PROD(if(io_verbose & EGA_PORTS_VERBOSE)
fprintf(trace_file,"Bad extensions index %x\n",
sequencer.address.as.abyte);)
/* 31.3.92 MG This used to return 0xFF, but a real card
returns zero. */
*value = 0;
break;
}
note_entrance1("returning %x",*value);
}
/*(
----------------------------------------------------------------------
Function:
draw_v7ptr()
Purpose:
To emulate the V7 hardware pointer on the screen.
Input:
None.
Output:
The pointer is displayed on the screen.
----------------------------------------------------------------------
)*/
GLOBAL VOID
draw_v7ptr()
{
sys_addr pattern;
if (extensions_controller.cursor_attrs.as_bfld.pointer_enable)
{
curr_v7ptr_x = extensions_controller.ptr_horiz_posn_lo +
(extensions_controller.ptr_horiz_posn_hi.as_bfld.ptr_horiz_position << 8);
if (get_seq_chain4_mode() && get_chain4_mode())
{
/*
* In the extended 256 col modes we seem to need to halve
* the x coordinate to get the pointer in the right place.
*/
curr_v7ptr_x >>= 1;
}
curr_v7ptr_y = extensions_controller.ptr_vert_posn_lo +
(extensions_controller.ptr_vert_posn_hi.as_bfld.ptr_vert_position << 8);
/*
* I have never seen the pointer bank select bits used, so
* this is a guess as to their meaning.
*/
/*
1.4.92 MG
Sadly, this guess isn't correct - the pointer_bank_select bits are
used to select which 256k bank the pointer data is read from. Now
we have a problem, as if a program writes the data to the third
bank then it actually ends up in the first because the bank
selection routines for memory access and off the top bit.
As a result, we also need to lose the top bit here. The correct
way to do this would be to either support nonexistent VGA memory
correctly, or to add another 512k to the memory we already use.
This fix is mainly to make Windows 3.1 work with its video-7
driver. It stuffs bytes into the last few k of the 1Mb space on
the video-7 to see if the memory exists. As we just map this
access to 512k lower, it thinks we have 1Mb of RAM rather than
512k, so puts the pointer at the top of the 1Mb.
Programs which call the VGA BIOS to determine the memory size
will not have this problem.
*/
pattern = (((extensions_controller.interface_control.as_bfld.pointer_bank_select&1) << 16)
+ (0xc000 + (extensions_controller.pointer_pattern << 6))) << 2;
(*paint_v7ptr)(pattern, curr_v7ptr_x, curr_v7ptr_y);
}
}
GLOBAL VOID remove_v7ptr IFN0()
{
(*clear_v7ptr)(curr_v7ptr_x, curr_v7ptr_y);
}
GLOBAL BOOL v7ptr_between_lines IFN2(int, start_line, int, end_line)
{
if (curr_v7ptr_y+32<start_line||curr_v7ptr_y>end_line)
return FALSE;
return TRUE;
}
#ifdef CPU_40_STYLE
/*
* 4.0 video support moves v7 fg latch value from variable 'fg_latches'
* int CPU variable accessed by interface fn to get/set all 4 bytes of
* latches. Take byte index and value and update v7 latch via interface
*/
GLOBAL void set_v7_fg_latch_byte IFN2(IU8, index, IU8, value)
{
IU32 v7latch;
/* get current value */
v7latch = getVideov7_fg_latches();
/* change byte 'index' to 'value */
switch(index)
{
case 0:
v7latch = (v7latch & 0xffffff00) | value;
break;
case 1:
v7latch = (v7latch & 0xffff00ff) | (value << 8);
break;
case 2:
v7latch = (v7latch & 0xff00ffff) | (value << 16);
break;
case 3:
v7latch = (v7latch & 0x00ffffff) | (value << 24);
break;
default:
always_trace1("set_v7_fg_latch_byte: index > 3 (%d)", index);
}
/* update v7 latches */
setVideov7_fg_latches(v7latch);
}
#endif /* CPU_40_STYLE */
#endif /* V7VGA */