mirror of
https://github.com/dingusdev/dingusppc.git
synced 2024-11-04 20:06:35 +00:00
Initial support for Nubus/PDS.
This commit is contained in:
parent
5b08f283e5
commit
ee9448cbc6
@ -6,6 +6,7 @@ file(GLOB SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/*.cpp"
|
|||||||
"${CMAKE_CURRENT_SOURCE_DIR}/common/*.cpp"
|
"${CMAKE_CURRENT_SOURCE_DIR}/common/*.cpp"
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/common/adb/*.cpp"
|
"${CMAKE_CURRENT_SOURCE_DIR}/common/adb/*.cpp"
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/common/i2c/*.cpp"
|
"${CMAKE_CURRENT_SOURCE_DIR}/common/i2c/*.cpp"
|
||||||
|
"${CMAKE_CURRENT_SOURCE_DIR}/common/nubus/*.cpp"
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/common/pci/*.cpp"
|
"${CMAKE_CURRENT_SOURCE_DIR}/common/pci/*.cpp"
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/common/scsi/*.cpp"
|
"${CMAKE_CURRENT_SOURCE_DIR}/common/scsi/*.cpp"
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/ethernet/*.cpp"
|
"${CMAKE_CURRENT_SOURCE_DIR}/ethernet/*.cpp"
|
||||||
|
@ -39,6 +39,8 @@ enum HWCompType {
|
|||||||
I2C_DEV = 1ULL << 9, /* I2C device */
|
I2C_DEV = 1ULL << 9, /* I2C device */
|
||||||
ADB_HOST = 1ULL << 12, /* ADB host */
|
ADB_HOST = 1ULL << 12, /* ADB host */
|
||||||
ADB_DEV = 1ULL << 13, /* ADB device */
|
ADB_DEV = 1ULL << 13, /* ADB device */
|
||||||
|
PDS_DEV = 1ULL << 14, /* processor direct slot (PDS) device */
|
||||||
|
NUBUS_DEV = 1ULL << 15, /* Nubus device */
|
||||||
INT_CTRL = 1ULL << 16, /* interrupt controller */
|
INT_CTRL = 1ULL << 16, /* interrupt controller */
|
||||||
SCSI_BUS = 1ULL << 20, /* SCSI bus */
|
SCSI_BUS = 1ULL << 20, /* SCSI bus */
|
||||||
SCSI_HOST = 1ULL << 21, /* SCSI host adapter */
|
SCSI_HOST = 1ULL << 21, /* SCSI host adapter */
|
||||||
|
146
devices/common/nubus/nubusutils.cpp
Normal file
146
devices/common/nubus/nubusutils.cpp
Normal file
@ -0,0 +1,146 @@
|
|||||||
|
/*
|
||||||
|
DingusPPC - The Experimental PowerPC Macintosh emulator
|
||||||
|
Copyright (C) 2018-22 divingkatae and maximum
|
||||||
|
(theweirdo) spatium
|
||||||
|
|
||||||
|
(Contact divingkatae#1017 or powermax#2286 on Discord for more info)
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <devices/common/nubus/nubusutils.h>
|
||||||
|
#include <devices/memctrl/memctrlbase.h>
|
||||||
|
#include <machines/machinebase.h>
|
||||||
|
#include <loguru.hpp>
|
||||||
|
#include "memaccess.h"
|
||||||
|
|
||||||
|
#include <cinttypes>
|
||||||
|
#include <fstream>
|
||||||
|
|
||||||
|
uint32_t calculate_rom_crc(uint8_t *data_ptr, int length)
|
||||||
|
{
|
||||||
|
uint32_t sum = 0;
|
||||||
|
|
||||||
|
for (int i = 0; i < length; i++) {
|
||||||
|
// rotate sum left by one bit
|
||||||
|
if (sum & 0x80000000UL) {
|
||||||
|
sum = (sum << 1) | 1;
|
||||||
|
} else {
|
||||||
|
sum = (sum << 1) | 0;
|
||||||
|
}
|
||||||
|
sum += data_ptr[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
return sum;
|
||||||
|
}
|
||||||
|
|
||||||
|
int load_declaration_rom(const std::string rom_path, int slot_num)
|
||||||
|
{
|
||||||
|
std::ifstream rom_file;
|
||||||
|
|
||||||
|
int result = 0;
|
||||||
|
|
||||||
|
try {
|
||||||
|
rom_file.open(rom_path, std::ios::in | std::ios::binary);
|
||||||
|
if (rom_file.fail()) {
|
||||||
|
throw std::runtime_error("could not open declaration ROM image");
|
||||||
|
}
|
||||||
|
|
||||||
|
// determine image size
|
||||||
|
rom_file.seekg(0, std::ios::end);
|
||||||
|
uint32_t rom_size = rom_file.tellg();
|
||||||
|
|
||||||
|
// load it
|
||||||
|
auto rom_data = std::unique_ptr<uint8_t[]> (new uint8_t[rom_size]);
|
||||||
|
rom_file.seekg(0, std::ios::beg);
|
||||||
|
rom_file.read((char *)rom_data.get(), rom_size);
|
||||||
|
|
||||||
|
// verify image data
|
||||||
|
uint8_t byte_lane = rom_data[rom_size - 1];
|
||||||
|
if ((byte_lane & 0xF) != ((byte_lane >> 4) ^ 0xF)) {
|
||||||
|
throw std::runtime_error("invalid byte lane value");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (READ_DWORD_BE_A(&rom_data[rom_size - 6]) != 0x5A932BC7UL) {
|
||||||
|
throw std::runtime_error("invalid test pattern");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rom_data[rom_size - 7] != 1) {
|
||||||
|
throw std::runtime_error("unsupported format");
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t crc = READ_DWORD_BE_A(&rom_data[rom_size - 12]);
|
||||||
|
int hdr_length = READ_DWORD_BE_A(&rom_data[rom_size - 16]);
|
||||||
|
|
||||||
|
// patch the CRC field of the format header to 0
|
||||||
|
WRITE_DWORD_BE_A(&rom_data[rom_size - 12], 0);
|
||||||
|
|
||||||
|
uint32_t test_crc = calculate_rom_crc(rom_data.get(), hdr_length);
|
||||||
|
|
||||||
|
// restore the CRC field value
|
||||||
|
WRITE_DWORD_BE_A(&rom_data[rom_size - 12], crc);
|
||||||
|
|
||||||
|
if (test_crc != crc) {
|
||||||
|
throw std::runtime_error("invalid CRC");
|
||||||
|
}
|
||||||
|
|
||||||
|
int lanes_used = 0;
|
||||||
|
|
||||||
|
// count meaningful lanes in a data quad
|
||||||
|
for (int i = 0; i < 4; i++) {
|
||||||
|
if (byte_lane & (1 << i)) {
|
||||||
|
lanes_used++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// calculate padded size = rom_size * (4 / lanes_used)
|
||||||
|
int padded_len = static_cast<int>((float)rom_size * (4 / (float)lanes_used) + 0.5f);
|
||||||
|
|
||||||
|
// calculate starting physical address of the ROM
|
||||||
|
uint32_t rom_phys_start = (0xF0FFFFFFUL | ((slot_num & 0xF) << 24)) - padded_len + 1;
|
||||||
|
|
||||||
|
auto mem_crtl = dynamic_cast<MemCtrlBase*>(gMachineObj->get_comp_by_type(HWCompType::MEM_CTRL));
|
||||||
|
if (!mem_crtl->add_rom_region(rom_phys_start, padded_len)) {
|
||||||
|
throw std::runtime_error("could not allocate ROM space");
|
||||||
|
}
|
||||||
|
|
||||||
|
int data_pos = 0;
|
||||||
|
|
||||||
|
auto new_data = std::unique_ptr<uint8_t[]> (new uint8_t[padded_len]);
|
||||||
|
|
||||||
|
// prepare new ROM data by copying over used lanes
|
||||||
|
// and padding unused lanes with 0xFF
|
||||||
|
// NOTE: speed uncritical - don't optimize!
|
||||||
|
for (int i = 0; i < padded_len; i += 4) {
|
||||||
|
for (int b = 0; b < 4; b++) {
|
||||||
|
if (byte_lane & (1 << b)) {
|
||||||
|
new_data[i+b] = rom_data[data_pos++];
|
||||||
|
} else {
|
||||||
|
new_data[i+b] = 0xFF;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// move padded ROM data to the memory region
|
||||||
|
mem_crtl->set_data(rom_phys_start, new_data.get(), padded_len);
|
||||||
|
}
|
||||||
|
catch (const std::exception& exc) {
|
||||||
|
LOG_F(ERROR, "load_declaration_rom failed: %s", exc.what());
|
||||||
|
result = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
rom_file.close();
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
30
devices/common/nubus/nubusutils.h
Normal file
30
devices/common/nubus/nubusutils.h
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
/*
|
||||||
|
DingusPPC - The Experimental PowerPC Macintosh emulator
|
||||||
|
Copyright (C) 2018-22 divingkatae and maximum
|
||||||
|
(theweirdo) spatium
|
||||||
|
|
||||||
|
(Contact divingkatae#1017 or powermax#2286 on Discord for more info)
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef NUBUS_UTILS_H
|
||||||
|
#define NUBUS_UTILS_H
|
||||||
|
|
||||||
|
#include <cinttypes>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
int load_declaration_rom(const std::string rom_path, int slot_num);
|
||||||
|
|
||||||
|
#endif // NUBUS_UTILS_H
|
Loading…
Reference in New Issue
Block a user