Skip to content

Commit 0dfeeab

Browse files
Add DMA Clear Ordering Table Channel
1 parent c978377 commit 0dfeeab

File tree

4 files changed

+199
-8
lines changed

4 files changed

+199
-8
lines changed

PSEMU/Bus.cpp

Lines changed: 183 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -279,13 +279,192 @@ uint32_t Bus::dma_reg(uint32_t offset) {
279279
}
280280

281281
void Bus::set_dma_reg(uint32_t offset, uint32_t value) {
282-
switch (offset) {
283-
case 0x70:
284-
dma.set_control(value);
282+
auto major = (offset & 0x70) >> 4;
283+
auto minor = offset & 0xf;
284+
285+
Port active_port;
286+
switch (major) {
287+
// Per-channel registers
288+
// 0-6
289+
case 0:
290+
auto port = dma.from_index(major);
291+
auto channel = dma.channels[port];
292+
293+
switch (minor){
294+
case 0: channel.set_base(value);
295+
case 4: channel.set_block_control(value);
296+
case 8: channel.set_control(value);
297+
default:
298+
std::cout << "[BUS] ERROR: Unhandled DMA write at " << std::to_string(offset) << "\n";
299+
exit(0);
300+
}
301+
302+
if (channel.active()) {
303+
active_port = port;
304+
}
305+
else {
306+
active_port = Port::NUL;
307+
}
308+
break;
309+
case 1:
310+
auto port = dma.from_index(major);
311+
auto channel = dma.channels[port];
312+
313+
switch (minor) {
314+
case 0: channel.set_base(value);
315+
case 4: channel.set_block_control(value);
316+
case 8: channel.set_control(value);
317+
default:
318+
std::cout << "[BUS] ERROR: Unhandled DMA write at " << std::to_string(offset) << "\n";
319+
exit(0);
320+
}
321+
322+
if (channel.active()) {
323+
active_port = port;
324+
}
325+
else {
326+
active_port = Port::NUL;
327+
}
328+
break;
329+
case 2:
330+
auto port = dma.from_index(major);
331+
auto channel = dma.channels[port];
332+
333+
switch (minor) {
334+
case 0: channel.set_base(value);
335+
case 4: channel.set_block_control(value);
336+
case 8: channel.set_control(value);
337+
default:
338+
std::cout << "[BUS] ERROR: Unhandled DMA write at " << std::to_string(offset) << "\n";
339+
exit(0);
340+
}
341+
342+
if (channel.active()) {
343+
active_port = port;
344+
}
345+
else {
346+
active_port = Port::NUL;
347+
}
348+
break;
349+
case 3:
350+
auto port = dma.from_index(major);
351+
auto channel = dma.channels[port];
352+
353+
switch (minor) {
354+
case 0: channel.set_base(value);
355+
case 4: channel.set_block_control(value);
356+
case 8: channel.set_control(value);
357+
default:
358+
std::cout << "[BUS] ERROR: Unhandled DMA write at " << std::to_string(offset) << "\n";
359+
exit(0);
360+
}
361+
362+
if (channel.active()) {
363+
active_port = port;
364+
}
365+
else {
366+
active_port = Port::NUL;
367+
}
368+
break;
369+
case 4:
370+
auto port = dma.from_index(major);
371+
auto channel = dma.channels[port];
372+
373+
switch (minor) {
374+
case 0: channel.set_base(value);
375+
case 4: channel.set_block_control(value);
376+
case 8: channel.set_control(value);
377+
default:
378+
std::cout << "[BUS] ERROR: Unhandled DMA write at " << std::to_string(offset) << "\n";
379+
exit(0);
380+
}
381+
382+
if (channel.active()) {
383+
active_port = port;
384+
}
385+
else {
386+
active_port = Port::NUL;
387+
}
388+
break;
389+
case 5:
390+
auto port = dma.from_index(major);
391+
auto channel = dma.channels[port];
392+
393+
switch (minor) {
394+
case 0: channel.set_base(value);
395+
case 4: channel.set_block_control(value);
396+
case 8: channel.set_control(value);
397+
default:
398+
std::cout << "[BUS] ERROR: Unhandled DMA write at " << std::to_string(offset) << "\n";
399+
exit(0);
400+
}
401+
402+
if (channel.active()) {
403+
active_port = port;
404+
}
405+
else {
406+
active_port = Port::NUL;
407+
}
408+
break;
409+
case 6:
410+
auto port = dma.from_index(major);
411+
auto channel = dma.channels[port];
412+
413+
switch (minor) {
414+
case 0: channel.set_base(value);
415+
case 4: channel.set_block_control(value);
416+
case 8: channel.set_control(value);
417+
default:
418+
std::cout << "[BUS] ERROR: Unhandled DMA write at " << std::to_string(offset) << "\n";
419+
exit(0);
420+
}
421+
422+
if (channel.active()) {
423+
active_port = port;
424+
}
425+
else {
426+
active_port = Port::NUL;
427+
}
428+
break;
429+
// Common DMA registers
430+
case 7:
431+
switch (minor) {
432+
case 0:
433+
dma.set_control(value);
434+
435+
case 4:
436+
dma.set_interrupt(value);
437+
438+
default:
439+
std::cout << "[BUS] ERROR: Unhandled DMA write at " << std::to_string(offset) << "\n";
440+
exit(0);
441+
}
442+
active_port = Port::NUL;
443+
break;
444+
default:
445+
std::cout << "[BUS] ERROR: Unhandled DMA write at " << std::to_string(offset) << "\n";
446+
exit(0);
447+
};
448+
449+
if (active_port != Port::NUL) {
450+
do_dma(active_port); // Call your do_dma function with the active_port.
451+
}
452+
}
453+
454+
void Bus::do_dma(Port port) {
455+
// DMA transfer has been started, for now let's
456+
// process everything in one pass (i.e. no
457+
// chopping or priority handling)
458+
switch (dma.channels[port].sync) {
459+
case Sync::LinkedList:
460+
std::cout << "[BUS] ERROR: Linked list mode unsupported\n";
461+
exit(0);
285462
break;
286463

287464
default:
288-
std::cout << "[BUS] ERROR: Unhandled DMA write access\n";
465+
std::cout << "[BUS] UNIMPLEMENTED: DO DMA BLOCK\n";
466+
exit(0);
467+
//do_dma_block(port);
289468
break;
290469
}
291470
}

PSEMU/Bus.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ class Bus {
4141
uint16_t load16(uint8_t addr);
4242

4343
uint32_t dma_reg(uint32_t offset);
44+
void do_dma(Port port);
4445

4546
void set_dma_reg(uint32_t offset, uint32_t value);
4647

PSEMU/DMA.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,4 +109,16 @@ uint32_t DMAChannel::block_control() {
109109
void DMAChannel::set_block_control(uint32_t val) {
110110
block_size = (uint16_t)val;
111111
block_count = (uint16_t)(val >> 16);
112+
}
113+
114+
bool DMAChannel::active() {
115+
// In manual sync mode the CPU must set the "trigger" bit
116+
// to start the transfer.
117+
bool trigger;
118+
switch (sync){
119+
case Sync::Manual: trigger = trigger;
120+
default: trigger = true;
121+
};
122+
123+
enable&& trigger;
112124
}

PSEMU/DMA.h

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,8 @@ enum Port {
2828
/// Extension port
2929
Pio = 5,
3030
/// Used to clear the ordering table
31-
Otc = 6
31+
Otc = 6,
32+
NUL = 100
3233
};
3334

3435
// DMA transfer synchronization mode
@@ -60,16 +61,14 @@ class DMAChannel {
6061
}
6162

6263
uint32_t control();
64+
bool active();
6365
void set_control(uint32_t val);
6466
uint32_t block_control();
6567
void set_block_control(uint32_t val);
6668
uint32_t get_base() { return base; };
6769
void set_base(uint32_t value) {
6870
base = value & 0xffffff;
6971
}
70-
71-
72-
private:
7372
bool enable;
7473
Direction direction;
7574
Step step;

0 commit comments

Comments
 (0)