Files
TeslaRel410/sda4/DPL3/VR_COMMS.C
T
CydandClaude Fable 5 db7745fcd0 sda4: commit the Glaze developer hard-drive dump
Un-ignored: the dev drive is the ground truth the restoration and
emulator work constantly reference (DPL3/LIBDPL + VRENDER i860 renderer
source, BT/RP live+dev game trees, VGL_LABS pod boot, scene/audio
content). Kept in-repo for the pod-owner community.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-04 19:41:15 -05:00

1464 lines
30 KiB
C++

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <dpltypes.h>
#include <dpl.h>
#include <dpl_host.h>
#include <vr_comms.h>
#include <linkio.h>
/*{{{ banner*/
/* **************************************************
Copyright DIVISION Limited (c) 1994
All rights reserved
File : vr_comms.c
Project : dpl interface
communication to 'velocirender for pxpl5'
Author : PJA
Date : 22/06/94
Function: communication to 'velocirender for pxpl5'
implements low-level messaging protocol
iserver transactions
byte-sex conversion for big-endian architectures
bootstrapping of vrender firmare onto vraster
History : Rev 1.0, 23 / 06 / 1994
**************************** */
/*}}} */
/*{{{ new VelociRender protocol*/
/* *****************************
new protocol is much simplified over original dNet;
basic protocol is l::bytes, with conditional behaviour on l
if (l & 0x80000000) then message is an iserver message,
otherwise a vr_net message
if message is to host, ((l >> 16) & 0xff) is id of sender,
if message is from host ((l >> 16) & 0xff) is id of receiver (target)
an outgoing id of 0xff implies a broadcast message
in all cases, (l & 0x3ff) is true number of bytes sent, 0..1023
Note that the i860s are now no longer in a position to communicate -
they simply input messages from the visual server, act on the messages
and sometimes reply.
*/
/*}}} */
#define verbose 0
/*
#define verbose 1
*/
int32 dpl_little_endian=1;
static char vr_msg_buffer[1040];
int32 dpl_frame_replied=1;
int32 vr_holding_bytes=0;
static char vr_holding_buffer[1040];
/*{{{ endian conversion / buffer access*/
/*{{{ static char *put_char ( char *b, char v )*/
static char *put_char ( char *b, char v )
{
*b++=v;
return b;
}
/*}}} */
/*{{{ static char *put_int8 ( char *b, int8 v )*/
static char *put_int8 ( char *b, int8 v )
{
char *cv=(char *) &v;
*b++=*cv;
return b;
}
/*}}} */
/*{{{ static char *put_int16 ( char *b, int16 v )*/
static char *put_int16 ( char *b, int16 v )
{
char *cv=(char *) &v;
if (dpl_little_endian) {
*b++=*cv++;
*b++=*cv++;
return b;
}
else {
b[0]=cv[1];
b[1]=cv[0];
return b+2;
}
}
/*}}} */
/*{{{ static char *put_int32 ( char *b, int32 v )*/
static char *put_int32 ( char *b, int32 v )
{
char *cv=(char *) &v;
if (dpl_little_endian) {
*b++=*cv++;
*b++=*cv++;
*b++=*cv++;
*b++=*cv++;
return b;
}
else {
b[0]=cv[3];
b[1]=cv[2];
b[2]=cv[1];
b[3]=cv[0];
return b+4;
}
}
/*}}} */
/*{{{ static char *put_fast_int32 ( char *b, int32 v )*/
static char *put_fast_int32 ( char *b, int32 v )
{
char *cv=(char *) &v;
if (dpl_little_endian) {
*(int *) b=v;
return b+4;
}
else {
b[0]=cv[3];
b[1]=cv[2];
b[2]=cv[1];
b[3]=cv[0];
return b+4;
}
}
/*}}} */
/*{{{ static char *put_float32 ( char *b, float32 v )*/
static char *put_float32 ( char *b, float32 v )
{
char *cv=(char *) &v;
if (dpl_little_endian) {
*b++=*cv++;
*b++=*cv++;
*b++=*cv++;
*b++=*cv++;
return b;
}
else {
b[0]=cv[3];
b[1]=cv[2];
b[2]=cv[1];
b[3]=cv[0];
return b+4;
}
}
/*}}} */
/*{{{ static char *put_struct8 ( char *b, void *v, int n_bytes )*/
static char *put_struct8 ( char *b, void *v, int n_bytes )
{
memcpy ( b, v, n_bytes );
return b+n_bytes;
}
/*}}} */
/*{{{ static char *put_struct32 ( char *b, void *v, int n_bytes )*/
static char *put_struct32 ( char *b, void *v, int n_bytes )
{
if (dpl_little_endian) {
memcpy ( b, v, n_bytes );
return b+n_bytes;
}
else {
int i;
char *cv=(char *) v;
for (i=0; i<n_bytes>>2; i++ ) {
b[0]=cv[3];
b[1]=cv[2];
b[2]=cv[1];
b[3]=cv[0];
b +=4;
cv+=4;
}
return b;
}
}
/*}}} */
/*{{{ static char *put_string ( char *b, char *s )*/
static char *put_string ( char *b, char *s )
{
int n_bytes=strlen(s)+1;
memcpy ( b, s, n_bytes );
return b+n_bytes;
}
/*}}} */
/*{{{ static char *get_char ( char *b, char *v )*/
static char *get_char ( char *b, char *v )
{
*v=*b++;
return b;
}
/*}}} */
/*{{{ static char *get_int8 ( char *b, int8 *v )*/
static char *get_int8 ( char *b, int8 *v )
{
char *cv=(char *) &v;
*cv++=*b++;
return b;
}
/*}}} */
/*{{{ static char *get_int16 ( char *b, int16 *v )*/
static char *get_int16 ( char *b, int16 *v )
{
char *cv=(char *) v;
if (dpl_little_endian) {
*cv++=*b++;
*cv++=*b++;
return b;
}
else {
cv[0]=b[1];
cv[1]=b[0];
return b+2;
}
}
/*}}} */
/*{{{ static char *get_int32 ( char *b, int32 *v )*/
static char *get_int32 ( char *b, int32 *v )
{
char *cv=(char *) v;
if (dpl_little_endian) {
*cv++ = *b++;
*cv++ = *b++;
*cv++ = *b++;
*cv++ = *b++;
return b;
}
else {
cv[3]=b[0];
cv[2]=b[1];
cv[1]=b[2];
cv[0]=b[3];
return b+4;
}
}
/*}}} */
/*{{{ static char *get_float32 ( char *b, float32 *v )*/
static char *get_float32 ( char *b, float32 *v )
{
char *cv=(char *) v;
if (dpl_little_endian) {
*cv++ = *b++;
*cv++ = *b++;
*cv++ = *b++;
*cv++ = *b++;
return b;
}
else {
cv[3]=b[0];
cv[2]=b[1];
cv[1]=b[2];
cv[0]=b[3];
return b+4;
}
}
/*}}} */
/*{{{ static char *get_struct8 ( char *b, void *v, int n_bytes )*/
static char *get_struct8 ( char *b, void *v, int n_bytes )
{
memcpy ( v, b, n_bytes );
return b+n_bytes;
}
/*}}} */
/*{{{ static char *get_struct32 ( char *b, void *v, int n_bytes )*/
static char *get_struct32 ( char *b, void *v, int n_bytes )
{
if (dpl_little_endian) {
memcpy ( v, b, n_bytes );
return b+n_bytes;
}
else {
int i;
char *cv=(char *) v;
for (i=0; i<n_bytes>>2; i++ ) {
cv[0]=b[3];
cv[1]=b[2];
cv[2]=b[1];
cv[3]=b[0];
b +=4;
cv+=4;
}
return b;
}
}
/*}}} */
/*{{{ static char *get_string ( char *b, char *s )*/
static char *get_string ( char *b, char *s )
{
int n_bytes=strlen(b)+1;
memcpy ( s, b, n_bytes );
return b+n_bytes;
}
/*}}} */
#define put_byte(a,b) put_int8(a,b)
#define get_byte(a,b) get_int8(a,b)
/*}}} */
/*{{{ low-level protocol transmit / receive*/
#define send_protocol send_link_protocol
static int32 use_fifo=0;
static int32
send_link_protocol ( int target, void *data, int n_bytes, int iserver, int iserver_enable );
/* #define outRecord(a,b) outveryfast((a),C012,(b)) */
static int32 isaction=0;
static int32 isactions=0;
#if 0
/*{{{ multi-pipe message formatting*/
typedef struct remote_msg {
char remote_printf[256];
char *printf_cp;
int32 printf_chars;
} remote_msg;
static remote_msg remote_messages[4];
static int32 remote_init=0;
/*{{{ static void flush_remote_messages ()*/
static void flush_remote_messages ()
{
int i;
for (i=0; i<4; i++) {
remote_msg *rp=&remote_messages[i];
if (rp->printf_chars) {
printf (rp->remote_printf);
rp->printf_cp=rp->remote_printf;
rp->printf_chars=0;
}
}
}
/*}}} */
/*{{{ static void vr_printf ( char * b)*/
static void vr_printf ( int32 him, char * b)
{
remote_msg *rp;
char c, *cp, *cp0;
int chars;
/*{{{ do init*/
if (remote_init==0) {
int i;
for (i=0; i<4; i++) {
rp=&remote_messages[i];
rp->printf_chars=0;
rp->printf_cp=rp->remote_printf;
}
remote_init=1;
}
/*}}} */
rp=&remote_messages[him-2];
cp =rp->printf_cp;
cp0=rp->remote_printf;
chars=rp->printf_chars;
while (c=*b++) {
if (c!=0xa) {
if (c==0xd) c='\n';
*cp++=c;
chars++;
}
if ((c=='\n') || (chars > 253)) {
*cp++=0x0;
printf (cp0);
fflush(stdout);
cp=cp0;
sprintf ( cp, "%d)", him );
while (*cp++)
;
chars=4;
}
}
rp->printf_cp=cp;
rp->printf_chars=chars;
}
/*}}} */
/*}}} */
#endif
/*{{{ iserver_action ( int32 him, char *boot_packet );*/
static
int32 iserver_action ( int him, char *boot_packet )
{
char *cp, *b=boot_packet, *mesg="VelociRender";
int16 l=0;
isactions++;
isaction = (int32) (*b);
switch (isaction) {
/*{{{ case 40 : commandline*/
case 40 :
#if (verbose)
printf("{%d} Iserver_action returning command line \"%s\".\n",him, mesg);
#endif
l=strlen(mesg);
b=put_char ( b, 0x0 );
b=put_int16 ( b, l );
b=put_struct8 ( b, mesg, l );
send_protocol ( him, boot_packet, l+3, 1, 0 );
break;
/*}}} */
/*{{{ case 42 : version*/
case 42 :
#if (verbose)
printf("{%d} Iserver_action returning iserver version 1.50\n", him );
#endif
b=put_char (b, 0 ); /* result */
b=put_char (b, 15 ); /* current iserver 1.50 */
b=put_char (b, 1 );
b=put_char (b, 1 );
b=put_char (b, 1 );
send_protocol ( him, boot_packet, 5, 1, 0 );
break;
/*}}} */
/*{{{ case 32 : getenv*/
case 32 :
#if (verbose)
printf("{%d} Iserver_action doing getenv..\n", him);
#endif
b++;
b = get_int16 ( b, &l );
#if (verbose)
printf("{%d} l=%d\n", him, l );
#endif
b[l]='\0';
#if (verbose)
printf("{%d} getenv of %s\n", him, b );
#endif
cp = getenv(b);
#if (verbose)
printf("{%d} which is %s\n", him, cp );
#endif
l = strlen(cp);
b = boot_packet;
b = put_byte ( b, 0 );
b = put_int16 ( b, l );
b = put_struct8 ( b, cp, l );
send_protocol ( him, boot_packet, l+3, 1, 0 );
break;
/*}}} */
/*{{{ case 24 : fputblock*/
case 24 :
{
int32 streamID;
b++;
b=get_int32 ( b, &streamID );
b=get_int16 ( b, &l );
b[l]= '\0';
if ((streamID == 1) || (streamID == 2)) {
printf ("%d):%s", him, b );
b=boot_packet;
b=put_byte ( b, 0 );
b=put_int16 ( b, l );
send_protocol ( him, boot_packet, 3, 1, 0 );
}
else {
printf ("i860 error : attempt to fputblock to NOT stdout\n" );
return 0;
}
}
break;
/*}}} */
/*{{{ case 13 : fwrite*/
case 13 :
{
int32 streamID;
char c;
b++;
b=get_int32 ( b, &streamID );
b=get_int16 ( b, &l );
b[l]= '\0';
if ((streamID == 1) || (streamID == 2)) {
printf ("%d):%s", him, b );
b=boot_packet;
b=put_byte ( b, 0 );
b=put_int16 ( b, l );
send_protocol ( him, boot_packet, 3, 1, 0 );
}
else {
printf ( "ERROR : i860 attempting to fwrite\n" );
return 0;
}
}
break;
/*}}} */
/*{{{ case 16 : fflush - don't do owt*/
case 16 :
#if (verbose)
printf("{%d} Iserver_action ignoring fflush.\n", him);
#endif
b=put_byte ( b, 0 );
b=put_byte ( b, 1 );
b=put_byte ( b, 0 );
send_protocol ( him, boot_packet, 3, 1, 0 );
break;
/*}}} */
default :
printf ("iserver_transaction, unexpected tag (%d) in %s\n",
isaction, __lastop);
exit(666);
return 0;
break;
}
return 1;
}
/*}}} */
/*{{{ receive_protocol ( int *sender, void *data, int *n_bytes, int *iserver )*/
static int32
cntl_word=0;
static int32
receive_protocol ( int *sender, void *data, int *n_bytes, int *iserver )
{
int32 nb=0, length_word, i;
char *b=(char *) &nb;
if (inRecord ( b, 4 )) {
get_int32 ( b, &length_word );
cntl_word=length_word;
*sender=(length_word >> 16) & 0xff;
if (length_word & 0x80000000)
*iserver=1;
else
*iserver=0;
nb=length_word&0xffff;
if (nb > 1040) {
printf ("protocol error, length %d too big\n", nb );
return 0;
}
if (inRecord ( data, nb )) {
char *cd=(char *) data;
*n_bytes=nb;
return 1;
}
else {
printf ("protocol error, %d bytes not completed (is=%d)\n",
nb, *iserver );
return 0;
}
}
else {
printf ("protocol error, length word not received\n" );
return 0;
}
return 1;
}
/*}}} */
/*{{{ static void handle_iserver_stuff()*/
static void handle_iserver_stuff ( void )
{
char *b;
while (vr_holding_bytes == 0) {
int32 iserver;
int32 sender;
b=&vr_holding_buffer[0];
if (altRecord() == 0)
return;
else {
if ((receive_protocol ( &sender, b, &vr_holding_bytes, &iserver )) == 0) {
linkio_error ("ERROR : receive protocol fail during iserver handling\n" );
return;
}
if (iserver) {
if (iserver_action ( sender, b ) == 0) {
linkio_error ("ERROR : iserver transaction failure during transmit\n" );
return;
}
else {
vr_holding_bytes=0;
}
}
else {
printf ("handle_iserver_stuff found REAL DATA packet\n" );
}
}
}
}
/*}}} */
/*{{{ send_FIFO_protocol ( int target, void *data, int n_bytes, int iserver, int iserver_enable )*/
extern int outsw ( int32 length_word, int32 port, void *address, int32 bytes );
extern int32 C012;
int32
send_FIFO_protocol ( int target, void *data, int n_bytes, int iserver, int iserver_enable )
{
/* try to figure out a scam for less copies when endian_fix is deasserted */
static int32 good_sends=0;
int32 t=0;
char length_word[4];
char *cdata=(char *) data;
if ((iserver == 0) & iserver_enable)
handle_iserver_stuff();
if (n_bytes > 1024) {
printf ("Attempt to send %d bytes in packet, dying!!\n", n_bytes );
exit(666);
}
if (iserver) {
if (n_bytes & 1)
n_bytes++;
put_int32 ( length_word, n_bytes | (target << 16) | 0x80000000 );
}
else
put_int32 ( length_word, (0xff << 16) | n_bytes ); /* top bit clear = broadcast */
return outsw ( *((int32 *) (&length_word[0])), C012, data, n_bytes );
}
/*}}} */
/*{{{ send_link_protocol ( int target, void *data, int n_bytes, int iserver, int iserver_enable )*/
static int32
send_link_protocol ( int target, void *data, int n_bytes, int iserver, int iserver_enable )
{
/* try to figure out a scam for less copies when endian_fix is deasserted */
static int32 good_sends=0;
char length_word[4];
char *cdata=(char *) data;
if (use_fifo)
return send_FIFO_protocol ( target, data, n_bytes, iserver, iserver_enable );
if ((iserver == 0) & iserver_enable)
handle_iserver_stuff();
if (n_bytes > 1024) {
printf ("Attempt to send %d bytes in packet, dying!!\n", n_bytes );
exit(666);
}
if (iserver) {
if (n_bytes & 1)
n_bytes++;
put_int32 ( length_word, n_bytes | (target << 16) | 0x80000000 );
}
else
put_int32 ( length_word, (0xff << 16) | n_bytes ); /* top bit clear = broadcast */
if (outRecord ( length_word, 4 ) == 0) {
#if (verbose)
printf("send_protocol failed to squirt length word, good_sends=%d\n",
good_sends );
exit(666);
#endif
return 0;
}
if (outRecord ( data, n_bytes ) == 0) {
#if (verbose)
printf("send_protocol failed to squirt data, good_sends=%d\n",
good_sends );
exit(666);
#endif
return 0;
}
if (iserver == 0) good_sends++;
return 1;
}
/*}}} */
/*}}} */
/*{{{ velocirender_receive ( vr_action *action, void *node, int32 *n_bytes )*/
int32
velocirender_receive ( vr_action *action, void *node, int32 *n_bytes )
{
char *b=&vr_msg_buffer[0];
int32 iserver=1;
int32 nb, sender, received=0;
#if (verbose)
printf ("call to velocirender_receive\n" );
#endif
if (vr_holding_bytes) {
nb=vr_holding_bytes & 0xff;
b=get_int32 ( b, (int32 *) action );
b=get_struct32 ( b, node, nb - 4 );
*n_bytes=nb-4;
vr_holding_bytes = 0;
if ((*action) == vr_draw_scene_action) {
printf ("draw scene ack found in receive\n" );
dpl_frame_replied=1;
}
else
return 1;
}
do {
do {
if ((receive_protocol ( &sender, b, &nb, &iserver )) == 0)
return 0;
if (iserver) {
if (iserver_action ( sender, b ) == 0)
return 0;
}
} while (iserver);
if (nb < 8) {
printf ("Huh, at least 8 bytes expected - cntl word=0x%x\n",
cntl_word );
return 0;
}
b=get_int32 ( b, (int32 *) action );
b=get_struct32 ( b, node, nb - 4 );
*n_bytes=nb-4;
if ((*action) == vr_draw_scene_action) {
printf ("draw scene ack found in receive\n" );
dpl_frame_replied=1;
}
else
received = 1;
} while (received == 0);
return 1;
}
/*}}} */
/*{{{ velocirender_frameack ( vr_action *action, void *node, int32 *n_bytes )*/
int32
velocirender_frameack ( void )
{
vr_action action;
int32 n_bytes;
char *b=&vr_msg_buffer[0];
int32 iserver=1;
int32 sender, received=0;
#if (verbose)
printf ("call to velocirender_receive\n" );
#endif
if (vr_holding_bytes) {
n_bytes=vr_holding_bytes & 0xff;
vr_holding_bytes = 0;
b=get_int32 ( b, (int32 *) &action );
if (action == vr_draw_scene_action) {
dpl_frame_replied=1;
return 1;
}
else {
printf ("Unexpected vr_net input 0x%x during frame ack\n", action );
return 0;
}
}
do {
if ((receive_protocol ( &sender, b, &n_bytes, &iserver )) == 0)
return 0;
if (iserver) {
if (iserver_action ( sender, b ) == 0)
return 0;
}
} while (iserver);
if ((n_bytes) < 8) {
printf ("Huh, at least 8 bytes expected - cntl word=0x%x\n",
cntl_word );
return 0;
}
b=get_int32 ( b, (int32 *) &action );
if (action == vr_draw_scene_action) {
dpl_frame_replied=1;
return 1;
}
else {
printf ("Unexpected vr_net input 0x%x during frame ack\n", action );
return 0;
}
return 0;
}
/*}}} */
/*{{{ velocirender_inputstatus ( void )*/
int32
velocirender_inputstatus ( void )
{
if (vr_holding_bytes)
return 1;
else if (altRecord())
return 1;
else
return 0;
}
/*}}} */
/*{{{ velocirender_transmit ( vr_action action, void *data, int32 n_bytes )*/
int32
velocirender_transmit ( vr_action action, void *data, int32 n_bytes,
int32 endian_fix )
{
char *b=&vr_msg_buffer[0];
/* this is a bit nasty to do non-endian fix stuff
without additional memcpy */
if (action == vr_draw_scene_action) {
if (dpl_frame_replied==0)
velocirender_frameack();
dpl_frame_replied=0;
}
if (dpl_little_endian || (endian_fix == 0)) {
int32 t1, t2;
char *at1=(char *) &t1;
char *at2=(char *) &t2;
handle_iserver_stuff();
n_bytes+=4;
put_fast_int32 ( at1, (0xff << 16) | n_bytes);
put_fast_int32 ( at2, (int32) action);
if (use_fifo) {
outsw ( 0, C012, at2, 4 );
return outsw ( t1, C012, data, n_bytes-4 );
}
else {
outRecord ( at1, 4 );
outRecord ( at2, 4 );
return outRecord ( data, n_bytes-4 );
}
}
else {
b=put_int32 ( b, (int32) action );
b=put_struct32 ( b, data, n_bytes );
send_protocol ( 0xff, vr_msg_buffer, n_bytes+4, 0, 1 );
}
return 1;
}
/*}}} */
/*{{{ velocirender_packetize ( vr_action action, void *data, int32 n_bytes, int32 endian_fix )*/
int32
velocirender_packetize ( vr_action action, void *data, int32 n_bytes, int32 endian_fix )
{
char *cdata=(char *) data;
int max_bytes=512-4;
while (n_bytes > max_bytes) {
if (velocirender_transmit ( action, cdata, max_bytes, endian_fix ) == 0)
return 0;
n_bytes-=max_bytes;
cdata +=max_bytes;
}
if (n_bytes) {
if (velocirender_transmit ( action, cdata, n_bytes, endian_fix ) == 0)
return 0;
}
return 1;
}
/*}}} */
/*{{{ code for booting transputers*/
#define boot_packet_size (2*1024)
static char *__boot_packet,
*__packet,
*__blk;
/*{{{ startup_transaction ( void )*/
static int32
startup_transaction ( void )
{
int32 t;
int32 iserver, sender, n_bytes;
vr_action action;
#if (verbose)
printf ("**** startup transaction\n" );
#endif
t = receive_protocol ( &sender, __boot_packet, &n_bytes, &iserver );
if (t == 0) return 0;
if (iserver) {
if (iserver_action ( sender, __boot_packet ) == 0)
return 0;
}
else {
printf ("ERROR : unexpected vrNet transaction in startup-handshake\n" );
return 0;
}
return n_bytes;
}
/*}}} */
/*{{{ startup_handshake*/
static int32
startup_handshake ()
{
int32 ret;
/*{{{ sorry...*/
/*
This is deeply Yuck, and relies on the knowledge that
the C run-time boots up and does 3 iserver transactions before
closing down
Phil
*/
/*}}} */
#if verbose
printf ("Startup handshake velocirender v 1.0\n");
#endif
/* 1 getenv*/
link_io_ABORTCHECK;
if ((ret=startup_transaction ()) == 0) return 0;
#if verbose
printf ("Startup handshake ret 1 was %d (%d)\n", ret, isaction );
#endif
/* 2 getenv*/
link_io_ABORTCHECK;
if ((ret=startup_transaction ()) == 0) return 0;
#if verbose
printf ("Startup handshake ret 2 was %d (%d)\n", ret, isaction );
#endif
/* 3 getenv*/
link_io_ABORTCHECK;
if ((ret=startup_transaction ()) == 0) return 0;
#if verbose
printf ("Startup handshake ret 3 was %d (%d)\n", ret, isaction );
#endif
return 1;
link_io_EXITZERO;
}
/*}}} */
/*{{{ boot_xputer*/
int32 boot_xputer ( char *f, int32 n_860s )
{
FILE *fp;
int32 n_read;
int32 total=0,
ok_to_fifo;
reset();
#if verbose
printf ("boot_xputer with %s\n", f );
#endif
if ((fp=fopen(f, "rb" )) == 0) {
printf ("Couldnt open %s\n", f );
return 0;
}
link_io_ABORTCHECK;
n_read=fread ( __boot_packet, 1, boot_packet_size, fp );
total=n_read;
ok_to_fifo=fifo_ok_status();
while (n_read == boot_packet_size) {
if (outRecord(__boot_packet, boot_packet_size )==0) {
#if verbose
printf ("Boot_packet returned 0\n");
#endif
fclose(fp);
return(0);
}
n_read=fread ( __boot_packet, 1, boot_packet_size, fp );
total+=n_read;
}
fclose (fp);
/*{{{ */
#if verbose
printf ("fclosed tranny boot file\n ");
#endif
/*}}} */
link_io_ABORTCHECK;
if (n_read != 0) {
if (outRecord(__boot_packet, n_read )==0) {
/*{{{ */
#if verbose
printf ("Boot_packet returned 0\n");
#endif
/*}}} */
return(0);
}
}
/*
if (ok_to_fifo) {
printf ("waiting to become NOT ok to fifo\n" );
while(ok_to_fifo) {
ok_to_fifo=fifo_ok_status();
}
}
printf ("waiting to become ok to fifo\n" );
while(ok_to_fifo == 0)
ok_to_fifo=fifo_ok_status();
printf ("now its ok to fifo\n" );
*/
{
int32 i;
/*{{{ */
#if verbose
printf ("about to startup_handshake for %d 860s\n", n_860s );
#endif
/*}}} */
for (i=0; i<n_860s; i++ ) {
startup_handshake ();
link_io_ABORTCHECK;
}
}
return 1;
link_io_EXITZERO;
}
/*}}} */
#define link_address(a) (int32) (0x80000000 | (a<<2))
/*{{{ void resetLoop()*/
static void resetLoop ( int n )
{
clock_t the_time=clock();
int i;
for (i=0; i<n; i++ ) {
while (the_time==clock())
;
the_time=clock();
}
}
/*}}} */
/*{{{ static boot_HSP()*/
static void boot_HSP ( char *f, int32 link_A, int32 link_B )
{
FILE *fp;
int32 total=0;
char *cp = (char *) __boot_packet, *lp, *rp;
int32 chars=0;
/* set up packet header - HSPcode, link, bytes*/
lp = cp; /* record link address slot */
cp = put_int32 ( cp, link_address(link_A));
cp = put_int32 ( cp, 128 );
rp=cp;
if (link_A==link_B) {
link_B=-1;
}
#if (verbose)
printf ("Boot hsp from %s links 0x%lx 0x%lx\n", f, link_A, link_B );
#endif
if ((fp=fopen(f, "rb" ))!=0) {
/* boot file fp*/
chars = fread (rp, 1, 128, fp );
while (chars == 128 ) {
/* send packets of 128 */
total+=128;
cp=lp;
cp = put_int32 ( cp, link_address(link_A));
velocirender_transmit ( vr_hspcode_action, lp, 128+8, 0 );
if (link_B >= 0) {
cp=lp;
cp = put_int32 ( cp, link_address(link_B));
velocirender_transmit ( vr_hspcode_action, lp, 128+8, 0 );
}
chars = fread (rp, 1, 128, fp );
}
if (chars != 0) {
/* send last few*/
total+=chars;
cp = lp;
cp = put_int32 ( cp, link_address(link_A));
cp = put_int32 ( cp, chars );
velocirender_transmit ( vr_hspcode_action, lp, chars+8, 0 );
if (link_B >= 0) {
cp = lp;
cp = put_int32 ( cp, link_address(link_B));
velocirender_transmit ( vr_hspcode_action, lp, chars+8, 0 );
}
}
fclose (fp);
#if (verbose)
printf ("Booted %ld bytes to HSP\n", total );
#endif
}
else {
printf ("Couldnt open HSP file \"%s\".\n", f );
}
}
/*}}} */
/*{{{ static i860_args()*/
static void i860_args ( char *argv )
{
int32 bytes=1+strlen(argv);
velocirender_transmit ( vr_860args_action, argv, bytes, 0 );
}
/*}}} */
/*{{{ static i860_segment()*/
static void i860_segment ( FILE *fp, int32 bytes, vr_action action )
{
int32 n_read;
char *cp = (char *) __boot_packet;
int32 left=bytes;
#if (verbose)
printf ("i860 segment, expecting %ld bytes\n", bytes );
#endif
while (left > boot_packet_size ) {
link_io_ABORTCHECK;
n_read=fread ( cp, 1, boot_packet_size, fp );
if (n_read != boot_packet_size) {
printf ("i860 MNG file error, file corrupt or read error\n" );
return;
}
velocirender_packetize ( action, cp, boot_packet_size, 0 );
left-=boot_packet_size;
}
if (left != 0) {
link_io_ABORTCHECK;
n_read=fread ( cp, 1, (int32) left, fp );
if (n_read != left) {
printf ("i860 MNG file error, file corrupt or read error\n" );
return;
}
velocirender_packetize ( action, cp, n_read, 0 );
}
link_io_EXIT;
}
/*}}} */
/*{{{ static boot_860()*/
static void boot_860 ( char *f, char *argv )
{
FILE *fp;
int32 csize, dsize, bsize, cstart, dstart, bstart, entry;
char *cp=(char *) __boot_packet;
link_io_ABORTCHECK;
resetLoop( 5 );
#if verbose
printf ( "Calling i860_args\n" );
#endif
i860_args ( argv );
#if verbose
printf ( "Putting INT32 viz_860code\n" );
#endif
if ((fp=fopen(f, "rb" )) != 0) {
/* do csize, cstart etc.*/
/*{{{ */
#if verbose
printf ( "Putting 1st 7 words of mng\n" );
#endif
/*}}} */
/* note the 7 words are little-endian on disk, so fread, squirt is ok */
fread ( cp, 7, 4, fp ); /* read 7 ints, size 4*/
velocirender_transmit ( vr_860code_action, cp, 40, 0 );
link_io_ABORTCHECK;
cp = get_int32 ( cp, &csize );
cp = get_int32 ( cp, &dsize );
cp = get_int32 ( cp, &bsize );
cp = get_int32 ( cp, &cstart );
cp = get_int32 ( cp, &dstart );
cp = get_int32 ( cp, &bstart );
cp = get_int32 ( cp, &entry );
/*{{{ messgaes*/
#if (verbose)
printf ("csize <0x%lx> dsize <0x%lx> bsize <0x%lx>\n",
csize, dsize, bsize );
printf ("cstart <0x%lx> dstart <0x%lx> bstart <0x%lx> entry <0x%lx>\n",
cstart, dstart, bstart, entry );
#endif
/*}}} */
i860_segment ( fp, csize, vr_860code_action );
link_io_ABORTCHECK;
/*{{{ messages*/
#if (verbose)
printf ("i860 code segment loaded...\n");
#endif
/*}}} */
i860_segment ( fp, dsize, vr_860data_action );
link_io_ABORTCHECK;
/*{{{ messages*/
#if (verbose)
printf ("i860 data segment loaded...\n");
#endif
/*}}} */
i860_segment ( fp, bsize, vr_860bss_action );
link_io_ABORTCHECK;
/*{{{ messages*/
#if (verbose)
printf ("i860 bss segment loaded...\n");
#endif
/*}}} */
fclose (fp);
}
else {
/*{{{ */
#if verbose
printf ( "Failed to open i860 file\n" );
#endif
/*}}} */
printf ("Couldnt open i860 file %s\n", f );
return;
}
link_io_EXIT;
}
/*}}} */
/*{{{ static int32 getXputer(void)*/
static int32 getXputer(void)
{
char *str=getenv("TRANSPUTER");
if (str==NULL) return 0x150;
else {
int32 t;
if (sscanf(getenv("TRANSPUTER"), "%x", &t ) == 1)
return t;
else
return 0x150;
}
}
/*}}} */
/*}}} */
/*{{{ void vr_server ( char *tranny_name )*/
void vr_server ( char *tranny_name, int32 serve )
{
__blk=malloc(2048);
__boot_packet=malloc(2048);
setLA (0x150);
initLA();
#if verbose
printf("booting transputer with %s\n", tranny_name ); fflush(stdout);
#endif
boot_xputer ( tranny_name, 0 );
if (serve)
while (1)
startup_transaction();
}
/*}}} */
/*{{{ void start_velocirender ( char *tranny_name, char *hsp_name, char *i860_name,*/
void start_velocirender ( char *tranny_name,
char *hsp_name,
char *i860_name,
int32 XputerAddr,
int32 link_A,
int32 link_B,
int32 n_860s )
{
int32 ret, i;
__blk=malloc(2048);
__boot_packet=malloc(2048);
setLA (XputerAddr);
initLA();
#if verbose
printf("booting transputer at 0x%x with %s\n", XputerAddr, tranny_name ); fflush(stdout);
#endif
boot_xputer ( tranny_name, n_860s );
if (hsp_name != NULL) {
#if verbose
printf("booting HSP's ");
printf(" with %s\n", hsp_name ); fflush(stdout);
#endif
boot_HSP ( hsp_name, link_A, link_B );
}
if (i860_name != NULL) {
#if verbose
printf("booting i860 ");
printf("with %s\n", i860_name); fflush(stdout);
#endif
boot_860 ( i860_name, "i860 50MHz and kicking" );
}
#if verbose
printf("exiting start_dview\n"); fflush(stdout);
#endif
}
/*}}} */