diff --git a/AltairZ80/CMakeLists.txt b/AltairZ80/CMakeLists.txt index 242085e8..0e5f8591 100644 --- a/AltairZ80/CMakeLists.txt +++ b/AltairZ80/CMakeLists.txt @@ -18,6 +18,7 @@ add_simulator(altairz80 SOURCES altairz80_cpu.c altairz80_cpu_nommu.c + s100_jair.c sol20.c s100_vdm1.c mmd.c diff --git a/AltairZ80/altairz80_sys.c b/AltairZ80/altairz80_sys.c index f50841b1..473a0ce1 100644 --- a/AltairZ80/altairz80_sys.c +++ b/AltairZ80/altairz80_sys.c @@ -79,6 +79,10 @@ extern DEVICE m2sio0_dev; extern DEVICE m2sio1_dev; extern DEVICE pmmi_dev; extern DEVICE hayes_dev; +extern DEVICE jair_dev; +extern DEVICE jairs0_dev; +extern DEVICE jairs1_dev; +extern DEVICE jairp_dev; extern DEVICE mmd_dev; extern DEVICE mmdm_dev; extern DEVICE sol20_dev; @@ -171,6 +175,11 @@ DEVICE *sim_devices[] = { &pmmi_dev, /* HAYES MODEM */ &hayes_dev, + /* JAIR SBC */ + &jair_dev, + &jairs0_dev, + &jairs1_dev, + &jairp_dev, /* Vector Graphic Devices */ &fw2_dev, &vfdhd_dev, /* Single-Board Computers */ diff --git a/AltairZ80/s100_jair.c b/AltairZ80/s100_jair.c new file mode 100644 index 00000000..6635cd63 --- /dev/null +++ b/AltairZ80/s100_jair.c @@ -0,0 +1,1815 @@ +/*** s100_jair.c: Josh's Altair / IMASI Replacement CPU & SBC + + Created by Patrick Linstruth (patrick@deltecent.com) + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + PETER SCHORN BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + Except as contained in this notice, the name of Patrick Linstruth shall not + be used in advertising or otherwise to promote the sale, use or other dealings + in this Software without prior written authorization from Patrick Linstruth. + + Devices: + + JAIR - ROM and SD Card + JAIRS0 - COM1 + JAIRS1 - COM2 + JAIRP - Printer Port + + The serial and printer ports support TMXR which allow these + ports to be attached to real serial ports and sockets. If no TMXR + interfaces are attached, JAIRS0 will use the SIMH console for + both input and output, JAIRS1 and JAIRP will use the SIMH console + for output. +*/ + +#include "altairz80_defs.h" +#include "sim_imd.h" +#include "sim_tmxr.h" + +/********/ +/* SIMH */ +/********/ + +extern uint32 sim_map_resource(uint32 baseaddr, uint32 size, uint32 resource_type, + int32 (*routine)(const int32, const int32, const int32), const char* name, uint8 unmap); +extern t_stat set_dev_enbdis(DEVICE *dptr, UNIT *uptr, int32 flag, CONST char *cptr); +extern t_stat set_cmd(int32 flag, CONST char *cptr); +extern void PutBYTEWrapper(const uint32 Addr, const uint32 Value); +extern uint32 nmiInterrupt; + +/* Debug flags */ +#define VERBOSE_MSG (1 << 0) +#define ERROR_MSG (1 << 1) +#define STATUS_MSG (1 << 2) + +/* Debug Flags */ +static DEBTAB jair_dt[] = { + { "VERBOSE", VERBOSE_MSG, "Verbose messages" }, + { "ERROR", ERROR_MSG, "Error messages" }, + { "STATUS", STATUS_MSG, "Status messages" }, + { NULL, 0 } +}; + +/*****************************/ +/* Local function prototypes */ +/*****************************/ + +static t_stat jair_reset(DEVICE *dptr); +static t_stat jair_port_reset(DEVICE *dptr); +static t_stat jair_svc(UNIT *uptr); +static t_stat jair_help(FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr); +static t_stat jair_boot(int32 unitno, DEVICE *dptr); +static t_stat jair_attach(UNIT *uptr, CONST char *cptr); +static t_stat jair_detach(UNIT *uptr); +static t_stat jair_attach_mux(UNIT *uptr, CONST char *cptr); +static t_stat jair_detach_mux(UNIT *uptr); +static const char* jair_description(DEVICE *dptr); +static t_stat jair_config_line(DEVICE *dev, TMLN *tmln, int baud); +static const char* jairs0_description(DEVICE *dptr); +static const char* jairs1_description(DEVICE *dptr); +static const char* jairp_description(DEVICE *dptr); +static int jair_set_mc(TMLN *tmln, uint8 data); +static int jair_new_baud(UNIT *uptr); +static t_stat jair_set_baud(UNIT *uptr, int32 value, const char *cptr, void *desc); +static t_stat jair_show_baud(FILE *st, UNIT *uptr, int32 value, const void *desc); +static t_stat jair_show_ports(FILE *st, UNIT *uptr, int32 val, CONST void *desc); +static int32 jairio(int32 addr, int32 rw, int32 data); +static uint8 jair_io_in(uint32 addr); +static uint8 jair_io_out(uint32 addr, int32 data); +static t_stat jair_set_rom(UNIT *uptr, int32 value, CONST char *cptr, void *desc); +static t_stat jair_set_norom(UNIT *uptr, int32 value, CONST char *cptr, void *desc); +static int32 jair_shadow_rom(int32 Addr, int32 rw, int32 data); + +/***********/ +/* RAM/ROM */ +/***********/ + +#define JAIR_ROM_BASE 0x0000 +#define JAIR_ROM_SIZE 8192 +#define JAIR_ROM_MASK (JAIR_ROM_SIZE-1) + +#define JAIR_ROM_READ FALSE +#define JAIR_ROM_WRITE TRUE + +static uint8 jair_rom_v25[JAIR_ROM_SIZE] = { + 0x3e, 0x02, 0x21, 0x00, 0x00, 0x01, 0x01, 0x00, + 0x09, 0xd2, 0x08, 0x00, 0x3d, 0xc2, 0x02, 0x00, + 0x3e, 0x80, 0xd3, 0x23, 0xd3, 0x2b, 0x3e, 0x0c, + 0xd3, 0x20, 0xd3, 0x28, 0x3e, 0x00, 0xd3, 0x21, + 0xd3, 0x29, 0x3e, 0x03, 0xd3, 0x23, 0xd3, 0x2b, + 0xd3, 0x24, 0xd3, 0x2c, 0xdb, 0x20, 0x21, 0x34, + 0x00, 0xc3, 0xa4, 0x04, 0x0d, 0x0a, 0x41, 0x4c, + 0x54, 0x41, 0x49, 0x52, 0x2f, 0x49, 0x4d, 0x53, + 0x41, 0x49, 0x20, 0x38, 0x30, 0x38, 0x30, 0x20, + 0x43, 0x50, 0x55, 0x20, 0x42, 0x4f, 0x41, 0x52, + 0x44, 0x20, 0x42, 0x4f, 0x4f, 0x54, 0x20, 0x4c, + 0x4f, 0x41, 0x44, 0x45, 0x52, 0x20, 0x2d, 0x20, + 0x4a, 0x6f, 0x73, 0x68, 0x20, 0x42, 0x65, 0x6e, + 0x73, 0x61, 0x64, 0x6f, 0x6e, 0x20, 0x76, 0x32, + 0x2e, 0x35, 0x20, 0x53, 0x65, 0x70, 0x20, 0x33, + 0x2c, 0x20, 0x32, 0x30, 0x31, 0x38, 0x0d, 0x0a, + 0x3c, 0x44, 0x3e, 0x20, 0x2d, 0x53, 0x44, 0x20, + 0x43, 0x61, 0x72, 0x64, 0x20, 0x44, 0x69, 0x72, + 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x0d, 0x0a, + 0x3c, 0x52, 0x3e, 0x20, 0x2d, 0x52, 0x41, 0x4d, + 0x20, 0x54, 0x65, 0x73, 0x74, 0x0d, 0x0a, 0x3c, + 0x56, 0x3e, 0x20, 0x2d, 0x56, 0x69, 0x65, 0x77, + 0x20, 0x4c, 0x6f, 0x61, 0x64, 0x0d, 0x0a, 0x3e, + 0x20, 0x00, 0xaf, 0x32, 0x24, 0xfd, 0x01, 0x03, + 0x00, 0x1e, 0x05, 0x21, 0x00, 0x00, 0xdb, 0x25, + 0xe6, 0x01, 0xca, 0xd2, 0x00, 0xdb, 0x20, 0xc3, + 0xe4, 0x00, 0xdb, 0x00, 0xe6, 0x02, 0xca, 0x03, + 0x01, 0xdb, 0x01, 0xb7, 0xca, 0x03, 0x01, 0xfe, + 0xff, 0xca, 0x03, 0x01, 0xd3, 0x20, 0xd3, 0x01, + 0xfe, 0x1b, 0xca, 0xb6, 0x04, 0xfe, 0x20, 0xca, + 0x07, 0x01, 0xe6, 0x5f, 0xfe, 0x44, 0xca, 0x1c, + 0x01, 0xfe, 0x52, 0xca, 0xcc, 0x01, 0xfe, 0x56, + 0xca, 0x14, 0x01, 0x09, 0xd2, 0xc6, 0x00, 0x3e, + 0x2e, 0xd3, 0x20, 0xd3, 0x01, 0x1d, 0xc2, 0xc3, + 0x00, 0xc3, 0xb6, 0x04, 0x3e, 0x01, 0x32, 0x24, + 0xfd, 0xc3, 0xc1, 0x00, 0x31, 0x00, 0xfd, 0xcd, + 0x90, 0x07, 0x0d, 0x0a, 0x49, 0x4e, 0x49, 0x54, + 0x5f, 0x46, 0x41, 0x54, 0x20, 0x00, 0xcd, 0xd8, + 0x09, 0xcd, 0x90, 0x07, 0x0d, 0x0a, 0x44, 0x49, + 0x52, 0x45, 0x43, 0x54, 0x4f, 0x52, 0x59, 0x3a, + 0x0d, 0x0a, 0x00, 0xcd, 0xe9, 0x07, 0xca, 0x87, + 0x01, 0x7e, 0xfe, 0x21, 0xfa, 0x81, 0x01, 0xfe, + 0x7f, 0xf2, 0x81, 0x01, 0xe5, 0x01, 0x1a, 0x00, + 0x09, 0x7e, 0x23, 0xb6, 0xe1, 0xca, 0x81, 0x01, + 0xcd, 0xaf, 0x0d, 0x3a, 0x35, 0xfd, 0xfe, 0x40, + 0xfa, 0x71, 0x01, 0xcd, 0x90, 0x07, 0x0d, 0x0a, + 0x00, 0x3a, 0x35, 0xfd, 0xe6, 0x0f, 0xca, 0x81, + 0x01, 0x3e, 0x20, 0xcd, 0xc3, 0x07, 0xc3, 0x71, + 0x01, 0xcd, 0xff, 0x07, 0xc3, 0x46, 0x01, 0xcd, + 0x90, 0x07, 0x0d, 0x0a, 0x45, 0x4e, 0x54, 0x45, + 0x52, 0x20, 0x38, 0x2e, 0x33, 0x20, 0x46, 0x49, + 0x4c, 0x45, 0x20, 0x4e, 0x41, 0x4d, 0x45, 0x3e, + 0x20, 0x00, 0x21, 0x6d, 0xfd, 0x06, 0x0b, 0x3e, + 0x20, 0xcd, 0x51, 0x0e, 0x0e, 0x2e, 0x06, 0x08, + 0xcd, 0x89, 0x0d, 0xda, 0x87, 0x01, 0xfe, 0x0d, + 0xca, 0xc3, 0x01, 0x21, 0x75, 0xfd, 0x06, 0x03, + 0xcd, 0x89, 0x0d, 0xcd, 0x90, 0x07, 0x0d, 0x0a, + 0x00, 0xc3, 0x0d, 0x05, 0x21, 0x00, 0x00, 0x01, + 0x01, 0x00, 0x09, 0xd2, 0xd2, 0x01, 0x21, 0xdc, + 0x01, 0xc3, 0xa4, 0x04, 0x0d, 0x0a, 0x54, 0x65, + 0x73, 0x74, 0x69, 0x6e, 0x67, 0x20, 0x53, 0x59, + 0x53, 0x54, 0x45, 0x4d, 0x20, 0x52, 0x41, 0x4d, + 0x20, 0x40, 0x46, 0x30, 0x30, 0x30, 0x2d, 0x46, + 0x46, 0x46, 0x46, 0x0d, 0x0a, 0x52, 0x41, 0x4d, + 0x20, 0x50, 0x41, 0x47, 0x45, 0x20, 0x4d, 0x41, + 0x52, 0x43, 0x48, 0x00, 0x1e, 0xff, 0x21, 0x00, + 0xf0, 0x7b, 0x2f, 0x77, 0x2c, 0xc2, 0x13, 0x02, + 0x7c, 0x24, 0xfe, 0xff, 0xc2, 0x11, 0x02, 0x16, + 0xf0, 0x62, 0x3e, 0x2e, 0xd3, 0x20, 0xd3, 0x01, + 0x7a, 0x2f, 0xd3, 0xff, 0x73, 0x2c, 0xc2, 0x2c, + 0x02, 0x21, 0x00, 0xf0, 0x7c, 0xba, 0x7b, 0xca, + 0x3b, 0x02, 0x2f, 0xbe, 0xc2, 0x26, 0x04, 0x2c, + 0xc2, 0x3b, 0x02, 0x7c, 0x24, 0xfe, 0xff, 0xc2, + 0x34, 0x02, 0x62, 0x7b, 0x2f, 0x77, 0x2c, 0xc2, + 0x4d, 0x02, 0x7a, 0x14, 0xfe, 0xff, 0xc2, 0x21, + 0x02, 0x1c, 0xca, 0x0e, 0x02, 0x21, 0x63, 0x02, + 0xc3, 0xa4, 0x04, 0x50, 0x41, 0x53, 0x53, 0x45, + 0x44, 0x0d, 0x0a, 0x52, 0x41, 0x4d, 0x20, 0x42, + 0x59, 0x54, 0x45, 0x20, 0x4d, 0x41, 0x52, 0x43, + 0x48, 0x20, 0x41, 0x00, 0x05, 0xc2, 0x7c, 0x02, + 0x1e, 0xff, 0x26, 0xf0, 0x2e, 0x00, 0x7c, 0x2f, + 0xd3, 0xff, 0x3e, 0x2e, 0xd3, 0x20, 0xd3, 0x01, + 0x7b, 0x2f, 0x77, 0x2c, 0xc2, 0x92, 0x02, 0x16, + 0x00, 0x6a, 0x7b, 0x77, 0x2f, 0x2e, 0x00, 0xbe, + 0xca, 0xaf, 0x02, 0x2f, 0xbe, 0xc2, 0x26, 0x04, + 0x7d, 0xba, 0xc2, 0x26, 0x04, 0x7b, 0x2f, 0x2c, + 0xc2, 0x9f, 0x02, 0x6a, 0x7b, 0x2f, 0x77, 0x14, + 0xc2, 0x99, 0x02, 0x7c, 0x24, 0xfe, 0xff, 0xc2, + 0x84, 0x02, 0x1c, 0xca, 0x82, 0x02, 0x21, 0xcc, + 0x02, 0xc3, 0xa4, 0x04, 0x50, 0x41, 0x53, 0x53, + 0x45, 0x44, 0x0d, 0x0a, 0x52, 0x41, 0x4d, 0x20, + 0x42, 0x59, 0x54, 0x45, 0x20, 0x4d, 0x41, 0x52, + 0x43, 0x48, 0x20, 0x42, 0x00, 0x1e, 0xff, 0x16, + 0x00, 0x21, 0x00, 0xf0, 0x7b, 0x2f, 0x77, 0x2c, + 0xc2, 0xee, 0x02, 0x7c, 0x24, 0xfe, 0xff, 0xc2, + 0xec, 0x02, 0x7a, 0x2f, 0xd3, 0xff, 0xe6, 0x0f, + 0xc2, 0x09, 0x03, 0x3e, 0x2e, 0xd3, 0x20, 0xd3, + 0x01, 0x26, 0xf0, 0x6a, 0x73, 0x7c, 0x24, 0xfe, + 0xff, 0xc2, 0x0c, 0x03, 0x2e, 0x00, 0x26, 0xf0, + 0x7d, 0xba, 0xca, 0x2d, 0x03, 0x7b, 0x2f, 0xbe, + 0xc2, 0x26, 0x04, 0x7c, 0x24, 0xfe, 0xff, 0xc2, + 0x1d, 0x03, 0xc3, 0x39, 0x03, 0x7b, 0xbe, 0xc2, + 0x26, 0x04, 0x7c, 0x24, 0xfe, 0xff, 0xc2, 0x2d, + 0x03, 0x2c, 0xc2, 0x16, 0x03, 0x26, 0xf0, 0x6a, + 0x7b, 0x2f, 0x77, 0x7c, 0x24, 0xfe, 0xff, 0xc2, + 0x40, 0x03, 0x14, 0xc2, 0xfa, 0x02, 0x1c, 0xca, + 0xe7, 0x02, 0x21, 0x58, 0x03, 0xc3, 0xa4, 0x04, + 0x50, 0x41, 0x53, 0x53, 0x45, 0x44, 0x0d, 0x0a, + 0x52, 0x41, 0x4d, 0x20, 0x42, 0x49, 0x54, 0x20, + 0x4d, 0x41, 0x52, 0x43, 0x48, 0x20, 0x00, 0x1e, + 0x01, 0x21, 0x00, 0xf0, 0x7b, 0x2f, 0xd3, 0xff, + 0x3e, 0x2e, 0xd3, 0x20, 0xd3, 0x01, 0x7b, 0x77, + 0x2c, 0xc2, 0x7f, 0x03, 0x7c, 0x24, 0xfe, 0xff, + 0xc2, 0x7e, 0x03, 0x21, 0x00, 0xf0, 0x7b, 0xbe, + 0xc2, 0x26, 0x04, 0x2c, 0xc2, 0x8f, 0x03, 0x7c, + 0x24, 0xfe, 0xff, 0xc2, 0x8e, 0x03, 0x7b, 0x17, + 0x7b, 0x07, 0x5f, 0xfe, 0x01, 0xc2, 0xad, 0x03, + 0x2f, 0x5f, 0xc3, 0x71, 0x03, 0xfe, 0xfe, 0xc2, + 0x71, 0x03, 0x21, 0xb8, 0x03, 0xc3, 0xa4, 0x04, + 0x50, 0x41, 0x53, 0x53, 0x45, 0x44, 0x0d, 0x0a, + 0x52, 0x41, 0x4d, 0x20, 0x53, 0x45, 0x51, 0x55, + 0x45, 0x4e, 0x43, 0x45, 0x20, 0x54, 0x45, 0x53, + 0x54, 0x00, 0x1e, 0x01, 0x7b, 0xe6, 0x07, 0xc2, + 0xe0, 0x03, 0x3e, 0x2e, 0xd3, 0x20, 0xd3, 0x01, + 0x7b, 0x2f, 0xd3, 0xff, 0x21, 0x00, 0xf0, 0x53, + 0x14, 0xc2, 0xed, 0x03, 0x14, 0x72, 0x2c, 0xc2, + 0xe8, 0x03, 0x7c, 0x24, 0xfe, 0xff, 0xc2, 0xe8, + 0x03, 0x21, 0x00, 0xf0, 0x53, 0x14, 0xc2, 0x02, + 0x04, 0x14, 0x7a, 0xbe, 0xc2, 0x26, 0x04, 0x2c, + 0xc2, 0xfd, 0x03, 0x7c, 0x24, 0xfe, 0xff, 0xc2, + 0xfd, 0x03, 0x1c, 0xc2, 0xd4, 0x03, 0x21, 0x1c, + 0x04, 0xc3, 0xa4, 0x04, 0x50, 0x41, 0x53, 0x53, + 0x45, 0x44, 0x00, 0xc3, 0xb6, 0x04, 0x54, 0x5d, + 0x21, 0x2e, 0x04, 0xc3, 0xa4, 0x04, 0x0d, 0x0a, + 0x46, 0x41, 0x49, 0x4c, 0x45, 0x44, 0x20, 0x41, + 0x54, 0x3a, 0x00, 0x7a, 0x0f, 0x0f, 0x0f, 0x0f, + 0xe6, 0x0f, 0xc6, 0x90, 0x27, 0xce, 0x40, 0x27, + 0x05, 0xc2, 0x48, 0x04, 0xd3, 0x20, 0xd3, 0x01, + 0x7a, 0xe6, 0x0f, 0xc6, 0x90, 0x27, 0xce, 0x40, + 0x27, 0x05, 0xc2, 0x59, 0x04, 0xd3, 0x20, 0xd3, + 0x01, 0x7b, 0x0f, 0x0f, 0x0f, 0x0f, 0xe6, 0x0f, + 0xc6, 0x90, 0x27, 0xce, 0x40, 0x27, 0x05, 0xc2, + 0x6e, 0x04, 0xd3, 0x20, 0xd3, 0x01, 0x7b, 0xe6, + 0x0f, 0xc6, 0x90, 0x27, 0xce, 0x40, 0x27, 0x05, + 0xc2, 0x7f, 0x04, 0xd3, 0x20, 0xd3, 0x01, 0x21, + 0x8d, 0x04, 0xc3, 0xa4, 0x04, 0x20, 0x2d, 0x20, + 0x53, 0x59, 0x53, 0x54, 0x45, 0x4d, 0x20, 0x48, + 0x41, 0x4c, 0x54, 0x45, 0x44, 0x0d, 0x0a, 0x00, + 0x76, 0xc3, 0xa0, 0x04, 0x7e, 0x23, 0xb7, 0xc2, + 0xab, 0x04, 0xe9, 0x05, 0xc2, 0xab, 0x04, 0xd3, + 0x20, 0xd3, 0x01, 0xc3, 0xa4, 0x04, 0x31, 0x00, + 0xfd, 0xcd, 0x90, 0x07, 0x0d, 0x0a, 0x42, 0x4f, + 0x4f, 0x54, 0x20, 0x42, 0x49, 0x4f, 0x53, 0x2e, + 0x48, 0x45, 0x58, 0x2c, 0x20, 0x49, 0x4e, 0x49, + 0x54, 0x5f, 0x46, 0x41, 0x54, 0x20, 0x00, 0xcd, + 0xd8, 0x09, 0xcd, 0x90, 0x07, 0x0d, 0x0a, 0x4c, + 0x4f, 0x41, 0x44, 0x49, 0x4e, 0x47, 0x20, 0x46, + 0x49, 0x4c, 0x45, 0x20, 0x00, 0x11, 0x01, 0xfd, + 0xcd, 0x3d, 0x07, 0x42, 0x49, 0x4f, 0x53, 0x20, + 0x20, 0x20, 0x20, 0x48, 0x45, 0x58, 0x00, 0x21, + 0x00, 0xfd, 0x36, 0x00, 0x23, 0x11, 0x6d, 0xfd, + 0x06, 0x0b, 0xcd, 0x43, 0x0e, 0xcd, 0x21, 0x08, + 0xca, 0x1c, 0x01, 0xe5, 0x01, 0x1c, 0x00, 0x09, + 0xcd, 0xe5, 0x0d, 0x21, 0x20, 0xfd, 0xcd, 0xed, + 0x0d, 0xe1, 0x01, 0x1a, 0x00, 0x09, 0xcd, 0x4c, + 0x0e, 0xeb, 0x21, 0x00, 0xfd, 0x36, 0x01, 0x21, + 0x0c, 0xfd, 0x73, 0x23, 0x72, 0x23, 0x06, 0x0e, + 0x3e, 0xff, 0xcd, 0x51, 0x0e, 0xcd, 0x90, 0x07, + 0x0d, 0x0a, 0x46, 0x49, 0x4c, 0x45, 0x20, 0x53, + 0x49, 0x5a, 0x45, 0x3d, 0x30, 0x78, 0x00, 0x2a, + 0x22, 0xfd, 0xcd, 0x61, 0x07, 0x2a, 0x20, 0xfd, + 0xcd, 0x61, 0x07, 0xcd, 0x90, 0x07, 0x0d, 0x0a, + 0x00, 0x21, 0x00, 0x00, 0x22, 0x3e, 0xfd, 0x21, + 0xff, 0xff, 0x22, 0x25, 0xfd, 0x3e, 0x00, 0x32, + 0x34, 0xfd, 0x21, 0xc8, 0x05, 0x22, 0x27, 0xfd, + 0x21, 0x20, 0xfd, 0xcd, 0xe5, 0x0d, 0xcd, 0x13, + 0x0e, 0xca, 0xba, 0x05, 0xcd, 0x0b, 0x0e, 0x21, + 0x20, 0xfd, 0xcd, 0xed, 0x0d, 0x2a, 0x25, 0xfd, + 0x23, 0x7c, 0xb5, 0xc2, 0xa3, 0x05, 0xcd, 0x58, + 0x08, 0x2a, 0x3e, 0xfd, 0x23, 0x22, 0x3e, 0xfd, + 0x21, 0x00, 0xfe, 0x22, 0x25, 0xfd, 0x3a, 0x24, + 0xfd, 0xb7, 0xca, 0xb1, 0x05, 0x7e, 0xcd, 0xc3, + 0x07, 0x7e, 0x21, 0x78, 0x05, 0xe5, 0x2a, 0x27, + 0xfd, 0xe9, 0xcd, 0x90, 0x07, 0x0d, 0x0a, 0x2d, + 0x45, 0x4f, 0x46, 0x2d, 0x00, 0xc3, 0xbe, 0x06, + 0xfe, 0x3a, 0xc0, 0xaf, 0x32, 0x2d, 0xfd, 0x21, + 0x2a, 0x06, 0x22, 0x2a, 0xfd, 0x21, 0xdc, 0x05, + 0x22, 0x27, 0xfd, 0xc9, 0xcd, 0x18, 0x07, 0xda, + 0x08, 0x06, 0x07, 0x07, 0x07, 0x07, 0x32, 0x2c, + 0xfd, 0x21, 0xf0, 0x05, 0x22, 0x27, 0xfd, 0xc9, + 0xcd, 0x18, 0x07, 0xda, 0x08, 0x06, 0x67, 0x3a, + 0x2c, 0xfd, 0xb4, 0x67, 0x3a, 0x2d, 0xfd, 0x84, + 0x32, 0x2d, 0xfd, 0x7c, 0x2a, 0x2a, 0xfd, 0xe9, + 0xcd, 0x90, 0x07, 0x0d, 0x0a, 0x21, 0x21, 0x21, + 0x20, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x2c, 0x20, + 0x4e, 0x4f, 0x54, 0x20, 0x41, 0x20, 0x48, 0x45, + 0x58, 0x20, 0x43, 0x48, 0x41, 0x52, 0x00, 0xc3, + 0x87, 0x04, 0x32, 0x2e, 0xfd, 0x21, 0x33, 0x06, + 0xc3, 0xd2, 0x05, 0x32, 0x30, 0xfd, 0x21, 0x3c, + 0x06, 0xc3, 0xd2, 0x05, 0x32, 0x2f, 0xfd, 0x3a, + 0x34, 0xfd, 0xb7, 0xc2, 0x50, 0x06, 0x3c, 0x32, + 0x34, 0xfd, 0x2a, 0x2f, 0xfd, 0x22, 0x32, 0xfd, + 0x21, 0x56, 0x06, 0xc3, 0xd2, 0x05, 0x32, 0x31, + 0xfd, 0xfe, 0x02, 0xf2, 0x93, 0x06, 0x3a, 0x2e, + 0xfd, 0xb7, 0x21, 0x7d, 0x06, 0xca, 0xd2, 0x05, + 0x3d, 0x32, 0x2e, 0xfd, 0x21, 0x72, 0x06, 0xc3, + 0xd2, 0x05, 0x2a, 0x2f, 0xfd, 0x77, 0x23, 0x22, + 0x2f, 0xfd, 0xc3, 0x5e, 0x06, 0x3a, 0x2d, 0xfd, + 0xb7, 0xc2, 0xa3, 0x06, 0x3a, 0x31, 0xfd, 0xfe, + 0x01, 0xca, 0xbe, 0x06, 0x21, 0xc8, 0x05, 0x22, + 0x27, 0xfd, 0xc9, 0xcd, 0x90, 0x07, 0x2d, 0x49, + 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x64, 0x20, 0x00, + 0xc3, 0x8c, 0x06, 0xcd, 0x90, 0x07, 0x0d, 0x0a, + 0x21, 0x21, 0x21, 0x20, 0x43, 0x48, 0x45, 0x43, + 0x4b, 0x53, 0x55, 0x4d, 0x20, 0x45, 0x52, 0x52, + 0x4f, 0x52, 0x00, 0xc3, 0x87, 0x04, 0x3a, 0x34, + 0xfd, 0xb7, 0xc2, 0xe7, 0x06, 0xcd, 0x90, 0x07, + 0x0d, 0x0a, 0x21, 0x21, 0x21, 0x20, 0x53, 0x54, + 0x41, 0x52, 0x54, 0x20, 0x41, 0x44, 0x44, 0x52, + 0x45, 0x53, 0x53, 0x20, 0x4e, 0x4f, 0x54, 0x20, + 0x53, 0x45, 0x54, 0x00, 0xc3, 0x87, 0x04, 0xcd, + 0x90, 0x07, 0x0d, 0x0a, 0x45, 0x78, 0x65, 0x63, + 0x75, 0x74, 0x65, 0x20, 0x61, 0x74, 0x3a, 0x00, + 0x2a, 0x15, 0x07, 0x22, 0xfd, 0xff, 0x3a, 0x17, + 0x07, 0x32, 0xff, 0xff, 0x2a, 0x32, 0xfd, 0xcd, + 0x61, 0x07, 0xcd, 0x90, 0x07, 0x0d, 0x0a, 0x00, + 0x3e, 0x01, 0xc3, 0xfd, 0xff, 0xd3, 0x38, 0xe9, + 0xfe, 0x30, 0xfa, 0x36, 0x07, 0xfe, 0x3a, 0xfa, + 0x3a, 0x07, 0xfe, 0x41, 0xfa, 0x36, 0x07, 0xfe, + 0x47, 0xfa, 0x38, 0x07, 0xfe, 0x61, 0xfa, 0x36, + 0x07, 0xfe, 0x67, 0xfa, 0x38, 0x07, 0x37, 0xc9, + 0xd6, 0x07, 0xe6, 0x0f, 0xc9, 0xe3, 0x7e, 0x23, + 0xb7, 0xca, 0x49, 0x07, 0x12, 0x13, 0xc3, 0x3e, + 0x07, 0xe3, 0xc9, 0xf5, 0x78, 0xcd, 0x6c, 0x07, + 0x79, 0xcd, 0x6c, 0x07, 0xf1, 0xc9, 0xf5, 0x7a, + 0xcd, 0x6c, 0x07, 0x7b, 0xcd, 0x6c, 0x07, 0xf1, + 0xc9, 0xf5, 0x7c, 0xcd, 0x6c, 0x07, 0x7d, 0xcd, + 0x6c, 0x07, 0xf1, 0xc9, 0xf5, 0x0f, 0x0f, 0x0f, + 0x0f, 0xcd, 0x7b, 0x07, 0xf1, 0xf5, 0xcd, 0x7b, + 0x07, 0xf1, 0xc9, 0xe6, 0x0f, 0xc6, 0x90, 0x27, + 0xce, 0x40, 0x27, 0xc3, 0xc3, 0x07, 0x7e, 0x23, + 0xb7, 0xc8, 0xcd, 0xc3, 0x07, 0xc3, 0x86, 0x07, + 0xe3, 0xf5, 0xcd, 0x86, 0x07, 0xf1, 0xe3, 0xc9, + 0x7e, 0xcd, 0xc3, 0x07, 0x23, 0x05, 0xc2, 0x98, + 0x07, 0xc9, 0xdb, 0x25, 0xe6, 0x01, 0xca, 0xae, + 0x07, 0xdb, 0x20, 0xc3, 0xc0, 0x07, 0xdb, 0x00, + 0xe6, 0x02, 0xca, 0xa2, 0x07, 0xdb, 0x01, 0xb7, + 0xca, 0xa2, 0x07, 0xfe, 0xff, 0xca, 0xa2, 0x07, + 0xfe, 0x20, 0xf8, 0xf5, 0xfe, 0x0d, 0xca, 0xe2, + 0x07, 0xfe, 0x20, 0xfa, 0xd5, 0x07, 0x3a, 0x35, + 0xfd, 0x3c, 0x32, 0x35, 0xfd, 0xdb, 0x25, 0xe6, + 0x20, 0xca, 0xd5, 0x07, 0xf1, 0xd3, 0x20, 0xd3, + 0x01, 0xc9, 0xaf, 0x32, 0x35, 0xfd, 0xc3, 0xd5, + 0x07, 0x21, 0x65, 0xfd, 0xcd, 0xe5, 0x0d, 0x2a, + 0x55, 0xfd, 0x22, 0x7d, 0xfd, 0xb7, 0xcd, 0x98, + 0x0b, 0x21, 0x00, 0xfe, 0xaf, 0xbe, 0xc9, 0x01, + 0x20, 0x00, 0x09, 0xd2, 0xfc, 0x07, 0xaf, 0x2a, + 0x7d, 0xfd, 0x01, 0xf0, 0xff, 0x09, 0x22, 0x7d, + 0xfd, 0xd0, 0x7c, 0xb5, 0xc8, 0x21, 0x78, 0xfd, + 0xcd, 0xe5, 0x0d, 0xcd, 0x05, 0x0e, 0xc3, 0xf6, + 0x07, 0x21, 0x6d, 0xfd, 0xcd, 0xaf, 0x0d, 0xcd, + 0x4a, 0x08, 0xc2, 0x3d, 0x08, 0xcd, 0x90, 0x07, + 0x20, 0x2d, 0x4e, 0x4f, 0x54, 0x20, 0x46, 0x4f, + 0x55, 0x4e, 0x44, 0x00, 0xc9, 0xcd, 0x90, 0x07, + 0x20, 0x2d, 0x45, 0x58, 0x49, 0x53, 0x54, 0x53, + 0x00, 0xc9, 0xcd, 0xe9, 0x07, 0xc8, 0xcd, 0xab, + 0x09, 0xc0, 0xcd, 0xff, 0x07, 0xc3, 0x4d, 0x08, + 0x21, 0x00, 0xfd, 0x7e, 0xb7, 0xc2, 0x80, 0x08, + 0xcd, 0xff, 0x04, 0x3a, 0x00, 0xfd, 0xb7, 0xc2, + 0x80, 0x08, 0xcd, 0x90, 0x07, 0x20, 0x2d, 0x44, + 0x69, 0x73, 0x6b, 0x20, 0x4e, 0x6f, 0x74, 0x20, + 0x4c, 0x6f, 0x61, 0x64, 0x65, 0x64, 0x00, 0xc9, + 0x21, 0x12, 0xfd, 0x5e, 0x23, 0x56, 0x2a, 0x3e, + 0xfd, 0xcd, 0x36, 0x0e, 0xc2, 0x98, 0x08, 0x21, + 0x18, 0xfd, 0xcd, 0xe5, 0x0d, 0xc3, 0xa4, 0x09, + 0xeb, 0x21, 0x12, 0xfd, 0x73, 0x23, 0x72, 0x2a, + 0x36, 0xfd, 0xcd, 0x5e, 0x0e, 0x21, 0x0e, 0xfd, + 0xe5, 0xcd, 0x4c, 0x0e, 0x44, 0x4d, 0xe1, 0x7a, + 0xb8, 0xc2, 0xb9, 0x08, 0x7b, 0xb9, 0xca, 0x88, + 0x09, 0xd2, 0xc4, 0x08, 0x01, 0x00, 0x00, 0x2b, + 0x2b, 0xc3, 0xcc, 0x08, 0x7b, 0x91, 0x5f, 0x7a, + 0x98, 0x57, 0x23, 0x23, 0xcd, 0x4c, 0x0e, 0x7a, + 0xb3, 0xca, 0x37, 0x09, 0x23, 0x7c, 0xb5, 0xc2, + 0x06, 0x09, 0xcd, 0x90, 0x07, 0x20, 0x2d, 0x45, + 0x52, 0x52, 0x4f, 0x52, 0x2c, 0x20, 0x4e, 0x4f, + 0x20, 0x4d, 0x4f, 0x52, 0x45, 0x20, 0x41, 0x4c, + 0x4c, 0x4f, 0x43, 0x41, 0x54, 0x45, 0x44, 0x20, + 0x43, 0x4c, 0x55, 0x53, 0x54, 0x45, 0x52, 0x53, + 0x21, 0x00, 0x76, 0xc3, 0x02, 0x09, 0x2b, 0xc5, + 0xd5, 0xe5, 0x5c, 0x2a, 0x61, 0xfd, 0x7d, 0x83, + 0x5f, 0x7c, 0xce, 0x00, 0x57, 0x2a, 0x63, 0xfd, + 0xd2, 0x1c, 0x09, 0x23, 0x44, 0x4d, 0xcd, 0x98, + 0x0b, 0xd1, 0x21, 0x00, 0xfe, 0xb7, 0x7b, 0x17, + 0x6f, 0x7c, 0xce, 0x00, 0x67, 0xcd, 0x4c, 0x0e, + 0xd1, 0xc1, 0x03, 0x1b, 0xc3, 0xcf, 0x08, 0xeb, + 0x21, 0x0e, 0xfd, 0x71, 0x23, 0x70, 0x23, 0x73, + 0x23, 0x72, 0xeb, 0x2b, 0x2b, 0x01, 0x00, 0x00, + 0x11, 0x00, 0x00, 0x3e, 0x08, 0x32, 0x3a, 0xfd, + 0x3a, 0x51, 0xfd, 0x1f, 0x32, 0x39, 0xfd, 0xd2, + 0x60, 0x09, 0xeb, 0x19, 0xeb, 0x79, 0x88, 0x4f, + 0x29, 0x78, 0x17, 0x47, 0x3a, 0x3a, 0xfd, 0x3d, + 0x32, 0x3a, 0xfd, 0x3a, 0x39, 0xfd, 0xc2, 0x53, + 0x09, 0x06, 0x00, 0x2a, 0x69, 0xfd, 0x19, 0xeb, + 0x2a, 0x6b, 0xfd, 0xd2, 0x7f, 0x09, 0x03, 0x09, + 0xe5, 0xc1, 0x21, 0x14, 0xfd, 0xcd, 0xed, 0x0d, + 0x21, 0x12, 0xfd, 0x5e, 0x23, 0x56, 0x2a, 0x3b, + 0xfd, 0xcd, 0x5e, 0x0e, 0x21, 0x14, 0xfd, 0x01, + 0x00, 0x00, 0x16, 0x00, 0x5f, 0xcd, 0xf5, 0x0d, + 0x23, 0xcd, 0xed, 0x0d, 0xcd, 0x98, 0x0b, 0x21, + 0x00, 0xfe, 0xc9, 0xe5, 0x06, 0x08, 0x11, 0x6d, + 0xfd, 0x1a, 0xbe, 0xc2, 0xd5, 0x09, 0x23, 0x13, + 0x05, 0xc2, 0xb1, 0x09, 0xe1, 0xe5, 0x11, 0x08, + 0x00, 0x19, 0x06, 0x03, 0x11, 0x75, 0xfd, 0x1a, + 0xbe, 0xc2, 0xd5, 0x09, 0x23, 0x13, 0x05, 0xc2, + 0xc7, 0x09, 0x04, 0xe1, 0xc9, 0xaf, 0xe1, 0xc9, + 0xcd, 0x06, 0x0c, 0xc0, 0xcd, 0x90, 0x07, 0x4d, + 0x42, 0x52, 0x00, 0x01, 0x00, 0x00, 0x11, 0x00, + 0x00, 0x37, 0xcd, 0x98, 0x0b, 0xcd, 0x83, 0x0b, + 0xc0, 0xcd, 0x90, 0x07, 0x20, 0x54, 0x79, 0x70, + 0x65, 0x00, 0x3a, 0xc2, 0xff, 0xcd, 0x6c, 0x07, + 0x32, 0x46, 0xfd, 0xfe, 0x04, 0xca, 0x12, 0x0a, + 0xfe, 0x06, 0xca, 0x12, 0x0a, 0xfe, 0x86, 0xc2, + 0x6d, 0x0b, 0x21, 0xc6, 0xff, 0x11, 0x47, 0xfd, + 0x06, 0x08, 0xcd, 0x43, 0x0e, 0xcd, 0x90, 0x07, + 0x20, 0x50, 0x42, 0x52, 0x00, 0x21, 0x47, 0xfd, + 0xcd, 0xe5, 0x0d, 0xcd, 0x98, 0x0b, 0xcd, 0x83, + 0x0b, 0xc0, 0x21, 0x0b, 0xfe, 0x11, 0x4f, 0xfd, + 0x06, 0x0a, 0xcd, 0x43, 0x0e, 0xeb, 0x2b, 0x2b, + 0x7e, 0x23, 0xb6, 0xc2, 0x51, 0x0a, 0x2b, 0xeb, + 0x21, 0x20, 0xfe, 0xcd, 0x41, 0x0e, 0xc3, 0x58, + 0x0a, 0xaf, 0x23, 0x77, 0x23, 0x77, 0x23, 0xeb, + 0x21, 0x1c, 0xfe, 0xcd, 0x41, 0x0e, 0x21, 0x16, + 0xfe, 0xcd, 0x3c, 0x0e, 0x2a, 0x52, 0xfd, 0xeb, + 0x2a, 0x47, 0xfd, 0x19, 0x22, 0x61, 0xfd, 0x2a, + 0x49, 0xfd, 0xd2, 0x76, 0x0a, 0x23, 0x22, 0x63, + 0xfd, 0x3a, 0x54, 0xfd, 0x47, 0x2a, 0x5f, 0xfd, + 0xeb, 0x21, 0x00, 0x00, 0x19, 0x05, 0xc2, 0x84, + 0x0a, 0xeb, 0x2a, 0x61, 0xfd, 0x19, 0x22, 0x65, + 0xfd, 0x2a, 0x63, 0xfd, 0xd2, 0x98, 0x0a, 0x23, + 0x22, 0x67, 0xfd, 0x06, 0x10, 0x2a, 0x4f, 0xfd, + 0xeb, 0x2a, 0x55, 0xfd, 0x7b, 0x1f, 0xda, 0xd3, + 0x0a, 0x7d, 0x1f, 0xda, 0xd3, 0x0a, 0x7a, 0x1f, + 0x57, 0x7b, 0x1f, 0x5f, 0x7c, 0x1f, 0x67, 0x7d, + 0x1f, 0x6f, 0x05, 0xc2, 0xa4, 0x0a, 0xcd, 0x90, + 0x07, 0x20, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x20, + 0x44, 0x41, 0x54, 0x41, 0x53, 0x54, 0x41, 0x52, + 0x54, 0x00, 0xc9, 0x06, 0x05, 0x29, 0xda, 0xbe, + 0x0a, 0x05, 0xc2, 0xd5, 0x0a, 0x7b, 0x2f, 0x4f, + 0x7a, 0x2f, 0x47, 0x03, 0x11, 0xff, 0xff, 0x09, + 0x13, 0xda, 0xe7, 0x0a, 0x2a, 0x65, 0xfd, 0x19, + 0x22, 0x69, 0xfd, 0x2a, 0x67, 0xfd, 0xd2, 0xfa, + 0x0a, 0x23, 0x22, 0x6b, 0xfd, 0x3a, 0x51, 0xfd, + 0x3d, 0x32, 0x3d, 0xfd, 0x3c, 0xca, 0x57, 0x0b, + 0x01, 0x00, 0x08, 0x1f, 0xd2, 0x11, 0x0b, 0x50, + 0x0c, 0x05, 0xc2, 0x0b, 0x0b, 0x3e, 0x01, 0xb9, + 0xc2, 0x2b, 0x0b, 0x7a, 0x2f, 0xc6, 0x0a, 0x32, + 0x38, 0xfd, 0x21, 0x7b, 0x0e, 0x11, 0x8b, 0x0e, + 0xc3, 0x30, 0x0b, 0x21, 0x5f, 0x0e, 0xe5, 0xd1, + 0x22, 0x36, 0xfd, 0xeb, 0x22, 0x3b, 0xfd, 0xcd, + 0x90, 0x07, 0x20, 0x56, 0x4f, 0x4c, 0x3d, 0x00, + 0x21, 0x2b, 0xfe, 0x06, 0x0b, 0xcd, 0x98, 0x07, + 0xcd, 0x90, 0x07, 0x20, 0x53, 0x59, 0x53, 0x3d, + 0x00, 0x06, 0x08, 0xcd, 0x98, 0x07, 0xc9, 0xcd, + 0x90, 0x07, 0x0d, 0x0a, 0x45, 0x72, 0x72, 0x6f, + 0x72, 0x3d, 0x30, 0x20, 0x53, 0x65, 0x63, 0x2f, + 0x43, 0x6c, 0x75, 0x73, 0x00, 0xcd, 0x90, 0x07, + 0x0d, 0x0a, 0x46, 0x41, 0x54, 0x20, 0x49, 0x6e, + 0x69, 0x74, 0x20, 0x46, 0x41, 0x49, 0x4c, 0x45, + 0x44, 0x00, 0xc9, 0xcd, 0x90, 0x07, 0x20, 0x53, + 0x00, 0x2b, 0x3e, 0xaa, 0xbe, 0xc2, 0x6d, 0x0b, + 0x2b, 0x3e, 0x55, 0xbe, 0xc2, 0x6d, 0x0b, 0xc9, + 0x21, 0x78, 0xfd, 0xda, 0xa2, 0x0b, 0xcd, 0x1a, + 0x0e, 0xc8, 0x21, 0x78, 0xfd, 0xcd, 0xed, 0x0d, + 0xcd, 0xeb, 0x0b, 0x06, 0x05, 0x3e, 0x11, 0xcd, + 0x0b, 0x0d, 0xca, 0xbe, 0x0b, 0x05, 0xc2, 0xad, + 0x0b, 0x05, 0xcd, 0xf3, 0x0c, 0xc9, 0x06, 0x00, + 0xcd, 0x51, 0x0d, 0xfe, 0xfe, 0xca, 0xd0, 0x0b, + 0x05, 0xc2, 0xc0, 0x0b, 0xcd, 0xf3, 0x0c, 0xc9, + 0x01, 0x00, 0x02, 0xcd, 0x51, 0x0d, 0x77, 0x23, + 0x0d, 0xc2, 0xd3, 0x0b, 0x05, 0xc2, 0xd3, 0x0b, + 0xcd, 0x51, 0x0d, 0xcd, 0x51, 0x0d, 0xcd, 0xf3, + 0x0c, 0xaf, 0xc9, 0x3a, 0x40, 0xfd, 0xfe, 0x03, + 0xca, 0xfc, 0x0b, 0x79, 0xeb, 0x29, 0x17, 0x47, + 0x4c, 0x55, 0x1e, 0x00, 0x21, 0x42, 0xfd, 0xcd, + 0xed, 0x0d, 0x21, 0x00, 0xfe, 0xc9, 0xcd, 0xf3, + 0x0c, 0x0e, 0x80, 0x3e, 0xff, 0x32, 0x40, 0xfd, + 0xd3, 0x30, 0x0d, 0xc2, 0x10, 0x0c, 0xcd, 0xfa, + 0x0c, 0xcd, 0x90, 0x07, 0x0d, 0x0a, 0x49, 0x6e, + 0x69, 0x74, 0x20, 0x53, 0x44, 0x00, 0xcd, 0x7b, + 0x0d, 0x06, 0x00, 0x3e, 0x00, 0xcd, 0x0b, 0x0d, + 0xfe, 0x01, 0xca, 0x4a, 0x0c, 0x05, 0xc2, 0x2b, + 0x0c, 0xcd, 0x90, 0x07, 0x2d, 0x46, 0x41, 0x49, + 0x4c, 0x45, 0x44, 0x00, 0xcd, 0xf3, 0x0c, 0xaf, + 0x3d, 0xc9, 0xcd, 0x90, 0x07, 0x20, 0x54, 0x79, + 0x70, 0x65, 0x23, 0x00, 0x21, 0xaa, 0x01, 0x22, + 0x42, 0xfd, 0x3e, 0x08, 0xcd, 0x0b, 0x0d, 0xe6, + 0x04, 0xca, 0x6c, 0x0c, 0x3e, 0x01, 0x32, 0x40, + 0xfd, 0xc3, 0x87, 0x0c, 0xcd, 0x51, 0x0d, 0xcd, + 0x51, 0x0d, 0xcd, 0x51, 0x0d, 0xcd, 0x51, 0x0d, + 0x32, 0x41, 0xfd, 0xfe, 0xaa, 0x3e, 0xaa, 0xc2, + 0x39, 0x0c, 0x3e, 0x02, 0x32, 0x40, 0xfd, 0xcd, + 0x7b, 0x07, 0xcd, 0x90, 0x07, 0x20, 0x41, 0x43, + 0x4d, 0x44, 0x34, 0x31, 0x00, 0xcd, 0x7b, 0x0d, + 0x06, 0x00, 0x3e, 0x37, 0xcd, 0x0b, 0x0d, 0x3e, + 0x29, 0xcd, 0x0b, 0x0d, 0xfe, 0x00, 0xca, 0xb4, + 0x0c, 0xaf, 0xcd, 0x06, 0x0d, 0x05, 0xc2, 0x9a, + 0x0c, 0xc3, 0x39, 0x0c, 0xcd, 0x90, 0x07, 0x2b, + 0x00, 0x3a, 0x40, 0xfd, 0xfe, 0x02, 0xc2, 0xee, + 0x0c, 0x3e, 0x3a, 0xcd, 0x0b, 0x0d, 0xfe, 0x00, + 0xc2, 0x39, 0x0c, 0xcd, 0x51, 0x0d, 0xe6, 0xc0, + 0xfe, 0xc0, 0xc2, 0xe5, 0x0c, 0x3e, 0x03, 0x32, + 0x40, 0xfd, 0xcd, 0x90, 0x07, 0x20, 0x54, 0x79, + 0x70, 0x65, 0x23, 0x33, 0x00, 0xcd, 0x51, 0x0d, + 0xcd, 0x51, 0x0d, 0xcd, 0x51, 0x0d, 0xcd, 0xf3, + 0x0c, 0xaf, 0xc9, 0xf5, 0x3e, 0x01, 0xd3, 0x31, + 0xf1, 0xc9, 0xf5, 0x3e, 0x00, 0xd3, 0x31, 0xcd, + 0x04, 0x0d, 0xf1, 0xc9, 0x3e, 0x0d, 0x3d, 0xc2, + 0x06, 0x0d, 0xc9, 0xc5, 0xcd, 0xfa, 0x0c, 0xcd, + 0x59, 0x0d, 0x06, 0xff, 0xfe, 0x00, 0xc2, 0x1b, + 0x0d, 0x06, 0x95, 0xfe, 0x08, 0xc2, 0x22, 0x0d, + 0x06, 0x87, 0xf6, 0x40, 0xd3, 0x30, 0x3a, 0x45, + 0xfd, 0xd3, 0x30, 0x3a, 0x44, 0xfd, 0xd3, 0x30, + 0x3a, 0x43, 0xfd, 0xd3, 0x30, 0x3a, 0x42, 0xfd, + 0xd3, 0x30, 0x00, 0x78, 0xd3, 0x30, 0x06, 0x00, + 0xcd, 0x51, 0x0d, 0x32, 0x41, 0xfd, 0xb7, 0xf2, + 0x4f, 0x0d, 0x05, 0xc2, 0x40, 0x0d, 0xb7, 0xc1, + 0xc9, 0x3e, 0xff, 0xd3, 0x30, 0x00, 0xdb, 0x30, + 0xc9, 0xf5, 0xc5, 0x06, 0x00, 0x0e, 0x01, 0xcd, + 0x51, 0x0d, 0x3c, 0xc2, 0x6f, 0x0d, 0x0d, 0xc2, + 0x5f, 0x0d, 0xc1, 0xf1, 0x37, 0x3f, 0xc9, 0xaf, + 0xcd, 0x06, 0x0d, 0x05, 0xc2, 0x5d, 0x0d, 0xc1, + 0xf1, 0x37, 0xc9, 0xaf, 0x32, 0x42, 0xfd, 0x32, + 0x43, 0xfd, 0x32, 0x44, 0xfd, 0x32, 0x45, 0xfd, + 0xc9, 0xcd, 0xa2, 0x07, 0xfe, 0x1b, 0x37, 0xc8, + 0xfe, 0x0d, 0xc8, 0xb9, 0xc8, 0xcd, 0xa6, 0x0d, + 0xfe, 0x21, 0xda, 0x89, 0x0d, 0x05, 0x04, 0xc8, + 0x77, 0x23, 0x05, 0xc3, 0x89, 0x0d, 0xfe, 0x61, + 0xd8, 0xfe, 0x7b, 0xd0, 0xe6, 0x5f, 0xc9, 0xe5, + 0x06, 0x08, 0x7e, 0xb7, 0xca, 0xc4, 0x0d, 0xfe, + 0x20, 0xca, 0xc4, 0x0d, 0xcd, 0xc3, 0x07, 0x23, + 0x05, 0xc2, 0xb2, 0x0d, 0x3e, 0x2e, 0xcd, 0xc3, + 0x07, 0xe1, 0xe5, 0x01, 0x08, 0x00, 0x09, 0x06, + 0x03, 0x7e, 0xb7, 0xca, 0xe3, 0x0d, 0xfe, 0x20, + 0xca, 0xe3, 0x0d, 0xcd, 0xc3, 0x07, 0x23, 0x05, + 0xc2, 0xd1, 0x0d, 0xe1, 0xc9, 0x5e, 0x23, 0x56, + 0x23, 0x4e, 0x23, 0x46, 0xc9, 0x73, 0x23, 0x72, + 0x23, 0x71, 0x23, 0x70, 0xc9, 0x7b, 0x86, 0x5f, + 0x23, 0x7a, 0x8e, 0x57, 0x23, 0x79, 0x8e, 0x4f, + 0x23, 0x78, 0x8e, 0x47, 0xc9, 0x13, 0x7a, 0xb3, + 0xc0, 0x03, 0xc9, 0x7a, 0xb3, 0xc2, 0x11, 0x0e, + 0x0b, 0x1b, 0xc9, 0x7a, 0xb3, 0xc0, 0xb1, 0xc0, + 0xb0, 0xc9, 0x23, 0x23, 0x23, 0x78, 0xbe, 0xc2, + 0x32, 0x0e, 0x2b, 0x79, 0xbe, 0xc2, 0x33, 0x0e, + 0x2b, 0x7a, 0xbe, 0xc2, 0x34, 0x0e, 0x2b, 0x7b, + 0xbe, 0xc9, 0x2b, 0x2b, 0x2b, 0xc9, 0x7a, 0xbc, + 0xc0, 0x7b, 0xbd, 0xc9, 0x06, 0x02, 0xc3, 0x43, + 0x0e, 0x06, 0x04, 0x7e, 0x12, 0x23, 0x13, 0x05, + 0xc2, 0x43, 0x0e, 0xc9, 0x7e, 0x23, 0x66, 0x6f, + 0xc9, 0xf5, 0xc5, 0xe5, 0x77, 0x23, 0x05, 0xc2, + 0x54, 0x0e, 0xe1, 0xc1, 0xf1, 0xc9, 0xe9, 0x3a, + 0x51, 0xfd, 0xeb, 0x1e, 0x00, 0x47, 0x0e, 0x08, + 0x29, 0x7b, 0x07, 0x5f, 0x7c, 0x90, 0xda, 0x73, + 0x0e, 0x67, 0x1c, 0x0d, 0xc2, 0x68, 0x0e, 0x7c, + 0x16, 0x00, 0xc9, 0x3a, 0x38, 0xfd, 0x47, 0x05, + 0xc8, 0xb7, 0x7a, 0x1f, 0x57, 0x7b, 0x1f, 0x5f, + 0xc3, 0x7f, 0x0e, 0x3a, 0x3d, 0xfd, 0xa3, 0xc9 + }; + +static uint8 jair_ram[JAIR_ROM_SIZE] = {0}; + +/*********************/ +/* JAIR Definitions */ +/*********************/ + +/* +** PORT ASSIGNMENTS +*/ +#define JAIR_CPU_IO 0x20 /* BASE ADDRESS FOR ONBOARD CPU I/O */ +#define JAIR_UART0 JAIR_CPU_IO /* UART0 OFFSET */ +#define JAIR_UART1 JAIR_CPU_IO + 0x08 /* UART1 OFFSET */ +#define JAIR_SPI JAIR_CPU_IO + 0x10 /* SPI OFFSET */ +#define JAIR_SPI_SS JAIR_CPU_IO + 0x11 /* SPI_SS OFFSET */ +#define JAIR_PPORT JAIR_CPU_IO + 0x18 /* PPORT OFFSET */ + +#define JAIR_SDATA 0x00 /* 8250 SERIAL DATA */ +#define JAIR_IER 0x01 /* 8250 INTERRUPT ENABLE REGISTER */ +#define JAIR_IIR 0x02 /* 8250 INTERRUPT IDENT REGISTER */ +#define JAIR_LCR 0x03 /* 8250 LINE CONTROL REGISTER */ +#define JAIR_MCR 0x04 /* 8250 MODEM CONTROL REGISTER */ +#define JAIR_LSR 0x05 /* 8250 LINE STATUS REGISTER */ +#define JAIR_MSR 0x06 /* 8250 MODEM STATUS REGISTER */ +#define JAIR_SR 0x07 /* 8250 SCRATCH REGISTER */ + +/* +** BIT ASSIGNMENT MASKS +*/ +#define JAIR_DR 0x01 /* SERIAL DATA READY */ +#define JAIR_THRE 0x20 /* SERIAL TRANSMITTER BUFFER EMPTY */ +#define JAIR_TEMT 0x40 /* SERIAL TRANSMITTER BUFFER EMPTY */ +#define JAIR_DLAB 0x80 /* DIVISOR LATCH ACCESS BIT */ + +#define JAIR_DCTS 0x01 /* Clear to Send (Delta) */ +#define JAIR_DDSR 0x02 /* Data Set Ready (Delta) */ +#define JAIR_DRNG 0x04 /* Ring Indicate (Delta) */ +#define JAIR_DDCD 0x08 /* Data Carrier Detect (Delta) */ +#define JAIR_CTS 0x10 /* Clear to Send */ +#define JAIR_DSR 0x20 /* Data Set Ready */ +#define JAIR_RNG 0x40 /* Ring Indicate */ +#define JAIR_DCD 0x80 /* Data Carrier Detect */ +#define JAIR_DTR 0x01 /* Data Terminal Ready */ +#define JAIR_RTS 0x02 /* Request to Send */ + +#define JAIR_STATE_IDLE 0 /* idle */ +#define JAIR_STATE_CMD 1 /* receiving command */ +#define JAIR_STATE_RESP 2 /* sending response */ +#define JAIR_STATE_SBLK 3 /* start block */ +#define JAIR_STATE_WBLK 4 /* write block */ + +/* +** SD Commands +*/ +#define JAIR_CMD0 0 +#define JAIR_CMD8 8 /* send if condition */ +#define JAIR_CMD13 13 /* send status */ +#define JAIR_CMD17 17 /* read single block */ +#define JAIR_CMD24 24 /* write single block */ +#define JAIR_CMD55 55 /* application command */ +#define JAIR_ACMD41 41 + 0x80 /* send op condition */ + +/****************/ +/* JAIR Device */ +/****************/ + +#define JAIR_NAME "Josh's Altair / IMASI Replacement CPU & SBC" +#define JAIR_SNAME "JAIR" + +#define JAIR_UNITS 1 + +#define UNIT_V_JAIR_VERBOSE (UNIT_V_UF + 0) /* VERBOSE / QUIET */ +#define UNIT_JAIR_VERBOSE (1 << UNIT_V_JAIR_VERBOSE) +#define UNIT_V_JAIR_WPROTECT (UNIT_V_UF + 1) /* WRTENB / WRTPROT */ +#define UNIT_JAIR_WPROTECT (1 << UNIT_V_JAIR_WPROTECT) +#define UNIT_V_JAIR_ROM (UNIT_V_UF + 2) /* WRTENB / WRTPROT */ +#define UNIT_JAIR_ROM (1 << UNIT_V_JAIR_ROM) + +/* +** JAIR Registers and Interface Controls +*/ + +typedef struct { + uint32 rom_base; /* Memory Base Address */ + uint32 rom_size; /* Memory Address space requirement */ + uint32 io_base; /* I/O Base Address */ + uint32 io_size; /* I/O Address Space requirement */ + t_bool sr_ena; /* Shadow ROM enable */ + t_bool spi_cs; /* SPI *CS (Active Low) */ + uint8 sd_istate; /* SD Card Input State */ + uint8 sd_ostate; /* SD Card Output State */ + uint8 sd_cmd[512+6]; /* SD Card Command */ + uint16 sd_cmd_len; + uint16 sd_cmd_idx; + uint8 sd_resp[512+6]; /* SD Card Response */ + uint16 sd_resp_len; + uint16 sd_resp_idx; + t_bool sd_appcmd; /* SD app command flag */ +} JAIR_CTX; + +static JAIR_CTX jair_ctx = { + JAIR_ROM_BASE, JAIR_ROM_SIZE, JAIR_SPI, 2 +}; + +static UNIT jair_unit[] = { + { UDATA (NULL, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE + UNIT_JAIR_ROM, 0) } +}; + +static REG jair_reg[] = { + { NULL } +}; + +static MTAB jair_mod[] = { + { MTAB_XTD|MTAB_VDV, 0, "PORT", "PORT", + NULL, jair_show_ports, NULL, "I/O port address" }, + { UNIT_JAIR_ROM, UNIT_JAIR_ROM, "ROM", "ROM", &jair_set_rom, + NULL, NULL, "Enable JAIR ROM" }, + { UNIT_JAIR_ROM, 0, "NOROM", "NOROM", &jair_set_norom, + NULL, NULL, "Disable JAIR ROM"}, + { 0 } +}; + +DEVICE jair_dev = { + JAIR_SNAME, /* name */ + jair_unit, /* unit */ + jair_reg, /* registers */ + jair_mod, /* modifiers */ + JAIR_UNITS, /* # units */ + 10, /* address radix */ + 31, /* address width */ + 1, /* addr increment */ + 8, /* data radix */ + 8, /* data width */ + NULL, /* examine routine */ + NULL, /* deposit routine */ + &jair_reset, /* reset routine */ + &jair_boot, /* boot routine */ + &jair_attach, /* attach routine */ + &jair_detach, /* detach routine */ + &jair_ctx, /* context */ + (DEV_DISABLE | DEV_DIS | DEV_DEBUG), /* flags */ + ERROR_MSG, /* debug control */ + jair_dt, /* debug flags */ + NULL, /* mem size routine */ + NULL, /* logical name */ + &jair_help, /* help */ + NULL, /* attach help */ + NULL, /* context for help */ + &jair_description /* description */ +}; + +/****************/ +/* GENERIC PORT */ +/****************/ + +typedef struct { + PNP_INFO pnp; /* Must be first */ + int32 conn; /* Connected Status */ + uint16 baud; /* Baud rate */ + uint8 status; /* Status Byte */ + uint8 rdr; /* Receive Data Ready */ + uint8 rxd; /* Receive Data Buffer */ + uint8 txd; /* Transmit Data Buffer */ + t_bool txp; /* Transmit Data Pending */ + uint8 ier; /* Interrupt Enable Register */ + uint8 iir; /* Interrupt Ident Register */ + uint8 lcr; /* Line Control Register */ + uint8 mcr; /* Modem Control Register */ + uint8 lsr; /* Line Status Register */ + uint8 msr; /* Modem Status Register */ + uint8 sr; /* Scratch Register */ + uint8 dlls; /* Divisor Latch LS */ + uint8 dlms; /* Divisor Latch MS */ + TMLN *tmln; /* TMLN pointer */ + TMXR *tmxr; /* TMXR pointer */ +} JAIR_PORT_CTX; + +/**************************/ +/* JAIRS0 Keyboard Device */ +/**************************/ + +#define JAIRS0_NAME "JAIR Serial Port 0" +#define JAIRS0_SNAME "JAIRS0" + +static TMLN jairs0_tmln[1] = { /* line descriptors */ + { 0 } +}; + +static TMXR jairs0_tmxr = { /* multiplexer descriptor */ + 1, /* number of terminal lines */ + 0, /* listening port (reserved) */ + 0, /* master socket (reserved) */ + jairs0_tmln, /* line descriptor array */ + NULL, /* line connection order */ + NULL /* multiplexer device (derived internally) */ +}; + +static JAIR_PORT_CTX jairs0_ctx = { + {0, 0, JAIR_UART0, 8}, 0, 9600, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + jairs0_tmln, &jairs0_tmxr +}; + +static REG jairs0_reg[] = { + { DRDATAD (BAUD0, jairs0_ctx.baud, 16, "Serial port baud register"), }, + { HRDATAD (TXP0, jairs0_ctx.txp, 1, "Serial port TX data pending"), }, + { HRDATAD (TXD0, jairs0_ctx.txd, 8, "Serial port TX data register"), }, + { HRDATAD (RDR0, jairs0_ctx.rdr, 1, "Serial port RX data ready"), }, + { HRDATAD (RXD0, jairs0_ctx.rxd, 8, "Serial port RX register"), }, + { HRDATAD (LSR0, jairs0_ctx.lsr, 8, "Serial port line status register"), }, + { HRDATAD (MSR0, jairs0_ctx.msr, 8, "Serial port modem status register"), }, + { NULL } +}; + + +static UNIT jairs0_unit[] = { + { UDATA (&jair_svc, UNIT_ATTABLE, 0), (int) USECS_PER_SECOND / 1000 } +}; + +static MTAB jairs0_mod[] = { + { MTAB_XTD|MTAB_VDV, 0, "PORT", "PORT", + NULL, jair_show_ports, NULL, "Show serial I/O ports" }, + { MTAB_XTD|MTAB_VDV|MTAB_VALR, 0, "BAUD", "BAUD", + &jair_set_baud, &jair_show_baud, NULL, "Set baud rate (default=9600)" }, + { 0 } +}; + +DEVICE jairs0_dev = { + JAIRS0_SNAME, /* name */ + jairs0_unit, /* unit */ + jairs0_reg, /* registers */ + jairs0_mod, /* modifiers */ + 1, /* # units */ + 10, /* address radix */ + 31, /* address width */ + 1, /* addr increment */ + 8, /* data radix */ + 8, /* data width */ + NULL, /* examine routine */ + NULL, /* deposit routine */ + &jair_port_reset, /* reset routine */ + NULL, /* boot routine */ + &jair_attach_mux, /* attach routine */ + &jair_detach_mux, /* detach routine */ + &jairs0_ctx, /* context */ + (DEV_DISABLE | DEV_DIS | DEV_DEBUG | DEV_MUX), /* flags */ + ERROR_MSG, /* debug control */ + jair_dt, /* debug flags */ + NULL, /* mem size routine */ + NULL, /* logical name */ + NULL, /* help */ + NULL, /* attach help */ + NULL, /* context for help */ + &jairs0_description /* description */ +}; + +/************************/ +/* JAIRS1 Serial Device */ +/************************/ + +#define JAIRS1_NAME "JAIR Serial Port 1" +#define JAIRS1_SNAME "JAIRS1" + +static TMLN jairs1_tmln[1] = { /* line descriptors */ + { 0 } +}; + +static TMXR jairs1_tmxr = { /* multiplexer descriptor */ + 1, /* number of terminal lines */ + 0, /* listening port (reserved) */ + 0, /* master socket (reserved) */ + jairs1_tmln, /* line descriptor array */ + NULL, /* line connection order */ + NULL /* multiplexer device (derived internally) */ +}; + +static JAIR_PORT_CTX jairs1_ctx = { + {0, 0, JAIR_UART1, 8}, 0, 9600, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + jairs1_tmln, &jairs1_tmxr +}; + +static REG jairs1_reg[] = { + { DRDATAD (BAUD1, jairs1_ctx.baud, 16, "Serial port baud register"), }, + { HRDATAD (TXP1, jairs1_ctx.txp, 1, "Serial port TX data pending"), }, + { HRDATAD (TXD1, jairs1_ctx.txd, 8, "Serial port TX data register"), }, + { HRDATAD (RDR1, jairs1_ctx.rdr, 1, "Serial port RX data ready"), }, + { HRDATAD (RXD1, jairs1_ctx.rxd, 8, "Serial port RX register"), }, + { HRDATAD (LSR1, jairs1_ctx.lsr, 8, "Serial port line status register"), }, + { HRDATAD (MSR1, jairs1_ctx.msr, 8, "Serial port modem status register"), }, + { NULL } +}; + +static UNIT jairs1_unit[] = { + { UDATA (&jair_svc, UNIT_ATTABLE, 0), (int) USECS_PER_SECOND / 1000 } +}; + +static MTAB jairs1_mod[] = { + { MTAB_XTD|MTAB_VDV, 0, "PORT", "PORT", + NULL, jair_show_ports, NULL, "Show serial I/O ports" }, + { MTAB_XTD|MTAB_VDV|MTAB_VALR, 0, "BAUD", "BAUD", + &jair_set_baud, &jair_show_baud, NULL, "Set baud rate (default=9600)" }, + { 0 } +}; + +DEVICE jairs1_dev = { + JAIRS1_SNAME, /* name */ + jairs1_unit, /* unit */ + jairs1_reg, /* registers */ + jairs1_mod, /* modifiers */ + 1, /* # units */ + 10, /* address radix */ + 31, /* address width */ + 1, /* addr increment */ + 8, /* data radix */ + 8, /* data width */ + NULL, /* examine routine */ + NULL, /* deposit routine */ + &jair_port_reset, /* reset routine */ + NULL, /* boot routine */ + &jair_attach_mux, /* attach routine */ + &jair_detach_mux, /* detach routine */ + &jairs1_ctx, /* context */ + (DEV_DISABLE | DEV_DIS | DEV_DEBUG | DEV_MUX), /* flags */ + ERROR_MSG, /* debug control */ + jair_dt, /* debug flags */ + NULL, /* mem size routine */ + NULL, /* logical name */ + NULL, /* help */ + NULL, /* attach help */ + NULL, /* context for help */ + &jairs1_description /* description */ +}; + +/***********************/ +/* JAIRP Parallel Port */ +/***********************/ + +#define JAIRP_NAME "JAIR Parallel Port" +#define JAIRP_SNAME "JAIRP" + +static TMLN jairp_tmln[1] = { /* line descriptors */ + { 0 } +}; + +static TMXR jairp_tmxr = { /* multiplexer descriptor */ + 1, /* number of terminal lines */ + 0, /* listening port (reserved) */ + 0, /* master socket (reserved) */ + jairp_tmln, /* line descriptor array */ + NULL, /* line connection order */ + NULL /* multiplexer device (derived internally) */ +}; + +static JAIR_PORT_CTX jairp_ctx = { + {0, 0, JAIR_PPORT, 1}, 0, 9600, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + jairp_tmln, &jairp_tmxr +}; + +static REG jairp_reg[] = { + { DRDATAD (BAUDP, jairp_ctx.baud, 16, "Serial port baud register"), }, + { HRDATAD (TXPP, jairp_ctx.txp, 1, "Printer port tx pending"), }, + { HRDATAD (TXDP, jairp_ctx.txd, 8, "Printer port data register"), }, + { HRDATAD (RDRP, jairp_ctx.rdr, 1, "Printer port RX data ready"), }, + { HRDATAD (RXDP, jairp_ctx.rxd, 8, "Printer port RX data register"), }, + { NULL } +}; + +static UNIT jairp_unit[] = { + { UDATA (&jair_svc, UNIT_ATTABLE, 0), (int) USECS_PER_SECOND / 1000 } +}; + +static MTAB jairp_mod[] = { + { MTAB_XTD|MTAB_VDV|MTAB_VALR, 0, "BAUD", "BAUD", + &jair_set_baud, &jair_show_baud, NULL, "Set baud rate (default=9600)" }, + { 0 } +}; + +DEVICE jairp_dev = { + JAIRP_SNAME, /* name */ + jairp_unit, /* unit */ + jairp_reg, /* registers */ + jairp_mod, /* modifiers */ + 1, /* # units */ + 10, /* address radix */ + 31, /* address width */ + 1, /* addr increment */ + 8, /* data radix */ + 8, /* data width */ + NULL, /* examine routine */ + NULL, /* deposit routine */ + &jair_port_reset, /* reset routine */ + NULL, /* boot routine */ + &jair_attach_mux, /* attach routine */ + &jair_detach_mux, /* detach routine */ + &jairp_ctx, /* context */ + (DEV_DISABLE | DEV_DIS | DEV_DEBUG | DEV_MUX), /* flags */ + ERROR_MSG, /* debug control */ + jair_dt, /* debug flags */ + NULL, /* mem size routine */ + NULL, /* logical name */ + NULL, /* help */ + NULL, /* attach help */ + NULL, /* context for help */ + &jairp_description /* description */ +}; + +static const char* jair_description(DEVICE *dptr) { + return JAIR_NAME; +} + +static const char* jairs0_description(DEVICE *dptr) { + return JAIRS0_NAME; +} + +static const char* jairs1_description(DEVICE *dptr) { + return JAIRS1_NAME; +} + +static const char* jairp_description(DEVICE *dptr) { + return JAIRP_NAME; +} + +/* + * Reset function for the main JAIR device. + * + * Enables all other Sol-20 devices + */ +static t_stat jair_reset(DEVICE *dptr) +{ + static t_bool first = TRUE; + + if (dptr->flags & DEV_DIS) { /* Disconnect Resources */ + sim_map_resource(jair_ctx.io_base, jair_ctx.io_size, RESOURCE_TYPE_IO, &jairio, "jairio", TRUE); + sim_map_resource(jair_ctx.rom_base, jair_ctx.rom_size, RESOURCE_TYPE_MEMORY, &jair_shadow_rom, "jairrom", TRUE); + } + else { + /* Connect I/O Ports at base address */ + if (sim_map_resource(jair_ctx.io_base, jair_ctx.io_size, RESOURCE_TYPE_IO, &jairio, "jairio", FALSE) != 0) { + sim_debug(ERROR_MSG, &jair_dev, "Error mapping I/O resource at 0x%02x\n", jair_ctx.io_base); + return SCPE_ARG; + } + if (sim_map_resource(jair_ctx.rom_base, jair_ctx.rom_size, RESOURCE_TYPE_MEMORY, &jair_shadow_rom, "jairrom", FALSE) != 0) { + sim_debug(ERROR_MSG, &jair_dev, "Error mapping ROM resource at 0x%02x\n", jair_ctx.io_base); + return SCPE_ARG; + } + + if (first) { + set_dev_enbdis(&jairs0_dev, NULL, 1, NULL); + set_dev_enbdis(&jairs1_dev, NULL, 1, NULL); + set_dev_enbdis(&jairp_dev, NULL, 1, NULL); + + first = FALSE; + } + } + + jair_ctx.sr_ena = TRUE; + jair_ctx.spi_cs = TRUE; + jair_ctx.sd_appcmd = FALSE; + jair_ctx.sd_istate = JAIR_STATE_IDLE; + jair_ctx.sd_ostate = JAIR_STATE_IDLE; + + sim_debug(STATUS_MSG, &jair_dev, "reset controller.\n"); + + return SCPE_OK; +} + +/* + * The BOOT command will enter the ROM at 0x0000 + */ +static t_stat jair_boot(int32 unitno, DEVICE *dptr) +{ + sim_printf("%s: Booting using ROM at 0x%04x\n", JAIR_SNAME, jair_ctx.rom_base); + + *((int32 *) sim_PC->loc) = jair_ctx.rom_base; + + return SCPE_OK; +} + +static t_stat jair_port_reset(DEVICE *dptr) { + JAIR_PORT_CTX *port; + uint32 u; + + port = (JAIR_PORT_CTX *) dptr->ctxt; + + for (u = 0; u < dptr->numunits; u++) { + dptr->units[u].dptr = dptr; + } + + if (dptr->flags & DEV_DIS) { /* Disconnect I/O Port(s) */ + sim_map_resource(port->pnp.io_base, port->pnp.io_size, RESOURCE_TYPE_IO, &jairio, dptr->name, TRUE); + for (u = 0; u < dptr->numunits; u++) { + sim_cancel(&dptr->units[u]); /* cancel timer */ + } + } + else { + /* Connect I/O Ports at base address */ + if (sim_map_resource(port->pnp.io_base, port->pnp.io_size, RESOURCE_TYPE_IO, &jairio, dptr->name, FALSE) != 0) { + sim_debug(ERROR_MSG, dptr, "Error mapping I/O resource at 0x%02x\n", port->pnp.io_base); + return SCPE_ARG; + } + + /* Enable TMXR modem control passthrough */ + tmxr_set_modem_control_passthru(port->tmxr); + tmxr_set_port_speed_control(port->tmxr); + + port->status = 0x00; + port->rdr = FALSE; + port->txp = FALSE; + port->lsr = JAIR_TEMT | JAIR_THRE; + port->msr = 0; + + for (u = 0; u < dptr->numunits; u++) { + sim_activate_after(&dptr->units[u], dptr->units[u].wait); /* activate timer */ + } + } + + return SCPE_OK; +} + +/* + * JAIR service routine + * + * The JAIR simulator has 3 I/O devices + * + * JAIRS0 - Keyboard device that supports TMXR + * JAIRS1 - Serial device that supports TMXR + * JAIRP - Parallel device that supports TMXR + */ +static t_stat jair_svc(UNIT *uptr) +{ + JAIR_PORT_CTX *port; + int32 c = 0; + int32 s; + t_stat r = SCPE_OK; + uint8 msr; + + port = (JAIR_PORT_CTX *) uptr->dptr->ctxt; + + /* Check for new incoming connection */ + if (uptr->dynflags & UNIT_TM_POLL && !port->conn && uptr->flags & UNIT_ATT) { + if (tmxr_poll_conn(port->tmxr) >= 0) { /* poll connection */ + + port->conn = 1; /* set connected */ + + sim_printf("%s: new connection.\n", uptr->dptr->name); + } + } + + /* TX byte pending? */ + if (port->txp == TRUE) { + if (uptr->flags & UNIT_ATT) { + if (uptr->fileref) { + r = (sim_fwrite(&port->txd, 1, 1, uptr->fileref) == 1) ? SCPE_OK : SCPE_IOERR; + port->txp = FALSE; + port->lsr |= (JAIR_TEMT | JAIR_THRE); + } else if (port->conn) { + if ((r = tmxr_putc_ln(&port->tmln[0], port->txd)) == SCPE_OK) { + tmxr_poll_tx(port->tmxr); + port->txp = FALSE; + } else if (r == SCPE_LOST) { + port->conn = 0; /* Connection was lost */ + sim_printf("%s: lost connection.\n", uptr->dptr->name); + } else { + sim_printf("%s: tmxr_putc_ln error %d.\n", uptr->dptr->name, r); + } + } + } + else { + sim_putchar(port->txd); + port->txp = FALSE; + port->lsr |= (JAIR_TEMT | JAIR_THRE); + } + } + + /* Update LSR if no character pending */ + if (port->txp == FALSE && port->conn && !(port->lsr & (JAIR_TEMT | JAIR_THRE))) { + port->lsr |= tmxr_txdone_ln(port->tmln) ? (JAIR_TEMT | JAIR_THRE) : 0; + } + + /* Check for Data if RX buffer empty */ + if (port->rdr == FALSE) { + if (uptr->flags & UNIT_ATT) { + if (uptr->fileref) { + if (sim_fread(&c, 1, 1, uptr->fileref) == 1) { + c |= SCPE_KFLAG; + } + } + else if (port->conn) { + tmxr_poll_rx(port->tmxr); + c = tmxr_getc_ln(&port->tmln[0]); + } + } + else if (uptr == jairs0_unit) { + c = sim_poll_kbd(); + } + + if (c & (TMXR_VALID | SCPE_KFLAG)) { + port->rxd = c & 0xff; + port->rdr = TRUE; + port->lsr |= JAIR_DR; + } + } + + /* Update Modem Status Register */ + if (uptr->flags & UNIT_ATT && port->conn) { + tmxr_set_get_modem_bits(port->tmln, 0, 0, &s); + + msr = port->msr; + + port->msr &= ~JAIR_CTS; + port->msr |= (s & TMXR_MDM_CTS) ? JAIR_CTS : 0; + + /* CTS status changed */ + if ((msr ^ port->msr) & JAIR_CTS) { + port->msr |= JAIR_DCTS; + sim_debug(STATUS_MSG, uptr->dptr, "CTS state changed to %s.\n", (port->msr & JAIR_CTS) ? "HIGH" : "LOW"); + } + + port->msr &= ~JAIR_DSR; + port->msr |= (s & TMXR_MDM_DSR) ? JAIR_DSR : 0; + + /* DSR status changed */ + if ((msr ^ port->msr) & JAIR_DSR) { + port->msr |= JAIR_DDSR; + sim_debug(STATUS_MSG, uptr->dptr, "DSR state changed to %s.\n", (port->msr & JAIR_DSR) ? "HIGH" : "LOW"); + } + + port->msr &= ~JAIR_RNG; + port->msr |= (s & TMXR_MDM_RNG) ? JAIR_RNG : 0; + + /* RI status changed */ + if ((msr ^ port->msr) & JAIR_RNG) { + port->msr |= (port->msr & JAIR_RNG) ? 0 : JAIR_DRNG; /* trailing edge to low */ + sim_debug(STATUS_MSG, uptr->dptr, "RNG state changed to %s.\n", (port->msr & JAIR_RNG) ? "HIGH" : "LOW"); + } + + port->msr &= ~JAIR_DCD; + port->msr |= (s & TMXR_MDM_DCD) ? JAIR_DCD : 0; + + /* DCD status changed */ + if ((msr ^ port->msr) & JAIR_DCD) { + port->msr |= JAIR_DDCD; + sim_debug(STATUS_MSG, uptr->dptr, "DCD state changed to %s.\n", (port->msr & JAIR_DCD) ? "HIGH" : "LOW"); + } + } + + r = sim_activate_after(uptr, uptr->wait); /* reactivate timer */ + + return r; +} + +/* Attach routines */ +static t_stat jair_attach(UNIT *uptr, CONST char *cptr) +{ + t_stat r; + unsigned int i = 0; + + r = attach_unit(uptr, cptr); /* attach unit */ + if (r != SCPE_OK) { /* error? */ + sim_debug(ERROR_MSG, &jair_dev, "ATTACH error=%d\n", r); + return r; + } + + /* Determine length of this disk */ + uptr->capac = sim_fsize(uptr->fileref); + + for (i = 0; i < JAIR_UNITS; i++) { + if (jair_dev.units[i].fileref == uptr->fileref) { + break; + } + } + + if (i >= JAIR_UNITS) { + jair_detach(uptr); + + return SCPE_ARG; + } + + /* Default for new file is DSK */ + uptr->u3 = IMAGE_TYPE_DSK; + + sim_debug(VERBOSE_MSG, uptr->dptr, "unit %d, attached to '%s' size=%d\n", + i, cptr, uptr->capac); + + return SCPE_OK; +} + +/* Detach routines */ +static t_stat jair_detach(UNIT *uptr) +{ + t_stat r; + int8 i; + + for (i = 0; i < JAIR_UNITS; i++) { + if (jair_dev.units[i].fileref == uptr->fileref) { + break; + } + } + + if (i >= JAIR_UNITS) { + return SCPE_ARG; + } + + r = detach_unit(uptr); /* detach unit */ + + if (r != SCPE_OK) { + return r; + } + + jair_dev.units[i].fileref = NULL; + + sim_debug(VERBOSE_MSG, uptr->dptr, "unit %d detached.\n", i); + + return SCPE_OK; +} + +/* + * Used to attach (connect) MUX interfaces from the + * JAIRS0, JAIRS1, and JAIRP devices + */ +static t_stat jair_attach_mux(UNIT *uptr, CONST char *cptr) +{ + JAIR_PORT_CTX *xptr; + t_stat r; + + xptr = (JAIR_PORT_CTX *) uptr->dptr->ctxt; + + if ((r = tmxr_attach(xptr->tmxr, uptr, cptr)) == SCPE_OK) { + xptr->tmln[0].rcve = 1; + sim_printf("%s: attached '%s' to interface.\n", uptr->dptr->name, cptr); + tmxr_set_get_modem_bits(xptr->tmln, TMXR_MDM_DTR | TMXR_MDM_RTS, 0, NULL); + } + + return r; +} + +/* + * Used to detach (disconnect) MUX interfaces from the + * JAIRS0, JAIRS1, and JAIRP devices + */ +static t_stat jair_detach_mux(UNIT *uptr) +{ + JAIR_PORT_CTX *xptr; + t_stat r; + + xptr = (JAIR_PORT_CTX *) uptr->dptr->ctxt; + + if ((r = tmxr_detach(xptr->tmxr, uptr)) == SCPE_OK) { + sim_printf("%s: detached.\n", uptr->dptr->name); + } + + return r; +} + +static t_stat jair_show_ports(FILE *st, UNIT *uptr, int32 val, CONST void *desc) { + JAIR_PORT_CTX *port; + + port = (JAIR_PORT_CTX *) uptr->dptr->ctxt; + + fprintf(st, "I/O=0x%02X-0x%02X", port->pnp.io_base, port->pnp.io_base + port->pnp.io_size - 1); + return SCPE_OK; +} + +static t_stat jair_config_line(DEVICE *dev, TMLN *tmln, int baud) +{ + char config[20]; + const char *fmt; + t_stat r = SCPE_IERR; + + if (tmln->serport) { + fmt = "8N1"; + + sprintf(config, "%d-%s", baud, fmt); + + r = tmxr_set_config_line(tmln, config); + + sim_debug(STATUS_MSG, dev, "port configuration set to '%s'.\n", config); + } + + return r; +} + +static int jair_set_mc(TMLN *tmln, uint8 data) +{ + int s = 0; + + s |= (data & JAIR_DTR) ? TMXR_MDM_DTR : 0; + s |= (data & JAIR_RTS) ? TMXR_MDM_RTS : 0; + + return tmxr_set_get_modem_bits(tmln, s, ~s & (TMXR_MDM_DTR | TMXR_MDM_RTS), NULL); +} + +static int jair_new_baud(UNIT *uptr) +{ + JAIR_PORT_CTX *port; + int divisor; + + port = (JAIR_PORT_CTX *) uptr->dptr->ctxt; + + divisor = (port->dlms << 8) + port->dlls; + + if (divisor) { + port->baud = 115200 / divisor; + jair_config_line(uptr->dptr, port->tmln, port->baud); + } + + return port->baud; +} + +static t_stat jair_set_baud(UNIT *uptr, int32 value, const char *cptr, void *desc) +{ + int32 baud; + t_stat r = SCPE_ARG; + JAIR_PORT_CTX *port; + + port = (JAIR_PORT_CTX *) uptr->dptr->ctxt; + + if (!(uptr->flags & UNIT_ATT)) { + return SCPE_UNATT; + } + + if (cptr != NULL) { + if (sscanf(cptr, "%d", &baud)) { + port->baud = baud; + r = jair_config_line(uptr->dptr, port->tmln, port->baud); + } + } + + return r; +} + +static t_stat jair_show_baud(FILE *st, UNIT *uptr, int32 value, const void *desc) +{ + JAIR_PORT_CTX *port; + + port = (JAIR_PORT_CTX *) uptr->dptr->ctxt; + + if (uptr->flags & UNIT_ATT) { + fprintf(st, "Baud rate: %d", port->baud); + } + + return SCPE_OK; +} + +/* + * Handles I/O input and output + */ +static int32 jairio(int32 addr, int32 rw, int32 data) +{ + if (rw == 0) { + return(jair_io_in(addr)); + } + else { + return(jair_io_out(addr, data)); + } +} + +static uint8 jair_io_in(uint32 addr) +{ + uint8 data = 0xff; + + switch(addr & 0xff) { + case JAIR_UART0 + JAIR_LSR: + data = jairs0_ctx.lsr; + break; + + case JAIR_UART1 + JAIR_LSR: + data = jairs1_ctx.lsr; + break; + + case JAIR_UART0 + JAIR_SDATA: + data = jairs0_ctx.rxd; + jairs0_ctx.rdr = FALSE; + jairs0_ctx.lsr &= ~JAIR_DR; + break; + + case JAIR_UART1 + JAIR_SDATA: + data = jairs1_ctx.rxd; + jairs1_ctx.rdr = FALSE; + jairs1_ctx.lsr &= ~JAIR_DR; + break; + + case JAIR_UART0 + JAIR_MSR: + data = jairs0_ctx.msr; + jairs0_ctx.msr &= 0xf0; /* Clear deltas */ + break; + + case JAIR_UART1 + JAIR_MSR: + data = jairs1_ctx.msr; + jairs1_ctx.msr &= 0xf0; /* Clear deltas */ + break; + + case JAIR_UART0 + JAIR_SR: + data = jairs0_ctx.sr; + break; + + case JAIR_UART1 + JAIR_SR: + data = jairs1_ctx.sr; + break; + + case JAIR_PPORT: + data = jairp_ctx.rxd; + jairp_ctx.rdr = FALSE; + break; + + case JAIR_SPI: + if (jair_ctx.spi_cs) { /* Chip is disabled */ + break; + } + + switch (jair_ctx.sd_istate) { + case JAIR_STATE_IDLE: + data = 0xff; + break; + + case JAIR_STATE_RESP: + if (jair_ctx.sd_resp_idx < jair_ctx.sd_resp_len) { /* Receive next command byte */ + data = jair_ctx.sd_resp[jair_ctx.sd_resp_idx++]; + } + else { + jair_ctx.sd_istate = JAIR_STATE_IDLE; + } + break; + + default: + break; + } + break; + + case JAIR_SPI_SS: + break; + + default: + sim_printf("Invalid IO Read %02x\n", addr); + + sim_debug(ERROR_MSG, &jair_dev, "READ Invalid I/O Address %02x (%02x)\n", + addr & 0xFF, addr & 0x01); + break; + } + + return (data); +} + +static uint8 jair_io_out(uint32 addr, int32 data) +{ + uint32 sd_addr; + + switch(addr & 0xff) { + case JAIR_UART0 + JAIR_SDATA: + if (jairs0_ctx.lcr & JAIR_DLAB) { + jairs0_ctx.dlls = data; + jair_new_baud(jairs0_unit); + } else { + jairs0_ctx.txd = data; + jairs0_ctx.txp = TRUE; + jairs0_ctx.lsr &= ~(JAIR_THRE | JAIR_TEMT); + } + break; + + case JAIR_UART1 + JAIR_SDATA: + if (jairs1_ctx.lcr & JAIR_DLAB) { + jairs1_ctx.dlls = data; + jair_new_baud(jairs1_unit); + } else { + jairs1_ctx.txd = data; + jairs1_ctx.txp = TRUE; + jairs1_ctx.lsr &= ~(JAIR_THRE | JAIR_TEMT); + } + break; + + case JAIR_UART0 + JAIR_IER: + if (jairs0_ctx.lcr & JAIR_DLAB) { + jairs0_ctx.dlms = data; + jair_new_baud(jairs0_unit); + } else { + jairs0_ctx.ier = data; + } + break; + + case JAIR_UART1 + JAIR_IER: + if (jairs1_ctx.lcr & JAIR_DLAB) { + jairs1_ctx.dlms = data; + jair_new_baud(jairs1_unit); + } else { + jairs1_ctx.ier = data; + } + break; + + case JAIR_UART0 + JAIR_SR: + jairs0_ctx.sr = data; + break; + + case JAIR_UART1 + JAIR_SR: + jairs1_ctx.sr = data; + break; + + case JAIR_UART0 + JAIR_LCR: + jairs0_ctx.lcr = data; + break; + + case JAIR_UART1 + JAIR_LCR: + jairs1_ctx.lcr = data; + break; + + case JAIR_UART0 + JAIR_MCR: + jairs0_ctx.mcr = data; + jair_set_mc(jairs0_ctx.tmln, data); + break; + + case JAIR_UART1 + JAIR_MCR: + jairs1_ctx.mcr = data; + jair_set_mc(jairs1_ctx.tmln, data); + break; + + case JAIR_PPORT: + jairp_ctx.txd = data; + jairp_ctx.txp = TRUE; + + jair_ctx.sr_ena = (data & 0x01) ? FALSE : TRUE; + break; + + case JAIR_SPI_SS: + jair_ctx.spi_cs = data & 0x01; + + if (jair_ctx.spi_cs) { /* If chip is disable, reset */ + jair_ctx.sd_appcmd = FALSE; + jair_ctx.sd_istate = JAIR_STATE_IDLE; + jair_ctx.sd_ostate = JAIR_STATE_IDLE; + } + break; + + case JAIR_SPI: + if (jair_ctx.spi_cs) { /* Chip is disabled */ + break; + } + + switch (jair_ctx.sd_ostate) { + case JAIR_STATE_IDLE: + if ((data & 0xc0) == 0x40) { /* Received start and transmission bits */ + jair_ctx.sd_cmd[0] = data & 0x3f; + jair_ctx.sd_cmd_len = 6; + jair_ctx.sd_cmd_idx = 1; + jair_ctx.sd_ostate = JAIR_STATE_CMD; + } + break; + + case JAIR_STATE_CMD: + if (jair_ctx.sd_cmd_idx < jair_ctx.sd_cmd_len) { /* Receive next command byte */ + jair_ctx.sd_cmd[jair_ctx.sd_cmd_idx++] = data; + } + else { + jair_ctx.sd_resp[0] = (jair_ctx.sd_cmd[5] & 0x01) ? 0x00 : 0x04; + + if (jair_ctx.sd_appcmd) { + jair_ctx.sd_cmd[0] |= 0x80; + jair_ctx.sd_appcmd = FALSE; + } + + switch (jair_ctx.sd_cmd[0]) { + case JAIR_CMD0: + jair_ctx.sd_resp[0] |= 0x01; + jair_ctx.sd_resp_idx = 0; + jair_ctx.sd_resp_len = 1; + jair_ctx.sd_istate = JAIR_STATE_RESP; + jair_ctx.sd_ostate = JAIR_STATE_IDLE; + break; + + case JAIR_CMD13: + jair_ctx.sd_resp[0] = 0x00; + jair_ctx.sd_resp[1] = 0x00; + jair_ctx.sd_resp_idx = 0; + jair_ctx.sd_resp_len = 2; + jair_ctx.sd_istate = JAIR_STATE_RESP; + jair_ctx.sd_ostate = JAIR_STATE_IDLE; + break; + + case JAIR_CMD17: + sd_addr = jair_ctx.sd_cmd[1] * 0x1000000; + sd_addr |= jair_ctx.sd_cmd[2] * 0x10000; + sd_addr |= (uint32) jair_ctx.sd_cmd[3] * 0x100; + sd_addr |= (uint32) jair_ctx.sd_cmd[4]; + + if (sim_fseek(jair_unit[0].fileref, sd_addr, SEEK_SET) != 0) { + jair_ctx.sd_resp[0] |= 0x04; + jair_ctx.sd_resp_len = 1; + } + else if (sim_fread(&jair_ctx.sd_resp[4], 1, 512, jair_unit[0].fileref) != 512) { + jair_ctx.sd_resp[0] |= 0x04; + jair_ctx.sd_resp_len = 1; + } else { + jair_ctx.sd_resp[0] |= 0x00; + jair_ctx.sd_resp[1] |= 0xff; + jair_ctx.sd_resp[2] |= 0xff; + jair_ctx.sd_resp[3] |= 0xfe; + jair_ctx.sd_resp_len = 4 + 512 + 2; + } + + jair_ctx.sd_resp_idx = 0; + jair_ctx.sd_istate = JAIR_STATE_RESP; + jair_ctx.sd_ostate = JAIR_STATE_IDLE; + break; + + case JAIR_CMD24: + jair_ctx.sd_resp[0] |= 0x00; + jair_ctx.sd_resp_idx = 0; + jair_ctx.sd_resp_len = 1; + jair_ctx.sd_istate = JAIR_STATE_RESP; + jair_ctx.sd_ostate = JAIR_STATE_SBLK; + break; + + case JAIR_CMD8: + jair_ctx.sd_resp[0] |= 0x04; /* Illegal command **/ + jair_ctx.sd_resp_idx = 0; + jair_ctx.sd_resp_len = 1; + jair_ctx.sd_istate = JAIR_STATE_RESP; + jair_ctx.sd_ostate = JAIR_STATE_IDLE; + break; + + case JAIR_CMD55: + jair_ctx.sd_appcmd = TRUE; + jair_ctx.sd_resp[0] |= 0x01; + jair_ctx.sd_resp_idx = 0; + jair_ctx.sd_resp_len = 1; + jair_ctx.sd_istate = JAIR_STATE_RESP; + jair_ctx.sd_ostate = JAIR_STATE_IDLE; + break; + + case JAIR_ACMD41: + jair_ctx.sd_resp_idx = 0; + jair_ctx.sd_resp_len = 1; + jair_ctx.sd_istate = JAIR_STATE_RESP; + jair_ctx.sd_ostate = JAIR_STATE_IDLE; + break; + + default: + jair_ctx.sd_resp[0] |= 0x04; /* Illegal command **/ + jair_ctx.sd_resp_idx = 0; + jair_ctx.sd_resp_len = 1; + jair_ctx.sd_istate = JAIR_STATE_RESP; + jair_ctx.sd_ostate = JAIR_STATE_IDLE; + sim_printf("Command not implemented: %d\n", jair_ctx.sd_cmd[0]); + break; + } + } + break; + + case JAIR_STATE_SBLK: + if (data == 0xfe) { + jair_ctx.sd_ostate = JAIR_STATE_WBLK; + jair_ctx.sd_cmd_len = 512; + jair_ctx.sd_cmd_idx = 0; + } + break; + + case JAIR_STATE_WBLK: + if (jair_ctx.sd_cmd_idx < jair_ctx.sd_cmd_len) { + jair_ctx.sd_cmd[6 + jair_ctx.sd_cmd_idx++] = data; /* store block starting at offset 6 */ + } + else { + sd_addr = jair_ctx.sd_cmd[1] * 0x1000000; + sd_addr |= jair_ctx.sd_cmd[2] * 0x10000; + sd_addr |= (uint32) jair_ctx.sd_cmd[3] * 0x100; + sd_addr |= (uint32) jair_ctx.sd_cmd[4]; + + if (sim_fseek(jair_unit[0].fileref, sd_addr, SEEK_SET) != 0) { + jair_ctx.sd_resp[0] = 0x0b; + } + else if (sim_fwrite(&jair_ctx.sd_cmd[6], 1, 512, jair_unit[0].fileref) != 512) { + jair_ctx.sd_resp[0] = 0x0b; + } else { + jair_ctx.sd_resp[0] = 0x05; + } + + jair_ctx.sd_resp_idx = 0; + jair_ctx.sd_resp_len = 1; + jair_ctx.sd_istate = JAIR_STATE_RESP; + jair_ctx.sd_ostate = JAIR_STATE_IDLE; + } + break; + + default: + break; + } + break; + + default: + sim_printf("Invalid IO Write %02x\n", addr); + + sim_debug(ERROR_MSG, &jair_dev, "WRITE Invalid I/O Address %02x (%02x)\n", + addr & 0xFF, addr & 0x01); + break; + } + + return(0xff); +} + +static t_stat jair_set_rom(UNIT *uptr, int32 value, CONST char *cptr, void *desc) { + jair_ctx.sr_ena = TRUE; + return SCPE_OK; +} + +static t_stat jair_set_norom(UNIT *uptr, int32 value, CONST char *cptr, void *desc) { + jair_ctx.sr_ena = FALSE; + return SCPE_OK; +} + +/* +** The JAIR overlays the first 8K (minimum) of RAM with a ROM. +** +** If the ROM is enabled, writes to 0x0000-0x2000 are written to RAM, reads are +** read from the ROM. +** +** The ROM is enabled/disabled by writing a 0 (enable) or 1 (disable) to the parallel port. +*/ +static int32 jair_shadow_rom(int32 Addr, int32 rw, int32 data) +{ + if (rw == JAIR_ROM_WRITE) { + jair_ram[Addr & JAIR_ROM_MASK] = data; + } else { + if (jair_ctx.sr_ena == TRUE && Addr < JAIR_ROM_SIZE) { + return(jair_rom_v25[Addr & JAIR_ROM_MASK]); + } else { + return(jair_ram[Addr & JAIR_ROM_MASK]); + } + } + + return 0xff; +} + +/* + * Display help + */ +static t_stat jair_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr) +{ + return SCPE_OK; +} + diff --git a/Visual Studio Projects/AltairZ80.vcproj b/Visual Studio Projects/AltairZ80.vcproj index cdd30349..89ff08f4 100644 --- a/Visual Studio Projects/AltairZ80.vcproj +++ b/Visual Studio Projects/AltairZ80.vcproj @@ -366,6 +366,10 @@ RelativePath="..\AltairZ80\s100_jadedd.c" > + + diff --git a/Visual Studio Projects/AltairZ80.vcxproj b/Visual Studio Projects/AltairZ80.vcxproj index 6c72d749..6635c661 100755 --- a/Visual Studio Projects/AltairZ80.vcxproj +++ b/Visual Studio Projects/AltairZ80.vcxproj @@ -281,6 +281,7 @@ + @@ -349,4 +350,4 @@ - \ No newline at end of file + diff --git a/makefile b/makefile index 32a3514a..1167f83a 100644 --- a/makefile +++ b/makefile @@ -1894,6 +1894,7 @@ ALTAIR_OPT = -I ${ALTAIRD} ALTAIRZ80D = ${SIMHD}/AltairZ80 ALTAIRZ80 = ${ALTAIRZ80D}/altairz80_cpu.c ${ALTAIRZ80D}/altairz80_cpu_nommu.c \ + ${ALTAIRZ80D}/s100_jair.c \ ${ALTAIRZ80D}/sol20.c \ ${ALTAIRZ80D}/s100_vdm1.c \ ${ALTAIRZ80D}/mmd.c \