#include #include #include #include #include #include #include #include /*{{{ 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>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>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= 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 } /*}}} */