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.
325 lines
7.9 KiB
325 lines
7.9 KiB
#include "insignia.h"
|
|
#include "host_def.h"
|
|
/*
|
|
* SoftPC Revision 3.0
|
|
*
|
|
* Title : cassette_io
|
|
*
|
|
* Description : Cassette i/o functions - interrupt 15H.
|
|
*
|
|
* Notes : None
|
|
*
|
|
*/
|
|
|
|
/*
|
|
* static char SccsID[]="@(#)tape_io.c 1.26 06/28/95 Copyright Insignia Solutions Ltd.";
|
|
*/
|
|
|
|
|
|
#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_BIOS.seg"
|
|
#endif
|
|
|
|
/*
|
|
* O/S include files.
|
|
*/
|
|
#include <stdio.h>
|
|
#include TypesH
|
|
|
|
/*
|
|
* SoftPC include files
|
|
*/
|
|
#include "xt.h"
|
|
#include CpuH
|
|
#include "sas.h"
|
|
#include "ios.h"
|
|
#include "bios.h"
|
|
#include "tape_io.h"
|
|
#include "ica.h"
|
|
#include "cmos.h"
|
|
#include "rtc_bios.h"
|
|
#include "cmosbios.h"
|
|
#include "trace.h"
|
|
#include "debug.h"
|
|
#include "quick_ev.h"
|
|
|
|
|
|
#define ONE_MEGABYTE (1024 * 1024)
|
|
#define SIXTY_FOUR_K (64 * 1024)
|
|
#define WRAP_AREA(addr) (addr) >= ONE_MEGABYTE && (addr) < ONE_MEGABYTE + SIXTY_FOUR_K
|
|
|
|
LOCAL q_ev_handle wait_event_handle = (q_ev_handle)0;
|
|
|
|
/* Call back routine that needs to set a user's flag byte */
|
|
LOCAL void wait_event IFN1(long, parm)
|
|
{
|
|
LIN_ADDR addr = (LIN_ADDR)parm;
|
|
|
|
note_trace1(CMOS_VERBOSE, "INT15_EVENT_WAIT: delay complete: flag at %05x\n", addr);
|
|
|
|
sas_store( addr, sas_hw_at( addr ) | 0x80 );
|
|
wait_event_handle = (q_ev_handle)0;
|
|
}
|
|
|
|
void cassette_io()
|
|
{
|
|
#ifdef PM
|
|
#ifndef CPU_30_STYLE
|
|
IMPORT void retrieve_descr_fields IPT4(half_word *, AR, sys_addr *, base,
|
|
word *, limit, sys_addr, descr_addr);
|
|
#endif /* not CPU_30_STYLE */
|
|
half_word cmos_u_m_s_hi;
|
|
half_word cmos_u_m_s_lo;
|
|
sys_addr gdt;
|
|
sys_addr source;
|
|
sys_addr source_base;
|
|
sys_addr target;
|
|
#if (!defined(PROD) || !defined(CPU_30_STYLE))
|
|
word source_limit;
|
|
word target_limit;
|
|
#endif
|
|
sys_addr target_base;
|
|
sys_addr byte_count; /* Max size is 0x8000 * 2 = 10000 */
|
|
#ifdef CPU_30_STYLE
|
|
DESCR src_entry;
|
|
DESCR dst_entry;
|
|
#else
|
|
half_word source_AR;
|
|
half_word target_AR;
|
|
#endif /* CPU_30_STYLE */
|
|
#endif /* PM */
|
|
|
|
half_word mask, /* interrupt mask */
|
|
alarm; /* value read from alarm register */
|
|
|
|
#if defined(NTVDM) && defined(MONITOR)
|
|
IMPORT word conf_15_seg, conf_15_off;
|
|
#endif /* NTVDM & MONITOR */
|
|
/*
|
|
* Determine function
|
|
*/
|
|
switch ( getAH() )
|
|
{
|
|
case INT15_DEVICE_OPEN:
|
|
case INT15_DEVICE_CLOSE:
|
|
case INT15_PROGRAM_TERMINATION:
|
|
case INT15_REQUEST_KEY:
|
|
case INT15_DEVICE_BUSY:
|
|
setAH( 0 );
|
|
setCF( 0 );
|
|
break;
|
|
|
|
case INT15_EMS_DETERMINE:
|
|
#if 0 /* I'm sure we've all had enough of this one */
|
|
always_trace0("INT15 Extended Memory Access");
|
|
#endif
|
|
#ifdef PM
|
|
outb(CMOS_PORT, CMOS_U_M_S_LO);
|
|
inb(CMOS_DATA, &cmos_u_m_s_lo);
|
|
outb(CMOS_PORT, CMOS_U_M_S_HI);
|
|
inb(CMOS_DATA, &cmos_u_m_s_hi);
|
|
setAH(cmos_u_m_s_hi);
|
|
setAL(cmos_u_m_s_lo);
|
|
#else
|
|
setAX ( 0 );
|
|
#endif /* PM */
|
|
break;
|
|
case INT15_MOVE_BLOCK:
|
|
#ifdef PM
|
|
/* Unlike the real PC we don't have to go into protected
|
|
mode in order to address memory above 1MB, thanks to
|
|
the wonders of C this function becomes much simpler
|
|
than the contortions of the bios */
|
|
|
|
gdt = effective_addr(getES(), getSI());
|
|
source = gdt + 0x10; /* see layout in bios listing */
|
|
target = gdt + 0x18;
|
|
|
|
#ifdef CPU_30_STYLE
|
|
read_descriptor(source, &src_entry);
|
|
read_descriptor(target, &dst_entry);
|
|
source_base = src_entry.base;
|
|
target_base = dst_entry.base;
|
|
#ifndef PROD
|
|
source_limit = src_entry.limit;
|
|
target_limit = dst_entry.limit;
|
|
#endif
|
|
|
|
assert1( (src_entry.AR & 0x9e) == 0x92, "Bad source access rights %x", src_entry.AR );
|
|
assert1( (dst_entry.AR & 0x9e) == 0x92, "Bad dest access rights %x", dst_entry.AR );
|
|
|
|
#else /* CPU_30_STYLE */
|
|
/* retrieve descriptor information for source */
|
|
retrieve_descr_fields(&source_AR, &source_base, &source_limit, source);
|
|
|
|
/* retrieve descriptor information for target */
|
|
retrieve_descr_fields(&target_AR, &target_base, &target_limit, target);
|
|
#endif /* CPU_30_STYLE */
|
|
|
|
/* make word count into a byte count */
|
|
byte_count = getCX() << 1;
|
|
|
|
assert1( byte_count <= 0x10000, "Invalid byte_count %x", byte_count );
|
|
|
|
/* Check count not outside limits of target
|
|
and source blocks. */
|
|
|
|
assert0( byte_count <= source_limit + 1, "Count outside source limit" );
|
|
assert0( byte_count <= target_limit + 1, "Count outside target limit" );
|
|
|
|
/* TO DO: Check base addresses of target and source
|
|
fall within the area of extended memory
|
|
that we support */
|
|
|
|
/* Go to it */
|
|
if (sas_twenty_bit_wrapping_enabled())
|
|
{
|
|
#ifdef NTVDM
|
|
/* call xms functions to deal with A20 line */
|
|
xmsDisableA20Wrapping();
|
|
sas_move_words_forward ( source_base, target_base, byte_count >> 1);
|
|
xmsEnableA20Wrapping();
|
|
#else
|
|
sas_disable_20_bit_wrapping();
|
|
sas_move_words_forward ( source_base, target_base, byte_count >> 1);
|
|
sas_enable_20_bit_wrapping();
|
|
#endif /* NTVDM */
|
|
}
|
|
else
|
|
sas_move_words_forward ( source_base, target_base, byte_count >> 1);
|
|
|
|
/* set for good completion, just like bios after reset */
|
|
setAH(0);
|
|
setCF(0);
|
|
setZF(1);
|
|
setIF(1);
|
|
#else
|
|
setCF(1);
|
|
setAH(INT15_INVALID);
|
|
#endif
|
|
break;
|
|
|
|
case INT15_VIRTUAL_MODE:
|
|
always_trace0("INT15 Virtual Mode (Go into PM)");
|
|
#ifdef PM
|
|
/*
|
|
* This function returns to the user in protected mode.
|
|
*
|
|
* See BIOS listing 5-174 AT Tech Ref for full details
|
|
*
|
|
* Upon entry the following is expected to be set up:-
|
|
*
|
|
* ES - GDT segment
|
|
* SI - GDT offset
|
|
* BH - hardware int level 1 offset
|
|
* BL - hardware int level 2 offset
|
|
*
|
|
* Also
|
|
*
|
|
* (ES:SI) -> 0 +-------------+
|
|
* | DUMMY |
|
|
* 8 +-------------+
|
|
* | GDT |
|
|
* 16+-------------+
|
|
* | IDT |
|
|
* 24+-------------+
|
|
* | DS |
|
|
* 32+-------------+
|
|
* | ES |
|
|
* 40+-------------+
|
|
* | SS |
|
|
* 48+-------------+
|
|
* | CS |
|
|
* 52+-------------+
|
|
* | (BIOS CS) |
|
|
* +-------------+
|
|
*/
|
|
|
|
/* Clear interrupt flag - no ints allowed in this mode. */
|
|
setIF(0);
|
|
|
|
/* Enable a20. */
|
|
sas_disable_20_bit_wrapping();
|
|
|
|
/* Reinitialise ICA0 to the offset given in BH. */
|
|
outb(ICA0_PORT_0, (half_word)0x11);
|
|
outb(ICA0_PORT_1, (half_word)getBH());
|
|
outb(ICA0_PORT_1, (half_word)0x04);
|
|
outb(ICA0_PORT_1, (half_word)0x01);
|
|
outb(ICA0_PORT_1, (half_word)0xff);
|
|
|
|
/* Reinitialise ICA1 to the offset given in BL. */
|
|
outb(ICA1_PORT_0, (half_word)0x11);
|
|
outb(ICA1_PORT_1, (half_word)getBL());
|
|
outb(ICA1_PORT_1, (half_word)0x02);
|
|
outb(ICA1_PORT_1, (half_word)0x01);
|
|
outb(ICA1_PORT_1, (half_word)0xff);
|
|
|
|
/* Set DS to the ES value for the bios rom to do the rest. */
|
|
setDS(getES());
|
|
|
|
#else
|
|
setCF(1);
|
|
setAH(INT15_INVALID);
|
|
#endif /* PM */
|
|
break;
|
|
|
|
case INT15_INTERRUPT_COMPLETE:
|
|
break;
|
|
case INT15_CONFIGURATION:
|
|
#if defined(NTVDM) && defined(MONITOR)
|
|
setES( conf_15_seg );
|
|
setBX( conf_15_off );
|
|
#else
|
|
setES( getCS() );
|
|
setBX( CONF_TABLE_OFFSET );
|
|
#endif
|
|
setAH( 0 );
|
|
setCF( 0 );
|
|
break;
|
|
|
|
#ifdef SPC486
|
|
case 0xc9:
|
|
setCF( 0 );
|
|
setAH( 0 );
|
|
setCX( 0xE401 );
|
|
note_trace0(GENERAL_VERBOSE, "INT15: C9 chip revision");
|
|
break;
|
|
#endif /* SPC486 */
|
|
|
|
/* Keyboard intercept 0x4f, wait_event 83, wait 86 are all no longer
|
|
* passed through from ROM.
|
|
*/
|
|
|
|
default:
|
|
/*
|
|
* All other functions invalid.
|
|
*/
|
|
#ifndef PROD
|
|
{
|
|
LIN_ADDR stack=effective_addr(getSS(),getSP());
|
|
|
|
IU16 ip = sas_w_at(stack);
|
|
IU16 cs = sas_w_at(stack+2);
|
|
|
|
note_trace3(GENERAL_VERBOSE, "INT15: AH=%02x @ %04x:%04x", getAH(), cs, ip);
|
|
}
|
|
#endif /* PROD */
|
|
|
|
/* Fall through */
|
|
|
|
case INT15_JOYSTICK:
|
|
case 0x24: /* A20 wrapping control */
|
|
case 0xd8: /* EISA device access */
|
|
case 0x41: /* Laptop wait event */
|
|
setCF(1);
|
|
setAH(INT15_INVALID);
|
|
break;
|
|
}
|
|
}
|
|
|