minivmac4ios/Mini vMac/mnvm_core/IWMEMDEV.c
2016-05-28 14:18:59 +02:00

211 lines
4.5 KiB
C
Executable File

/*
IWMEVDEV.c
Copyright (C) 2006 Philip Cummins, Paul C. Pratt
You can redistribute this file and/or modify it under the terms
of version 2 of the GNU General Public License as published by
the Free Software Foundation. You should have received a copy
of the license along with this file; see the file COPYING.
This file is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
license for more details.
*/
/*
Integrated Woz Machine EMulated DEVice
Emulates the IWM found in the Mac Plus.
This code is adapted from "IWM.c" in vMac by Philip Cummins.
*/
/*
This is the emulation for the IWM, the Integrated Woz Machine.
It's basically a serial to parallel converter with some timing
in-built into it to perform handshaking. Emulation so far just
includes Status and Mode Register Accesses.
*/
#ifndef AllFiles
#include "SYSDEPNS.h"
#include "MYOSGLUE.h"
#include "EMCONFIG.h"
#include "GLOBGLUE.h"
#endif
#include "IWMEMDEV.h"
#define kph0L 0x00 /* CA0 off (0) */
#define kph0H 0x01 /* CA0 on (1) */
#define kph1L 0x02 /* CA1 off (0) */
#define kph1H 0x03 /* CA1 on (1) */
#define kph2L 0x04 /* CA2 off (0) */
#define kph2H 0x05 /* CA2 on (1) */
#define kph3L 0x06 /* LSTRB off (low) */
#define kph3H 0x07 /* LSTRB on (high) */
#define kmtrOff 0x08 /* disk enable off */
#define kmtrOn 0x09 /* disk enable on */
#define kintDrive 0x0A /* select internal drive */
#define kextDrive 0x0B /* select external drive */
#define kq6L 0x0C /* Q6 off */
#define kq6H 0x0D /* Q6 on */
#define kq7L 0x0E /* Q7 off */
#define kq7H 0x0F /* Q7 on */
#define kph0 0x01
#define kph1 0x02
#define kph2 0x04
#define kph3 0x08
#define kmtr 0x10
#define kdrv 0x20
#define kq6 0x40
#define kq7 0x80
typedef struct
{
ui3b DataIn; /* Read Data Register */
ui3b Handshake; /* Read Handshake Register */
ui3b Status; /* Read Status Register */
ui3b Mode;
/* Drive Off : Write Mode Register */
/* Drive On : Write Data Register */
ui3b DataOut; /* Write Data Register */
ui3b Lines; /* Used to Access Disk Drive Registers */
} IWM_Ty;
IWM_Ty IWM;
GLOBALPROC IWM_Reset(void)
{
IWM.DataIn = IWM.Handshake = IWM.Status = IWM.Mode =
IWM.DataOut = IWM.Lines = 0;
}
typedef enum {On, Off} Mode_Ty;
LOCALPROC IWM_Set_Lines(ui3b line, Mode_Ty the_mode)
{
if (the_mode == Off) {
IWM.Lines &= (0xFF - line);
} else {
IWM.Lines |= line;
}
}
LOCALFUNC ui3b IWM_Read_Reg(void)
{
switch ((IWM.Lines & (kq6 + kq7)) >> 6) {
case 0 :
#if (CurEmMd >= kEmMd_SE) && (CurEmMd <= kEmMd_IIx)
/* don't report */
#else
ReportAbnormal("IWM Data Read");
#endif
#ifdef _IWM_Debug
printf("IWM Data Read\n");
#endif
return IWM.DataIn;
break;
case 1 :
#ifdef _IWM_Debug
printf("IWM Status Read\n");
#endif
return IWM.Status;
break;
case 2 :
ReportAbnormal("IWM Handshake Read");
#ifdef _IWM_Debug
printf("IWM Handshake Read\n");
#endif
return IWM.Handshake;
break;
case 3 :
default :
/*
should alway be in 0-3,
but compiler warnings don't know that
*/
return 0;
break;
}
}
LOCALPROC IWM_Write_Reg(ui3b in)
{
if (((IWM.Lines & kmtr) >> 4) == 0) {
#ifdef _IWM_Debug
printf("IWM Mode Register Write\n");
#endif
IWM.Mode = in;
IWM.Status = ((IWM.Status & 0xE0) + (IWM.Mode & 0x1F));
}
}
GLOBALFUNC ui5b IWM_Access(ui5b Data, blnr WriteMem, CPTR addr)
{
switch (addr) {
case kph0L :
IWM_Set_Lines(kph0, Off);
break;
case kph0H :
IWM_Set_Lines(kph0, On);
break;
case kph1L :
IWM_Set_Lines(kph1, Off);
break;
case kph1H :
IWM_Set_Lines(kph1, On);
break;
case kph2L :
IWM_Set_Lines(kph2, Off);
break;
case kph2H :
IWM_Set_Lines(kph2, On);
break;
case kph3L :
IWM_Set_Lines(kph3, Off);
break;
case kph3H :
IWM_Set_Lines(kph3, On);
break;
case kmtrOff :
IWM.Status &= 0xDF;
IWM_Set_Lines(kmtr, Off);
break;
case kmtrOn :
IWM.Status |= 0x20;
IWM_Set_Lines(kmtr, On);
break;
case kintDrive :
IWM_Set_Lines(kdrv, Off);
break;
case kextDrive :
IWM_Set_Lines(kdrv, On);
break;
case kq6L :
IWM_Set_Lines(kq6, Off);
break;
case kq6H :
IWM_Set_Lines(kq6, On);
break;
case kq7L :
if (! WriteMem) {
Data = IWM_Read_Reg();
}
IWM_Set_Lines(kq7, Off);
break;
case kq7H :
if (WriteMem) {
IWM_Write_Reg(Data);
}
IWM_Set_Lines(kq7, On);
break;
}
return Data;
}