gsplus/src/scc_llap.c

153 lines
3.4 KiB
C

/*
GSPLUS - Advanced Apple IIGS Emulator Environment
Based on the KEGS emulator written by Kent Dickey
See COPYRIGHT.txt for Copyright information
See LICENSE.txt for license (GPL v2)
*/
/* This is an interface between the SCC emulation and the LAP bridge. */
#include <stdbool.h>
#include "defc.h"
#include "scc.h"
int g_appletalk_bridging;
int g_appletalk_turbo = 0;
int g_appletalk_diagnostics = 0;
int g_appletalk_network_hint = 0;
#ifdef HAVE_ATBRIDGE
#include "atbridge/atbridge.h"
#include "atbridge/llap.h"
extern Scc scc_stat[2];
extern int g_config_gsplus_update_needed;
static bool bridge_initialized = false;
void scc_llap_init()
{
atbridge_set_diagnostics(g_appletalk_diagnostics);
bridge_initialized = atbridge_init();
atbridge_set_net(g_appletalk_network_hint);
}
void scc_llap_set_node(byte val)
{
atbridge_set_node(val);
}
void scc_llap_update()
{
if (bridge_initialized)
{
atbridge_process();
// Save the AppleTalk network number. Since the network number does not
// change very often, this will slightly improve startup time.
if (g_appletalk_network_hint != atbridge_get_net())
{
g_appletalk_network_hint = atbridge_get_net();
g_config_gsplus_update_needed = 1;
}
}
}
/** Transfer one packet from the bridge to the SCC **/
void scc_llap_fill_readbuf(int port, int space_left, double dcycs)
{
atbridge_set_diagnostics(g_appletalk_diagnostics);
byte* data;
if (!bridge_initialized)
return;
data = NULL;
size_t bytes_read;
size_t i;
llap_dequeue_out(dcycs, &bytes_read, &data);
for(i = 0; i < bytes_read; i++) {
scc_add_to_readbuf(port, data[i], dcycs);
}
free(data);
// Normally, the bridge updates from the 60 Hz loop, but that alone bottlenecks network throughput.
scc_llap_update();
}
/** Transfer one packet from the SCC to the AppleTalk bridge. **/
void scc_llap_empty_writebuf(int port, double dcycs)
{
atbridge_set_diagnostics(g_appletalk_diagnostics);
Scc* scc_ptr;
if (!bridge_initialized)
return;
int rdptr;
int wrptr;
int len;
scc_ptr = &(scc_stat[port]);
// If there's data in the output buffer, send it.
rdptr = scc_ptr->out_rdptr;
wrptr = scc_ptr->out_wrptr;
if(rdptr == wrptr)
return;
len = wrptr - rdptr;
if (len < 0)
{
// The data is not contiguous since it wraps around the end of the buffer.
// But, this should never happen since this function always empties the entire
// buffer, and the buffer is large enough to hold the maximum packet size.
halt_printf("SCC LLAP: Unexpected non-contiguous data. Dropping packet.\n");
}
else
{
// The data is contiguous, so read the data directly from the buffer.
llap_enqueue_in(dcycs, len, &scc_ptr->out_buf[rdptr]);
}
// Remove the sent data from the output buffer. Since the buffer contains
// one complete packet, always send all of the data.
scc_ptr->out_rdptr = 0;
scc_ptr->out_wrptr = 0;
// Latch EOM to indicate that the SCC has sent the message.
// The timing will be a bit off from the real hardware since we're not
// emulating the sending hardware timing and CRC generation.
scc_ptr->eom = 1;
// Normally, the bridge updates from the 60 Hz loop, but that alone bottlenecks network throughput.
scc_llap_update();
}
#else
void scc_llap_init()
{
}
void scc_llap_set_node(byte val)
{
}
void scc_llap_update()
{
}
void scc_llap_fill_readbuf(int port, int space_left, double dcycs)
{
}
void scc_llap_empty_writebuf(int port, double dcycs)
{
}
#endif