1 |
/* |
/* |
2 |
* Copyright (C) 2003-2005 Anders Gavare. All rights reserved. |
* Copyright (C) 2003-2007 Anders Gavare. All rights reserved. |
3 |
* |
* |
4 |
* Redistribution and use in source and binary forms, with or without |
* Redistribution and use in source and binary forms, with or without |
5 |
* modification, are permitted provided that the following conditions are met: |
* modification, are permitted provided that the following conditions are met: |
25 |
* SUCH DAMAGE. |
* SUCH DAMAGE. |
26 |
* |
* |
27 |
* |
* |
28 |
* $Id: dev_scc.c,v 1.27 2005/02/25 06:14:30 debug Exp $ |
* $Id: dev_scc.c,v 1.37 2007/01/28 14:15:30 debug Exp $ |
29 |
* |
* |
30 |
* Serial controller on some DECsystems and SGI machines. (Z8530 ?) |
* Serial controller on some DECsystems and SGI machines. (Z8530 ?) |
31 |
* Most of the code in here is written for DECsystem emulation, though. |
* Most of the code in here is written for DECsystem emulation, though. |
40 |
* emulate the same lk201 behaviour as when using the dc device) |
* emulate the same lk201 behaviour as when using the dc device) |
41 |
* DMA |
* DMA |
42 |
* More correct interrupt support. |
* More correct interrupt support. |
43 |
|
* |
44 |
|
****************************************************************************** |
45 |
|
* _____ ___ ____ ___ _ |
46 |
|
* |_ _/ _ \| _ \ / _ \| | |
47 |
|
* | || | | | | | | | | | | |
48 |
|
* | || |_| | |_| | |_| |_| |
49 |
|
* |_| \___/|____/ \___/(_) |
50 |
|
* |
51 |
|
* Since this is actually a Z8530, it should be merged with dev_z8530.c! |
52 |
*/ |
*/ |
53 |
|
|
54 |
#include <stdio.h> |
#include <stdio.h> |
147 |
} |
} |
148 |
|
|
149 |
|
|
150 |
/* |
DEVICE_TICK(scc) |
|
* dev_scc_tick(): |
|
|
*/ |
|
|
void dev_scc_tick(struct cpu *cpu, void *extra) |
|
151 |
{ |
{ |
152 |
int i; |
int i; |
153 |
struct scc_data *d = (struct scc_data *) extra; |
struct scc_data *d = (struct scc_data *) extra; |
159 |
d->console_handle), 2); |
d->console_handle), 2); |
160 |
} |
} |
161 |
if (d->use_fb == 1 && d->scc_nr == 1) |
if (d->use_fb == 1 && d->scc_nr == 1) |
162 |
lk201_tick(&d->lk201); |
lk201_tick(cpu->machine, &d->lk201); |
163 |
|
|
164 |
for (i=0; i<N_SCC_PORTS; i++) { |
for (i=0; i<N_SCC_PORTS; i++) { |
165 |
d->scc_register_r[i * N_SCC_REGS + SCC_RR0] |= SCC_RR0_TX_EMPTY; |
d->scc_register_r[i * N_SCC_REGS + SCC_RR0] |= SCC_RR0_TX_EMPTY; |
184 |
if (d->scc_register_r[i * N_SCC_REGS + SCC_RR3] |
if (d->scc_register_r[i * N_SCC_REGS + SCC_RR3] |
185 |
& SCC_RR3_TX_IP_A || |
& SCC_RR3_TX_IP_A || |
186 |
d->scc_register_r[i * N_SCC_REGS + SCC_RR3] |
d->scc_register_r[i * N_SCC_REGS + SCC_RR3] |
187 |
& SCC_RR3_TX_IP_B) |
& SCC_RR3_TX_IP_B) { |
188 |
cpu_interrupt(cpu, d->irq_nr); |
fatal("TODO: legacy rewrite!\n"); |
189 |
|
abort(); |
190 |
|
// cpu_interrupt(cpu, d->irq_nr); |
191 |
|
} |
192 |
} |
} |
193 |
|
|
194 |
/* RX interrupts? */ |
/* RX interrupts? */ |
207 |
if (d->scc_register_r[i * N_SCC_REGS + SCC_RR3] |
if (d->scc_register_r[i * N_SCC_REGS + SCC_RR3] |
208 |
& SCC_RR3_RX_IP_A || |
& SCC_RR3_RX_IP_A || |
209 |
d->scc_register_r[i * N_SCC_REGS + SCC_RR3] |
d->scc_register_r[i * N_SCC_REGS + SCC_RR3] |
210 |
& SCC_RR3_RX_IP_B) |
& SCC_RR3_RX_IP_B) { |
211 |
cpu_interrupt(cpu, d->irq_nr); |
fatal("TODO: legacy rewrite!\n"); |
212 |
|
abort(); |
213 |
|
// cpu_interrupt(cpu, d->irq_nr); |
214 |
|
} |
215 |
} |
} |
216 |
|
|
217 |
if (d->scc_register_w[N_SCC_REGS + SCC_WR1] & |
if (d->scc_register_w[N_SCC_REGS + SCC_WR1] & |
233 |
d->scc_register_r[i * N_SCC_REGS + SCC_RR3] |
d->scc_register_r[i * N_SCC_REGS + SCC_RR3] |
234 |
& SCC_RR3_EXT_IP_B) |
& SCC_RR3_EXT_IP_B) |
235 |
{ |
{ |
236 |
cpu_interrupt(cpu, d->irq_nr); |
fatal("TODO: legacy rewrite!\n"); |
237 |
|
abort(); |
238 |
|
// cpu_interrupt(cpu, d->irq_nr); |
239 |
/* TODO: huh? */ |
/* TODO: huh? */ |
240 |
cpu_interrupt(cpu, 8 + 0x02000000); |
//cpu_interrupt(cpu, 8 + 0x02000000); |
241 |
} |
} |
242 |
} |
} |
243 |
} |
} |
303 |
} |
} |
304 |
|
|
305 |
|
|
306 |
/* |
DEVICE_ACCESS(scc) |
|
* dev_scc_access(): |
|
|
*/ |
|
|
int dev_scc_access(struct cpu *cpu, struct memory *mem, |
|
|
uint64_t relative_addr, unsigned char *data, size_t len, |
|
|
int writeflag, void *extra) |
|
307 |
{ |
{ |
308 |
struct scc_data *d = (struct scc_data *) extra; |
struct scc_data *d = (struct scc_data *) extra; |
309 |
uint64_t idata = 0, odata = 0; |
uint64_t idata = 0, odata = 0; |
310 |
int port; |
int port; |
311 |
int ultrix_mode = 0; |
int ultrix_mode = 0; |
312 |
|
|
313 |
idata = memory_readmax64(cpu, data, len); |
if (writeflag == MEM_WRITE) |
314 |
|
idata = memory_readmax64(cpu, data, len); |
315 |
|
|
316 |
/* relative_addr /= d->addrmul; */ |
/* relative_addr /= d->addrmul; */ |
317 |
/* See SGI comment below instead. */ |
/* See SGI comment below instead. */ |
354 |
|
|
355 |
d->scc_register_r[port * N_SCC_REGS + |
d->scc_register_r[port * N_SCC_REGS + |
356 |
SCC_RR3] = 0; |
SCC_RR3] = 0; |
357 |
cpu_interrupt_ack(cpu, d->irq_nr); |
|
358 |
|
fatal("TODO: legacy rewrite!\n"); |
359 |
|
abort(); |
360 |
|
// cpu_interrupt_ack(cpu, d->irq_nr); |
361 |
} |
} |
362 |
|
|
363 |
#ifdef SCC_DEBUG |
#ifdef SCC_DEBUG |
404 |
|
|
405 |
/* TODO: perhaps only clear the RX part of RR3? */ |
/* TODO: perhaps only clear the RX part of RR3? */ |
406 |
d->scc_register_r[N_SCC_REGS + SCC_RR3] = 0; |
d->scc_register_r[N_SCC_REGS + SCC_RR3] = 0; |
407 |
cpu_interrupt_ack(cpu, d->irq_nr); |
|
408 |
|
fatal("TODO: legacy rewrite!\n"); |
409 |
|
abort(); |
410 |
|
// cpu_interrupt_ack(cpu, d->irq_nr); |
411 |
|
|
412 |
debug("[ scc: (port %i) read from 0x%08lx: 0x%02x ]\n", |
debug("[ scc: (port %i) read from 0x%08lx: 0x%02x ]\n", |
413 |
port, (long)relative_addr, (int)odata); |
port, (long)relative_addr, (int)odata); |
484 |
d->scc_nr = scc_nr; |
d->scc_nr = scc_nr; |
485 |
d->use_fb = use_fb; |
d->use_fb = use_fb; |
486 |
d->addrmul = addrmul; |
d->addrmul = addrmul; |
487 |
d->console_handle = console_start_slave(machine, "SCC"); |
d->console_handle = console_start_slave(machine, "SCC", 1); |
488 |
|
|
489 |
lk201_init(&d->lk201, use_fb, dev_scc_add_to_rx_queue, |
lk201_init(&d->lk201, use_fb, dev_scc_add_to_rx_queue, |
490 |
d->console_handle, d); |
d->console_handle, d); |
491 |
|
|
492 |
memory_device_register(mem, "scc", baseaddr, DEV_SCC_LENGTH, |
memory_device_register(mem, "scc", baseaddr, DEV_SCC_LENGTH, |
493 |
dev_scc_access, d, MEM_DEFAULT, NULL); |
dev_scc_access, d, DM_DEFAULT, NULL); |
494 |
machine_add_tickfunction(machine, dev_scc_tick, d, SCC_TICK_SHIFT); |
machine_add_tickfunction(machine, dev_scc_tick, d, SCC_TICK_SHIFT, 0.0); |
495 |
|
|
496 |
return (void *) d; |
return (void *) d; |
497 |
} |
} |