1
0
mirror of synced 2026-03-02 01:51:07 +00:00

Many fixes and improvements to the BIOS Extension ROM. (#33)

* Revert "Uploaded_2_9_2025"

This reverts commit ec79bbdbc9.

* Fixing DEBUG_IO builds.

* Make the IO port base a define.

* Fix CPU test to properly handle 808x vs V20.

* Improve timeout management logic.

* Improve SD Card initialization logic.

* Implement INT18h bootstrapping.

* Implementing a different test for processor type.

* Allow use with another fixed drive (eg: ESDI drive).

* Allow swapping driver ID between the BIOS disk and XTMax.

* Fix address of the ROM segment.

* Fixing missing STI at the top of the handler.

* Major rework of IO to use MOVSW.

* More code reorg and auto-detecting second drive.

* Update XTSD to use MOVSW.

* Add diagnostics program.

* Workaround for MS-DOS strange handling of interrupts.

* Use a lookup table for the memory map.

* Make the BootROM relocatable.

* Some more refactor of the Teensy code.
This commit is contained in:
Matthieu Bucchianeri
2025-02-17 15:11:37 -08:00
committed by GitHub
parent ec79bbdbc9
commit fe8385da08
15 changed files with 1199 additions and 456 deletions

View File

@@ -37,11 +37,18 @@
//
// Revision 7 01/12/2025
// - Refactor SD card I/O
// - Add support for 16-bit EMS page offsets.
// - Add support for 16-bit EMS page offsets
//
// Revision 8 01/20/2025
// - Added chip select for a second PSRAM to allow access to 16 MB of Expanded RAM
//
// Revision 9 01/26/2025
// - Add support for BIOS ROM extension (Boot ROM)
// - Add scrach registers for Boot ROM hooking
//
// Revision 10 02/17/2025
// - Use a lookup table for the memory map
//
//------------------------------------------------------------------------
//
// Copyright (c) 2024 Ted Fried
@@ -71,6 +78,8 @@
#include <stdint.h>
#include <stdio.h>
#include "bootrom.h"
// Teensy 4.1 pin assignments
//
@@ -166,7 +175,8 @@
#define EMS_TOTAL_SIZE (16*1024*1024)
#define SD_BASE 0x280 // Must be a multiple of 2.
#define SD_BASE 0x280 // Must be a multiple of 8.
#define SD_CONFIG_BYTE 0
// --------------------------------------------------------------------------------------------------
@@ -191,6 +201,9 @@ uint8_t spi_shift_out =0;
uint8_t sd_spi_datain =0;
uint32_t sd_spi_cs_n = 0x0;
uint32_t sd_spi_dataout =0;
uint8_t sd_scratch_register[6] = {0, 0, 0, 0, 0, 0};
uint16_t sd_requested_timeout = 0;
elapsedMillis sd_timeout;
uint8_t XTMax_MEM_Response_Array[16];
@@ -199,6 +212,16 @@ DMAMEM uint8_t internal_RAM1[0x60000];
uint8_t psram_cs =0;
enum Region {
Unused,
Ram,
EmsWindow,
BootRom,
SdCard
};
Region memmap[512];
// --------------------------------------------------------------------------------------------------
// --------------------------------------------------------------------------------------------------
@@ -282,6 +305,34 @@ void setup() {
//Serial.begin(9600);
// Populate the memory map.
unsigned int i;
for (i = 0; i < sizeof(memmap)/sizeof(memmap[0]); i++) {
memmap[i] = Unused;
}
for (i = 0;
i < (0xA0000 >> 11);
i++) {
memmap[i] = Ram;
}
static_assert((EMS_BASE_MEM & 0x7FF) == 0);
for (i = (EMS_BASE_MEM >> 11);
i < ((EMS_BASE_MEM+0x10000) >> 11);
i++) {
memmap[i] = EmsWindow;
}
static_assert((BOOTROM_ADDR & 0x7FF) == 0);
static_assert((sizeof(BOOTROM) % 2048) == 0, "BootROM must be in blocks of 2KB");
for (i = (BOOTROM_ADDR >> 11);
i < ((BOOTROM_ADDR+sizeof(BOOTROM)) >> 11);
i++) {
memmap[i] = BootRom;
}
memmap[(BOOTROM_ADDR+sizeof(BOOTROM)) >> 11] = SdCard;
}
@@ -507,239 +558,299 @@ inline void Internal_RAM_Write() {
// --------------------------------------------------------------------------------------------------
// --------------------------------------------------------------------------------------------------
inline void Mem_Read_Cycle() {
isa_address = ADDRESS_DATA_GPIO6_UNSCRAMBLE;
if ( (isa_address>=EMS_BASE_MEM) && (isa_address<EMS_BASE_MEM+0x10000) ) { // Expanded RAM page frame
page_base_address = (isa_address & 0xFC000);
if (page_base_address == (EMS_BASE_MEM | 0xC000)) { psram_address = (ems_frame_pointer[3]<<14) | (isa_address & 0x03FFF); }
else if (page_base_address == (EMS_BASE_MEM | 0x8000)) { psram_address = (ems_frame_pointer[2]<<14) | (isa_address & 0x03FFF); }
else if (page_base_address == (EMS_BASE_MEM | 0x4000)) { psram_address = (ems_frame_pointer[1]<<14) | (isa_address & 0x03FFF); }
else if (page_base_address == (EMS_BASE_MEM | 0x0000)) { psram_address = (ems_frame_pointer[0]<<14) | (isa_address & 0x03FFF); }
__attribute__((always_inline))
inline void Mem_Read_Cycle()
{
isa_address = ADDRESS_DATA_GPIO6_UNSCRAMBLE;
Region region = memmap[isa_address >> 11];
switch (region) {
case EmsWindow:
page_base_address = (isa_address & 0xFC000);
if (page_base_address == (EMS_BASE_MEM | 0xC000)) { psram_address = (ems_frame_pointer[3]<<14) | (isa_address & 0x03FFF); }
else if (page_base_address == (EMS_BASE_MEM | 0x8000)) { psram_address = (ems_frame_pointer[2]<<14) | (isa_address & 0x03FFF); }
else if (page_base_address == (EMS_BASE_MEM | 0x4000)) { psram_address = (ems_frame_pointer[1]<<14) | (isa_address & 0x03FFF); }
else if (page_base_address == (EMS_BASE_MEM | 0x0000)) { psram_address = (ems_frame_pointer[0]<<14) | (isa_address & 0x03FFF); }
GPIO7_DR = MUX_ADDR_n_LOW + CHRDY_OUT_LOW + trigger_out;
GPIO8_DR = sd_pin_outputs + MUX_DATA_n_HIGH + CHRDY_OE_n_LOW + DATA_OE_n_LOW ; // Assert CHRDY_n=0 to begin wait states
isa_data_out = PSRAM_Read(psram_address);
isa_data_out = PSRAM_Read(psram_address);
GPIO7_DR = GPIO7_DATA_OUT_UNSCRAMBLE + MUX_ADDR_n_LOW + CHRDY_OUT_LOW + trigger_out; // Output data
GPIO8_DR = sd_pin_outputs + MUX_DATA_n_HIGH + CHRDY_OE_n_HIGH + DATA_OE_n_LOW; // De-assert CHRDY
while ( (gpio9_int&0xF0) != 0xF0 ) { gpio9_int = GPIO9_DR; } // Wait here until cycle is complete
GPIO8_DR = sd_pin_outputs + MUX_DATA_n_HIGH + CHRDY_OE_n_HIGH + DATA_OE_n_HIGH;
}
break;
/*
XTMax_MEM_Response_Array
- Array holds value 0,1,2
0 = unitiailzed - add wait states and snoop
1 = No wait states and no response
2 = No wait states and yes respond
*/
else if (isa_address<0xA0000) { // "Conventional" RAM
case Ram:
isa_data_out = Internal_RAM_Read();
GPIO7_DR = GPIO7_DATA_OUT_UNSCRAMBLE + MUX_ADDR_n_LOW + CHRDY_OUT_LOW + trigger_out;
// If XTMax has not seen a read access to this 64 KB page yet, add wait states to give physical RAM (if present) a chance to respond
// XTMax_MEM_Response_Array
// - Array holds value 0,1,2
// 0 = unitiailzed - add wait states and snoop
// 1 = No wait states and no response
// 2 = No wait states and yes respond
//
if (XTMax_MEM_Response_Array[(isa_address>>16)] == 2) {
GPIO8_DR = sd_pin_outputs + MUX_DATA_n_HIGH + CHRDY_OE_n_HIGH + DATA_OE_n_LOW; // Physical RAM is NOT present at this page so XTMax will respond
}
else if (XTMax_MEM_Response_Array[(isa_address>>16)] == 0) {
GPIO8_DR = sd_pin_outputs + MUX_DATA_n_HIGH + CHRDY_OE_n_LOW + DATA_OE_n_HIGH ; // Assert CHRDY_n=0 to begin wait states
// If XTMax has not seen a read access to this 64 KB page yet, add wait states to give physical RAM (if present) a chance to respond
if (XTMax_MEM_Response_Array[(isa_address>>16)] == 2) {
GPIO8_DR = sd_pin_outputs + MUX_DATA_n_HIGH + CHRDY_OE_n_HIGH + DATA_OE_n_LOW; // Physical RAM is NOT present at this page so XTMax will respond
}
else if (XTMax_MEM_Response_Array[(isa_address>>16)] == 0) {
GPIO8_DR = sd_pin_outputs + MUX_DATA_n_HIGH + CHRDY_OE_n_LOW + DATA_OE_n_HIGH; // Assert CHRDY_n=0 to begin wait states
delayNanoseconds(800);
GPIO8_DR = sd_pin_outputs + MUX_DATA_n_HIGH + CHRDY_OE_n_HIGH + DATA_OE_n_HIGH; // De-assert CHRDY
gpio6_int = GPIO6_DR; // Read the data bus value currently on the ISA bus
data_in = 0xFF & ADDRESS_DATA_GPIO6_UNSCRAMBLE;
if (data_in == isa_data_out) {
if (data_in == isa_data_out) {
XTMax_MEM_Response_Array[(isa_address>>16)] = 1; // Physical RAM is present at this page so XTMax should not respond
}
else {
}
else {
XTMax_MEM_Response_Array[(isa_address>>16)] = 2;
GPIO8_DR = sd_pin_outputs + MUX_DATA_n_HIGH + CHRDY_OE_n_HIGH + DATA_OE_n_LOW; // Physical RAM is NOT present at this page so XTMax will respond
}
}
while ( (gpio9_int&0xF0) != 0xF0 ) { gpio9_int = GPIO9_DR; } // Wait here until cycle is complete
GPIO8_DR = sd_pin_outputs + MUX_DATA_n_HIGH + CHRDY_OE_n_HIGH + DATA_OE_n_HIGH;
}
return;
break;
case BootRom:
isa_data_out = BOOTROM[isa_address-BOOTROM_ADDR];
GPIO7_DR = GPIO7_DATA_OUT_UNSCRAMBLE + MUX_ADDR_n_LOW + CHRDY_OUT_LOW + trigger_out;
GPIO8_DR = sd_pin_outputs + MUX_DATA_n_HIGH + CHRDY_OE_n_HIGH + DATA_OE_n_LOW;
while ( (gpio9_int&0xF0) != 0xF0 ) { gpio9_int = GPIO9_DR; } // Wait here until cycle is complete
GPIO8_DR = sd_pin_outputs + MUX_DATA_n_HIGH + CHRDY_OE_n_HIGH + DATA_OE_n_HIGH;
break;
case SdCard:
GPIO7_DR = MUX_ADDR_n_LOW + CHRDY_OUT_LOW + trigger_out;
GPIO8_DR = sd_pin_outputs + MUX_DATA_n_HIGH + CHRDY_OE_n_LOW + DATA_OE_n_LOW ; // Assert CHRDY_n=0 to begin wait states
// Receive a byte to the SD Card
sd_spi_dataout = 0xff; SD_SPI_Cycle(); isa_data_out = sd_spi_datain;
GPIO7_DR = GPIO7_DATA_OUT_UNSCRAMBLE + MUX_ADDR_n_LOW + CHRDY_OUT_LOW + trigger_out; // Output data
GPIO8_DR = sd_pin_outputs + MUX_DATA_n_HIGH + CHRDY_OE_n_HIGH + DATA_OE_n_LOW; // De-assert CHRDY
while ( (gpio9_int&0xF0) != 0xF0 ) { gpio9_int = GPIO9_DR; } // Wait here until cycle is complete
GPIO8_DR = sd_pin_outputs + MUX_DATA_n_HIGH + CHRDY_OE_n_HIGH + DATA_OE_n_HIGH;
break;
default:
break;
}
}
// --------------------------------------------------------------------------------------------------
// --------------------------------------------------------------------------------------------------
inline void Mem_Write_Cycle() {
isa_address = ADDRESS_DATA_GPIO6_UNSCRAMBLE;
if ( (isa_address>=EMS_BASE_MEM) && (isa_address<EMS_BASE_MEM+0x10000) ) { // Expanded RAM page frame
page_base_address = (isa_address & 0xFC000);
__attribute__((always_inline))
inline void Mem_Write_Cycle()
{
isa_address = ADDRESS_DATA_GPIO6_UNSCRAMBLE;
Region region = memmap[isa_address >> 11];
switch (region) {
case EmsWindow:
page_base_address = (isa_address & 0xFC000);
if (page_base_address == (EMS_BASE_MEM | 0xC000)) { psram_address = (ems_frame_pointer[3]<<14) | (isa_address & 0x03FFF); }
else if (page_base_address == (EMS_BASE_MEM | 0x8000)) { psram_address = (ems_frame_pointer[2]<<14) | (isa_address & 0x03FFF); }
else if (page_base_address == (EMS_BASE_MEM | 0x4000)) { psram_address = (ems_frame_pointer[1]<<14) | (isa_address & 0x03FFF); }
else if (page_base_address == (EMS_BASE_MEM | 0x0000)) { psram_address = (ems_frame_pointer[0]<<14) | (isa_address & 0x03FFF); }
if (page_base_address == (EMS_BASE_MEM | 0xC000)) { psram_address = (ems_frame_pointer[3]<<14) | (isa_address & 0x03FFF); }
else if (page_base_address == (EMS_BASE_MEM | 0x8000)) { psram_address = (ems_frame_pointer[2]<<14) | (isa_address & 0x03FFF); }
else if (page_base_address == (EMS_BASE_MEM | 0x4000)) { psram_address = (ems_frame_pointer[1]<<14) | (isa_address & 0x03FFF); }
else if (page_base_address == (EMS_BASE_MEM | 0x0000)) { psram_address = (ems_frame_pointer[0]<<14) | (isa_address & 0x03FFF); }
GPIO7_DR = GPIO7_DATA_OUT_UNSCRAMBLE + MUX_ADDR_n_HIGH + CHRDY_OUT_LOW + trigger_out;
GPIO8_DR = sd_pin_outputs + MUX_DATA_n_LOW + CHRDY_OE_n_LOW + DATA_OE_n_HIGH; // Steer data mux to Data[7:0] and Assert CHRDY_n=0 to begin wait states
delayNanoseconds(10); // Wait some time for buffers to switch from address to data
gpio6_int = GPIO6_DR;
data_in = 0xFF & ADDRESS_DATA_GPIO6_UNSCRAMBLE;
PSRAM_Write(psram_address , data_in);
PSRAM_Write(psram_address , data_in);
GPIO8_DR = sd_pin_outputs + MUX_DATA_n_LOW + CHRDY_OE_n_HIGH + DATA_OE_n_HIGH; // De-assert CHRDY
while ( (gpio9_int&0xF0) != 0xF0 ) { // Wait here until cycle is complete
gpio6_int = GPIO6_DR;
gpio9_int = GPIO9_DR;
}
GPIO7_DR = GPIO7_DATA_OUT_UNSCRAMBLE + MUX_ADDR_n_LOW + CHRDY_OUT_LOW + trigger_out;
GPIO8_DR = sd_pin_outputs + MUX_DATA_n_HIGH + CHRDY_OE_n_HIGH + DATA_OE_n_HIGH;
break;
case Ram:
GPIO7_DR = GPIO7_DATA_OUT_UNSCRAMBLE + MUX_ADDR_n_HIGH + CHRDY_OUT_LOW + trigger_out;
GPIO8_DR = sd_pin_outputs + MUX_DATA_n_LOW + CHRDY_OE_n_HIGH + DATA_OE_n_HIGH;
while ( (gpio9_int&0xF0) != 0xF0 ) { // Wait here until cycle is complete
gpio6_int = GPIO6_DR;
gpio9_int = GPIO9_DR;
}
Internal_RAM_Write();
GPIO7_DR = GPIO7_DATA_OUT_UNSCRAMBLE + MUX_ADDR_n_LOW + CHRDY_OUT_LOW + trigger_out;
GPIO8_DR = sd_pin_outputs + MUX_DATA_n_HIGH + CHRDY_OE_n_HIGH + DATA_OE_n_HIGH;
break;
case SdCard:
GPIO7_DR = GPIO7_DATA_OUT_UNSCRAMBLE + MUX_ADDR_n_HIGH + CHRDY_OUT_LOW + trigger_out;
GPIO8_DR = sd_pin_outputs + MUX_DATA_n_LOW + CHRDY_OE_n_LOW + DATA_OE_n_HIGH; // Steer data mux to Data[7:0] and Assert CHRDY_n=0 to begin wait states
delayNanoseconds(10); // Wait some time for buffers to switch from address to data
gpio6_int = GPIO6_DR;
data_in = 0xFF & ADDRESS_DATA_GPIO6_UNSCRAMBLE;
// Send a byte to the SD Card
sd_spi_dataout = data_in; SD_SPI_Cycle();
GPIO8_DR = sd_pin_outputs + MUX_DATA_n_LOW + CHRDY_OE_n_HIGH + DATA_OE_n_HIGH; // De-assert CHRDY
while ( (gpio9_int&0xF0) != 0xF0 ) { // Wait here until cycle is complete
gpio6_int = GPIO6_DR;
gpio6_int = GPIO6_DR;
gpio9_int = GPIO9_DR;
}
GPIO7_DR = GPIO7_DATA_OUT_UNSCRAMBLE + MUX_ADDR_n_LOW + CHRDY_OUT_LOW + trigger_out;
GPIO8_DR = sd_pin_outputs + MUX_DATA_n_HIGH + CHRDY_OE_n_HIGH + DATA_OE_n_HIGH;
}
else if (isa_address<0xA0000) { // XTMax stores the full 640 KB conventional memory
GPIO7_DR = GPIO7_DATA_OUT_UNSCRAMBLE + MUX_ADDR_n_HIGH + CHRDY_OUT_LOW + trigger_out;
GPIO8_DR = sd_pin_outputs + MUX_DATA_n_LOW + CHRDY_OE_n_HIGH + DATA_OE_n_HIGH;
while ( (gpio9_int&0xF0) != 0xF0 ) { // Wait here until cycle is complete
gpio6_int = GPIO6_DR;
gpio9_int = GPIO9_DR;
}
Internal_RAM_Write();
GPIO7_DR = GPIO7_DATA_OUT_UNSCRAMBLE + MUX_ADDR_n_LOW + CHRDY_OUT_LOW + trigger_out;
GPIO8_DR = sd_pin_outputs + MUX_DATA_n_HIGH + CHRDY_OE_n_HIGH + DATA_OE_n_HIGH;
}
return;
}
// --------------------------------------------------------------------------------------------------
// --------------------------------------------------------------------------------------------------
inline void IO_Read_Cycle() {
isa_address = 0xFFFF & ADDRESS_DATA_GPIO6_UNSCRAMBLE;
if ((isa_address&0x0FF8)==EMS_BASE_IO ) { // Location of 16 KB Expanded Memory page frame pointers
switch (isa_address) {
case EMS_BASE_IO : isa_data_out = ems_frame_pointer[0]; break;
case EMS_BASE_IO+1: isa_data_out = ems_frame_pointer[0] >> 8; break;
case EMS_BASE_IO+2: isa_data_out = ems_frame_pointer[1]; break;
case EMS_BASE_IO+3: isa_data_out = ems_frame_pointer[1] >> 8; break;
case EMS_BASE_IO+4: isa_data_out = ems_frame_pointer[2]; break;
case EMS_BASE_IO+5: isa_data_out = ems_frame_pointer[2] >> 8; break;
case EMS_BASE_IO+6: isa_data_out = ems_frame_pointer[3]; break;
case EMS_BASE_IO+7: isa_data_out = ems_frame_pointer[3] >> 8; break;
}
GPIO7_DR = GPIO7_DATA_OUT_UNSCRAMBLE + MUX_ADDR_n_LOW + CHRDY_OUT_LOW + trigger_out;
GPIO8_DR = sd_pin_outputs + MUX_DATA_n_HIGH + CHRDY_OE_n_HIGH + DATA_OE_n_HIGH;
break;
default:
break;
}
}
// --------------------------------------------------------------------------------------------------
// --------------------------------------------------------------------------------------------------
__attribute__((always_inline))
inline void IO_Read_Cycle()
{
isa_address = 0xFFFF & ADDRESS_DATA_GPIO6_UNSCRAMBLE;
uint16_t base_address = isa_address&0x0FF8;
switch (base_address) {
case EMS_BASE_IO:
switch (isa_address) {
case EMS_BASE_IO : isa_data_out = ems_frame_pointer[0]; break;
case EMS_BASE_IO+1: isa_data_out = ems_frame_pointer[0] >> 8; break;
case EMS_BASE_IO+2: isa_data_out = ems_frame_pointer[1]; break;
case EMS_BASE_IO+3: isa_data_out = ems_frame_pointer[1] >> 8; break;
case EMS_BASE_IO+4: isa_data_out = ems_frame_pointer[2]; break;
case EMS_BASE_IO+5: isa_data_out = ems_frame_pointer[2] >> 8; break;
case EMS_BASE_IO+6: isa_data_out = ems_frame_pointer[3]; break;
case EMS_BASE_IO+7: isa_data_out = ems_frame_pointer[3] >> 8; break;
}
GPIO7_DR = GPIO7_DATA_OUT_UNSCRAMBLE + MUX_ADDR_n_LOW + CHRDY_OUT_LOW + trigger_out;
GPIO8_DR = sd_pin_outputs + MUX_DATA_n_HIGH + CHRDY_OE_n_HIGH + DATA_OE_n_LOW;
while ( (gpio9_int&0xF0) != 0xF0 ) { gpio9_int = GPIO9_DR; } // Wait here until cycle is complete
GPIO8_DR = sd_pin_outputs + MUX_DATA_n_HIGH + CHRDY_OE_n_HIGH + DATA_OE_n_HIGH;
}
else if ((isa_address&0x0FFE)==SD_BASE ) { // Location of SD Card registers
// Both registers serve the same function (to allow use of Word I/O)
sd_spi_dataout = 0xff;
SD_SPI_Cycle();
isa_data_out = sd_spi_datain;
break;
case SD_BASE:
switch (isa_address) {
case SD_BASE+0: sd_spi_dataout = 0xff; SD_SPI_Cycle(); isa_data_out = sd_spi_datain; break;
case SD_BASE+1: isa_data_out = SD_CONFIG_BYTE; break;
case SD_BASE+2: isa_data_out = sd_scratch_register[0]; break;
case SD_BASE+3: isa_data_out = sd_scratch_register[1]; break;
case SD_BASE+4: isa_data_out = sd_scratch_register[2]; break;
case SD_BASE+5: isa_data_out = sd_scratch_register[3]; break;
case SD_BASE+6: isa_data_out = sd_scratch_register[4]; break;
case SD_BASE+7: isa_data_out = sd_timeout >= sd_requested_timeout; break;
default: isa_data_out = 0xff; break;
}
GPIO7_DR = GPIO7_DATA_OUT_UNSCRAMBLE + MUX_ADDR_n_LOW + CHRDY_OUT_LOW + trigger_out;
GPIO8_DR = sd_pin_outputs + MUX_DATA_n_HIGH + CHRDY_OE_n_HIGH + DATA_OE_n_LOW;
while ( (gpio9_int&0xF0) != 0xF0 ) { gpio9_int = GPIO9_DR; } // Wait here until cycle is complete
GPIO8_DR = sd_pin_outputs + MUX_DATA_n_HIGH + CHRDY_OE_n_HIGH + DATA_OE_n_HIGH;
}
return;
break;
}
}
// --------------------------------------------------------------------------------------------------
// --------------------------------------------------------------------------------------------------
inline void IO_Write_Cycle() {
isa_address = 0xFFFF & ADDRESS_DATA_GPIO6_UNSCRAMBLE;
if ((isa_address&0x0FF8)==EMS_BASE_IO ) { // Location of 16 KB Expanded Memory page frame pointers
__attribute__((always_inline))
inline void IO_Write_Cycle()
{
isa_address = 0xFFFF & ADDRESS_DATA_GPIO6_UNSCRAMBLE;
uint16_t base_address = isa_address&0x0FF8;
switch (base_address) {
case EMS_BASE_IO:
GPIO7_DR = GPIO7_DATA_OUT_UNSCRAMBLE + MUX_ADDR_n_HIGH + CHRDY_OUT_LOW + trigger_out;
GPIO8_DR = sd_pin_outputs + MUX_DATA_n_LOW + CHRDY_OE_n_HIGH + DATA_OE_n_HIGH;
while ( (gpio9_int&0xF0) != 0xF0 ) { // Wait here until cycle is complete
gpio6_int = GPIO6_DR;
gpio6_int = GPIO6_DR;
gpio9_int = GPIO9_DR;
}
}
data_in = 0xFF & ADDRESS_DATA_GPIO6_UNSCRAMBLE;
switch (isa_address) {
case EMS_BASE_IO : ems_frame_pointer[0] = (ems_frame_pointer[0] & 0xFF00) | data_in; break;
case EMS_BASE_IO+1: ems_frame_pointer[0] = (ems_frame_pointer[0] & 0x00FF) | ((uint16_t)data_in << 8); break;
case EMS_BASE_IO+2: ems_frame_pointer[1] = (ems_frame_pointer[1] & 0xFF00) | data_in; break;
case EMS_BASE_IO+3: ems_frame_pointer[1] = (ems_frame_pointer[1] & 0x00FF) | ((uint16_t)data_in << 8); break;
case EMS_BASE_IO+4: ems_frame_pointer[2] = (ems_frame_pointer[2] & 0xFF00) | data_in; break;
case EMS_BASE_IO+5: ems_frame_pointer[2] = (ems_frame_pointer[2] & 0x00FF) | ((uint16_t)data_in << 8); break;
case EMS_BASE_IO+6: ems_frame_pointer[3] = (ems_frame_pointer[3] & 0xFF00) | data_in; break;
case EMS_BASE_IO+7: ems_frame_pointer[3] = (ems_frame_pointer[3] & 0x00FF) | ((uint16_t)data_in << 8); break;
case EMS_BASE_IO : ems_frame_pointer[0] = (ems_frame_pointer[0] & 0xFF00) | data_in; break;
case EMS_BASE_IO+1: ems_frame_pointer[0] = (ems_frame_pointer[0] & 0x00FF) | ((uint16_t)data_in << 8); break;
case EMS_BASE_IO+2: ems_frame_pointer[1] = (ems_frame_pointer[1] & 0xFF00) | data_in; break;
case EMS_BASE_IO+3: ems_frame_pointer[1] = (ems_frame_pointer[1] & 0x00FF) | ((uint16_t)data_in << 8); break;
case EMS_BASE_IO+4: ems_frame_pointer[2] = (ems_frame_pointer[2] & 0xFF00) | data_in; break;
case EMS_BASE_IO+5: ems_frame_pointer[2] = (ems_frame_pointer[2] & 0x00FF) | ((uint16_t)data_in << 8); break;
case EMS_BASE_IO+6: ems_frame_pointer[3] = (ems_frame_pointer[3] & 0xFF00) | data_in; break;
case EMS_BASE_IO+7: ems_frame_pointer[3] = (ems_frame_pointer[3] & 0x00FF) | ((uint16_t)data_in << 8); break;
}
GPIO7_DR = GPIO7_DATA_OUT_UNSCRAMBLE + MUX_ADDR_n_LOW + CHRDY_OUT_LOW + trigger_out;
GPIO8_DR = sd_pin_outputs + MUX_DATA_n_HIGH + CHRDY_OE_n_HIGH + DATA_OE_n_HIGH;
}
else if ((isa_address&0x0FFC)==SD_BASE ) { // Location of SD Card registers
break;
case SD_BASE:
GPIO7_DR = GPIO7_DATA_OUT_UNSCRAMBLE + MUX_ADDR_n_HIGH + CHRDY_OUT_LOW + trigger_out;
GPIO8_DR = sd_pin_outputs + MUX_DATA_n_LOW + CHRDY_OE_n_HIGH + DATA_OE_n_HIGH;
delayNanoseconds(50); // Give some time for write data to be available after IOWR_n goes low
gpio6_int = GPIO6_DR;
data_in = 0xFF & ADDRESS_DATA_GPIO6_UNSCRAMBLE;
switch (isa_address) {
case SD_BASE: // First two registers serve the same function (to allow use of Word I/O)
case SD_BASE+1: sd_spi_dataout = data_in; SD_SPI_Cycle(); break;
case SD_BASE+2: sd_spi_cs_n = data_in&0x1; break;
case SD_BASE+0: sd_spi_dataout = data_in; SD_SPI_Cycle(); break;
case SD_BASE+1: sd_spi_cs_n = data_in&0x1; break;
case SD_BASE+2: sd_scratch_register[0] = data_in; break;
case SD_BASE+3: sd_scratch_register[1] = data_in; break;
case SD_BASE+4: sd_scratch_register[2] = data_in; break;
case SD_BASE+5: sd_scratch_register[3] = data_in; break;
case SD_BASE+6: sd_scratch_register[4] = data_in; break;
case SD_BASE+7: sd_timeout = 0; sd_requested_timeout = data_in * 10; break;
}
//gpio9_int = GPIO9_DR;
while ( (gpio9_int&0xF0) != 0xF0 ) { // Wait here until cycle is complete
gpio6_int = GPIO6_DR;
gpio6_int = GPIO6_DR;
gpio9_int = GPIO9_DR;
}
}
sd_pin_outputs = (sd_spi_cs_n<<17); // SD_CS_n - SD_CLK - SD_MOSI
GPIO7_DR = GPIO7_DATA_OUT_UNSCRAMBLE + MUX_ADDR_n_LOW + CHRDY_OUT_LOW + trigger_out;
GPIO8_DR = sd_pin_outputs + MUX_DATA_n_HIGH + CHRDY_OE_n_HIGH + DATA_OE_n_HIGH;
}
return;
break;
}
}
@@ -749,23 +860,22 @@ inline void IO_Write_Cycle() {
// Main loop
//
// -------------------------------------------------
void loop() {
// Give Teensy 4.1 a moment
//
//delay (1000);
void loop()
{
PSRAM_Configure();
while (1) {
gpio6_int = GPIO6_DR;
gpio9_int = GPIO9_DR;
if ((gpio9_int&0x80000010)==0) IO_Read_Cycle(); // Isolate and check AEN and IO Rd/Wr
else if ((gpio9_int&0x80000020)==0) IO_Write_Cycle();
else if ((gpio9_int&0x00000040)==0) Mem_Read_Cycle();
else if ((gpio9_int&0x00000080)==0) Mem_Write_Cycle();
gpio6_int = GPIO6_DR;
gpio9_int = GPIO9_DR;
switch (gpio9_int&0x800000F0) {
case 0x000000E0: IO_Read_Cycle(); break; // ~AEN + ~IORD
case 0x000000D0: IO_Write_Cycle(); break; // ~AEN + ~IOWR
case 0x000000B0:
case 0x800000B0: Mem_Read_Cycle(); break; // ~MEMRD
case 0x00000070:
case 0x80000070: Mem_Write_Cycle(); break; // ~MEMWR
}
}
}
}

130
XTMax/Code/XTMax/bootrom.h Normal file
View File

@@ -0,0 +1,130 @@
#define BOOTROM_ADDR 0xce000
unsigned char BOOTROM[] = {
85, 170, 4, 6, 80, 81, 82, 250, 184, 152, 5, 232, 0, 5, 184, 218,
5, 232, 250, 4, 140, 200, 232, 18, 5, 184, 145, 5, 232, 239, 4, 184,
0, 0, 232, 6, 5, 184, 149, 5, 232, 227, 4, 232, 228, 3, 115, 3,
233, 140, 0, 49, 192, 142, 192, 38, 161, 78, 0, 186, 131, 2, 239, 38,
161, 76, 0, 186, 133, 2, 239, 140, 200, 38, 163, 78, 0, 184, 197, 0,
38, 163, 76, 0, 184, 55, 6, 232, 180, 4, 184, 64, 0, 142, 192, 38,
160, 117, 0, 4, 128, 186, 130, 2, 238, 80, 232, 190, 4, 184, 149, 5,
232, 155, 4, 184, 82, 6, 232, 149, 4, 38, 254, 6, 117, 0, 38, 160,
117, 0, 48, 228, 232, 164, 4, 184, 149, 5, 232, 129, 4, 88, 49, 201,
142, 193, 60, 128, 117, 15, 140, 200, 38, 163, 6, 1, 184, 170, 1, 38,
163, 4, 1, 235, 13, 140, 200, 38, 163, 26, 1, 184, 170, 1, 38, 163,
24, 1, 140, 200, 38, 163, 98, 0, 184, 127, 3, 38, 163, 96, 0, 251,
90, 89, 88, 7, 203, 251, 85, 86, 80, 82, 186, 130, 2, 236, 90, 56,
194, 88, 116, 58, 137, 197, 137, 214, 156, 14, 184, 238, 0, 80, 186, 131,
2, 237, 80, 186, 133, 2, 237, 80, 137, 232, 137, 242, 250, 203, 251, 156,
80, 137, 240, 60, 128, 114, 19, 137, 232, 128, 252, 8, 117, 12, 6, 184,
64, 0, 142, 192, 38, 138, 22, 117, 0, 7, 88, 157, 235, 58, 128, 252,
25, 126, 5, 232, 122, 0, 235, 34, 128, 252, 1, 116, 10, 128, 252, 21,
116, 5, 190, 58, 1, 235, 3, 190, 72, 1, 86, 137, 222, 136, 227, 48,
255, 208, 227, 135, 222, 46, 255, 164, 92, 1, 140, 197, 190, 64, 0, 142,
198, 38, 136, 38, 116, 0, 142, 197, 137, 229, 139, 118, 8, 86, 115, 4,
157, 249, 235, 2, 157, 248, 94, 93, 251, 202, 2, 0, 100, 3, 186, 1,
206, 1, 97, 2, 37, 3, 144, 1, 144, 1, 144, 1, 64, 3, 100, 3,
144, 1, 144, 1, 86, 3, 100, 3, 144, 1, 144, 1, 100, 3, 100, 3,
144, 1, 144, 1, 100, 3, 102, 3, 144, 1, 144, 1, 144, 1, 100, 3,
80, 184, 109, 6, 232, 119, 3, 88, 80, 136, 224, 48, 228, 232, 139, 3,
184, 149, 5, 232, 104, 3, 88, 233, 201, 1, 0, 4, 255, 0, 0, 255,
255, 0, 200, 0, 0, 0, 0, 0, 63, 0, 6, 189, 64, 0, 142, 197,
48, 228, 38, 134, 38, 116, 0, 132, 228, 116, 1, 249, 7, 195, 132, 192,
117, 3, 233, 158, 1, 80, 48, 228, 137, 198, 83, 232, 227, 1, 137, 197,
1, 240, 137, 222, 131, 211, 0, 232, 10, 2, 91, 88, 115, 3, 233, 134,
1, 30, 83, 81, 82, 87, 80, 137, 193, 48, 237, 140, 200, 142, 216, 137,
223, 186, 129, 2, 176, 0, 238, 81, 137, 232, 137, 243, 177, 81, 232, 213,
2, 114, 60, 186, 135, 2, 176, 10, 238, 186, 128, 2, 236, 60, 254, 116,
10, 186, 135, 2, 236, 132, 192, 117, 38, 235, 238, 185, 0, 1, 86, 190,
0, 8, 252, 243, 165, 173, 94, 131, 197, 1, 131, 214, 0, 89, 226, 199,
186, 129, 2, 176, 1, 238, 88, 95, 90, 89, 91, 31, 233, 44, 1, 186,
129, 2, 176, 1, 238, 89, 88, 40, 200, 95, 90, 89, 91, 31, 233, 14,
1, 132, 192, 117, 3, 233, 11, 1, 80, 48, 228, 137, 198, 83, 232, 80,
1, 137, 197, 1, 240, 137, 222, 131, 211, 0, 232, 119, 1, 91, 88, 115,
3, 233, 243, 0, 30, 83, 81, 82, 87, 80, 137, 193, 48, 237, 137, 223,
140, 192, 142, 216, 140, 200, 142, 192, 186, 129, 2, 176, 0, 238, 81, 137,
232, 137, 243, 177, 88, 232, 62, 2, 114, 102, 186, 128, 2, 176, 254, 238,
185, 0, 1, 86, 137, 254, 191, 0, 8, 252, 243, 165, 137, 247, 94, 186,
135, 2, 176, 25, 238, 186, 128, 2, 236, 60, 255, 117, 10, 186, 135, 2,
236, 132, 192, 117, 59, 235, 238, 36, 31, 60, 5, 117, 51, 186, 135, 2,
176, 25, 238, 186, 128, 2, 236, 132, 192, 117, 10, 186, 135, 2, 236, 132,
192, 117, 29, 235, 238, 131, 197, 1, 131, 214, 0, 89, 226, 160, 186, 129,
2, 176, 1, 238, 140, 216, 142, 192, 88, 95, 90, 89, 91, 31, 235, 107,
186, 129, 2, 176, 1, 238, 89, 140, 216, 142, 192, 88, 40, 200, 95, 90,
89, 91, 31, 235, 74, 132, 192, 116, 74, 80, 48, 228, 137, 197, 83, 232,
143, 0, 1, 232, 131, 211, 0, 232, 186, 0, 91, 88, 114, 57, 235, 59,
182, 254, 6, 184, 64, 0, 142, 192, 38, 138, 22, 117, 0, 7, 181, 254,
177, 255, 49, 192, 248, 195, 80, 83, 232, 102, 0, 232, 150, 0, 91, 88,
114, 21, 235, 23, 235, 21, 180, 3, 232, 160, 0, 135, 209, 248, 195, 180,
170, 249, 195, 180, 1, 249, 195, 180, 4, 249, 195, 48, 228, 248, 195, 49,
192, 142, 216, 142, 192, 185, 0, 1, 191, 0, 124, 243, 171, 186, 130, 2,
236, 136, 194, 48, 246, 184, 1, 2, 185, 1, 0, 187, 0, 124, 205, 19,
129, 62, 254, 125, 85, 170, 117, 15, 184, 138, 6, 232, 96, 1, 49, 192,
142, 192, 234, 0, 124, 0, 0, 184, 164, 6, 232, 81, 1, 251, 244, 235,
253, 49, 192, 49, 219, 82, 81, 82, 136, 200, 36, 192, 209, 224, 209, 224,
136, 232, 185, 255, 0, 247, 225, 90, 136, 241, 48, 237, 1, 200, 177, 63,
247, 225, 89, 81, 48, 237, 128, 225, 63, 73, 1, 200, 131, 210, 0, 137,
211, 89, 90, 195, 81, 82, 232, 18, 0, 57, 211, 114, 10, 119, 4, 57,
200, 114, 4, 249, 90, 89, 195, 248, 90, 89, 195, 186, 250, 0, 185, 63,
197, 195, 80, 30, 83, 81, 82, 86, 140, 200, 142, 216, 186, 129, 2, 176,
1, 238, 185, 1, 0, 186, 160, 134, 180, 134, 205, 21, 186, 128, 2, 176,
255, 185, 10, 0, 238, 226, 253, 186, 129, 2, 176, 0, 238, 187, 10, 0,
190, 206, 4, 185, 1, 0, 180, 1, 232, 92, 0, 115, 15, 49, 201, 186,
32, 78, 180, 134, 205, 21, 75, 117, 231, 249, 235, 52, 190, 212, 4, 185,
5, 0, 180, 1, 232, 64, 0, 114, 39, 186, 135, 2, 176, 250, 238, 190,
218, 4, 185, 1, 0, 180, 1, 232, 45, 0, 190, 224, 4, 185, 1, 0,
180, 0, 232, 34, 0, 115, 9, 186, 135, 2, 236, 132, 192, 116, 224, 249,
94, 90, 89, 91, 31, 114, 8, 184, 245, 5, 232, 113, 0, 88, 195, 184,
24, 6, 232, 105, 0, 88, 195, 186, 128, 2, 176, 255, 238, 81, 185, 6,
0, 252, 172, 238, 226, 252, 185, 8, 0, 236, 60, 255, 225, 251, 89, 56,
224, 118, 3, 249, 235, 4, 248, 236, 226, 253, 176, 255, 238, 195, 64, 0,
0, 0, 0, 149, 72, 0, 0, 1, 170, 135, 119, 0, 0, 0, 0, 1,
105, 64, 0, 0, 0, 1, 186, 128, 2, 80, 176, 255, 238, 136, 200, 238,
136, 248, 238, 136, 216, 238, 88, 134, 224, 238, 134, 224, 238, 176, 1, 238,
185, 8, 0, 236, 60, 255, 225, 251, 132, 192, 116, 1, 249, 195, 156, 30,
83, 86, 137, 198, 140, 200, 142, 216, 180, 14, 49, 219, 252, 172, 8, 192,
116, 4, 205, 16, 235, 247, 94, 91, 31, 157, 195, 156, 30, 83, 81, 82,
86, 137, 194, 140, 200, 142, 216, 49, 219, 252, 137, 214, 177, 12, 211, 238,
131, 230, 15, 138, 132, 129, 5, 180, 14, 205, 16, 137, 214, 177, 8, 211,
238, 131, 230, 15, 138, 132, 129, 5, 180, 14, 205, 16, 137, 214, 177, 4,
211, 238, 131, 230, 15, 138, 132, 129, 5, 180, 14, 205, 16, 137, 214, 131,
230, 15, 138, 132, 129, 5, 180, 14, 205, 16, 94, 90, 89, 91, 31, 157,
195, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 65, 66, 67, 68, 69,
70, 58, 0, 32, 0, 13, 10, 0, 66, 111, 111, 116, 82, 79, 77, 32,
102, 111, 114, 32, 88, 84, 77, 97, 120, 32, 118, 49, 46, 48, 13, 10,
67, 111, 112, 121, 114, 105, 103, 104, 116, 32, 40, 99, 41, 32, 50, 48,
50, 53, 32, 77, 97, 116, 116, 104, 105, 101, 117, 32, 66, 117, 99, 99,
104, 105, 97, 110, 101, 114, 105, 13, 10, 0, 82, 79, 77, 32, 66, 97,
115, 101, 32, 65, 100, 100, 114, 101, 115, 115, 32, 32, 32, 32, 32, 32,
32, 32, 61, 32, 0, 83, 68, 32, 67, 97, 114, 100, 32, 105, 110, 105,
116, 105, 97, 108, 105, 122, 101, 100, 32, 115, 117, 99, 99, 101, 115, 115,
102, 117, 108, 108, 121, 13, 10, 0, 83, 68, 32, 67, 97, 114, 100, 32,
102, 97, 105, 108, 101, 100, 32, 116, 111, 32, 105, 110, 105, 116, 105, 97,
108, 105, 122, 101, 13, 10, 0, 70, 105, 120, 101, 100, 32, 68, 105, 115,
107, 32, 73, 68, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 61,
32, 0, 84, 111, 116, 97, 108, 32, 70, 105, 120, 101, 100, 32, 68, 105,
115, 107, 32, 68, 114, 105, 118, 101, 115, 32, 61, 32, 0, 85, 110, 115,
117, 112, 112, 111, 114, 116, 101, 100, 32, 73, 78, 84, 49, 51, 104, 32,
70, 117, 110, 99, 116, 105, 111, 110, 32, 0, 66, 111, 111, 116, 105, 110,
103, 32, 102, 114, 111, 109, 32, 83, 68, 32, 67, 97, 114, 100, 46, 46,
46, 13, 10, 0, 78, 111, 116, 32, 98, 111, 111, 116, 97, 98, 108, 101,
13, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 189};