Skip to content

Commit

Permalink
Add DMA Clear Ordering Table Channel
Browse files Browse the repository at this point in the history
  • Loading branch information
Cherrytree56567 committed Oct 28, 2023
1 parent c978377 commit 0dfeeab
Show file tree
Hide file tree
Showing 4 changed files with 199 additions and 8 deletions.
187 changes: 183 additions & 4 deletions PSEMU/Bus.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -279,13 +279,192 @@ uint32_t Bus::dma_reg(uint32_t offset) {
}

void Bus::set_dma_reg(uint32_t offset, uint32_t value) {
switch (offset) {
case 0x70:
dma.set_control(value);
auto major = (offset & 0x70) >> 4;
auto minor = offset & 0xf;

Port active_port;
switch (major) {
// Per-channel registers
// 0-6
case 0:
auto port = dma.from_index(major);
auto channel = dma.channels[port];

switch (minor){
case 0: channel.set_base(value);
case 4: channel.set_block_control(value);
case 8: channel.set_control(value);
default:
std::cout << "[BUS] ERROR: Unhandled DMA write at " << std::to_string(offset) << "\n";
exit(0);
}

if (channel.active()) {
active_port = port;
}
else {
active_port = Port::NUL;
}
break;
case 1:
auto port = dma.from_index(major);
auto channel = dma.channels[port];

switch (minor) {
case 0: channel.set_base(value);
case 4: channel.set_block_control(value);
case 8: channel.set_control(value);
default:
std::cout << "[BUS] ERROR: Unhandled DMA write at " << std::to_string(offset) << "\n";
exit(0);
}

if (channel.active()) {
active_port = port;
}
else {
active_port = Port::NUL;
}
break;
case 2:
auto port = dma.from_index(major);
auto channel = dma.channels[port];

switch (minor) {
case 0: channel.set_base(value);
case 4: channel.set_block_control(value);
case 8: channel.set_control(value);
default:
std::cout << "[BUS] ERROR: Unhandled DMA write at " << std::to_string(offset) << "\n";
exit(0);
}

if (channel.active()) {
active_port = port;
}
else {
active_port = Port::NUL;
}
break;
case 3:
auto port = dma.from_index(major);
auto channel = dma.channels[port];

switch (minor) {
case 0: channel.set_base(value);
case 4: channel.set_block_control(value);
case 8: channel.set_control(value);
default:
std::cout << "[BUS] ERROR: Unhandled DMA write at " << std::to_string(offset) << "\n";
exit(0);
}

if (channel.active()) {
active_port = port;
}
else {
active_port = Port::NUL;
}
break;
case 4:
auto port = dma.from_index(major);
auto channel = dma.channels[port];

switch (minor) {
case 0: channel.set_base(value);
case 4: channel.set_block_control(value);
case 8: channel.set_control(value);
default:
std::cout << "[BUS] ERROR: Unhandled DMA write at " << std::to_string(offset) << "\n";
exit(0);
}

if (channel.active()) {
active_port = port;
}
else {
active_port = Port::NUL;
}
break;
case 5:
auto port = dma.from_index(major);
auto channel = dma.channels[port];

switch (minor) {
case 0: channel.set_base(value);
case 4: channel.set_block_control(value);
case 8: channel.set_control(value);
default:
std::cout << "[BUS] ERROR: Unhandled DMA write at " << std::to_string(offset) << "\n";
exit(0);
}

if (channel.active()) {
active_port = port;
}
else {
active_port = Port::NUL;
}
break;
case 6:
auto port = dma.from_index(major);
auto channel = dma.channels[port];

switch (minor) {
case 0: channel.set_base(value);
case 4: channel.set_block_control(value);
case 8: channel.set_control(value);
default:
std::cout << "[BUS] ERROR: Unhandled DMA write at " << std::to_string(offset) << "\n";
exit(0);
}

if (channel.active()) {
active_port = port;
}
else {
active_port = Port::NUL;
}
break;
// Common DMA registers
case 7:
switch (minor) {
case 0:
dma.set_control(value);

case 4:
dma.set_interrupt(value);

default:
std::cout << "[BUS] ERROR: Unhandled DMA write at " << std::to_string(offset) << "\n";
exit(0);
}
active_port = Port::NUL;
break;
default:
std::cout << "[BUS] ERROR: Unhandled DMA write at " << std::to_string(offset) << "\n";
exit(0);
};

if (active_port != Port::NUL) {
do_dma(active_port); // Call your do_dma function with the active_port.
}
}

void Bus::do_dma(Port port) {
// DMA transfer has been started, for now let's
// process everything in one pass (i.e. no
// chopping or priority handling)
switch (dma.channels[port].sync) {
case Sync::LinkedList:
std::cout << "[BUS] ERROR: Linked list mode unsupported\n";
exit(0);
break;

default:
std::cout << "[BUS] ERROR: Unhandled DMA write access\n";
std::cout << "[BUS] UNIMPLEMENTED: DO DMA BLOCK\n";
exit(0);
//do_dma_block(port);
break;
}
}
1 change: 1 addition & 0 deletions PSEMU/Bus.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ class Bus {
uint16_t load16(uint8_t addr);

uint32_t dma_reg(uint32_t offset);
void do_dma(Port port);

void set_dma_reg(uint32_t offset, uint32_t value);

Expand Down
12 changes: 12 additions & 0 deletions PSEMU/DMA.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -109,4 +109,16 @@ uint32_t DMAChannel::block_control() {
void DMAChannel::set_block_control(uint32_t val) {
block_size = (uint16_t)val;
block_count = (uint16_t)(val >> 16);
}

bool DMAChannel::active() {
// In manual sync mode the CPU must set the "trigger" bit
// to start the transfer.
bool trigger;
switch (sync){
case Sync::Manual: trigger = trigger;
default: trigger = true;
};

enable&& trigger;
}
7 changes: 3 additions & 4 deletions PSEMU/DMA.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@ enum Port {
/// Extension port
Pio = 5,
/// Used to clear the ordering table
Otc = 6
Otc = 6,
NUL = 100
};

// DMA transfer synchronization mode
Expand Down Expand Up @@ -60,16 +61,14 @@ class DMAChannel {
}

uint32_t control();
bool active();
void set_control(uint32_t val);
uint32_t block_control();
void set_block_control(uint32_t val);
uint32_t get_base() { return base; };
void set_base(uint32_t value) {
base = value & 0xffffff;
}


private:
bool enable;
Direction direction;
Step step;
Expand Down

0 comments on commit 0dfeeab

Please sign in to comment.