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>
428 lines
7.8 KiB
C++
428 lines
7.8 KiB
C++
/*
|
|
FILE : linkio.c
|
|
PROJECT : dView
|
|
Author : Phil Atkin / Jeff Sullivan
|
|
|
|
|
|
(C) Division Ltd 1991 / 1992.
|
|
|
|
Transputer link support functions
|
|
currently supported are -
|
|
|
|
simple polled PC / DOS interface, a la IMS B004
|
|
simple polled Mac interface for C012 (not high-speed Nubus access)
|
|
UNIX device driver interface
|
|
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <time.h>
|
|
#include <basictyp.h>
|
|
#include <linkio.h>
|
|
|
|
int32 __connected=1;
|
|
|
|
void linkio_error ( char *str )
|
|
{
|
|
printf ( str );
|
|
__connected=1;
|
|
}
|
|
|
|
#define time_out_seconds 5 /* plenty of time */
|
|
|
|
#ifdef MS_DOS
|
|
/*{{{ MS-DOS link io functions*/
|
|
#include <dos.h>
|
|
|
|
|
|
int32 C012;
|
|
static int32 inputData, outputData,
|
|
inputStatus, outputStatus,
|
|
resetRoot, analyseRoot,
|
|
ok_to_fifo;
|
|
|
|
#define failed (int32) 40000
|
|
|
|
#define read_C012(reg) inp(reg)
|
|
#define write_C012(reg,byte) outp(reg,byte)
|
|
|
|
#define INPUT_READY (1 & read_C012(inputStatus))
|
|
#define OUTPUT_READY (1 & read_C012(outputStatus))
|
|
|
|
#define OUTBYTE(b) write_C012(outputData, b)
|
|
#define INBYTE() read_C012(inputData)
|
|
|
|
/*{{{ void setLA ( int32 addr )*/
|
|
void setLA ( int32 C012_addr )
|
|
{
|
|
C012 = C012_addr;
|
|
inputData = C012;
|
|
outputData = inputData + 1;
|
|
inputStatus = outputData + 1;
|
|
outputStatus = inputStatus + 1;
|
|
resetRoot = C012 + 16;
|
|
analyseRoot = resetRoot+1;
|
|
ok_to_fifo = C012 + 16;
|
|
}
|
|
/*}}} */
|
|
/*{{{ void initLA ( )*/
|
|
void initLA ()
|
|
{
|
|
return;
|
|
}
|
|
/*}}} */
|
|
/*{{{ int32 outputOrFail ( unsigned char b)*/
|
|
int32 outputOrFail ( unsigned char b)
|
|
{
|
|
int32 i;
|
|
|
|
link_io_ABORTCHECK;
|
|
|
|
write_C012(outputData, b);
|
|
for (i=0; i<failed; i++ ) {
|
|
if (OUTPUT_READY) return(1);
|
|
}
|
|
printf ( "Fail in outputOrFail\n" );
|
|
|
|
link_io_EXITZERO;
|
|
}
|
|
/*}}} */
|
|
/*{{{ int32 inputOrFail ( unsigned char *b)*/
|
|
int32 inputOrFail ( unsigned char *b)
|
|
{
|
|
int32 i;
|
|
|
|
link_io_ABORTCHECK;
|
|
|
|
for (i=0; i<failed; i++ ) {
|
|
if (INPUT_READY) {
|
|
*b = read_C012(inputData);
|
|
return(1);
|
|
}
|
|
}
|
|
linkio_error ( "Fail in inputOrFail\n" );
|
|
return 0;
|
|
|
|
link_io_EXITZERO;
|
|
|
|
}
|
|
/*}}} */
|
|
|
|
/*{{{ void resetLoop()*/
|
|
static void resetLoop()
|
|
{
|
|
clock_t the_time=clock();
|
|
|
|
while (the_time==clock());
|
|
while (the_time==clock());
|
|
}
|
|
/*}}} */
|
|
/*{{{ static void reset()*/
|
|
void reset()
|
|
{
|
|
write_C012(analyseRoot,0);
|
|
write_C012(resetRoot, 0);
|
|
resetLoop();
|
|
write_C012(resetRoot, 1);
|
|
resetLoop();
|
|
write_C012(outputStatus, 0);
|
|
write_C012(inputStatus, 0);
|
|
write_C012(resetRoot, 0);
|
|
}
|
|
/*}}} */
|
|
|
|
|
|
/*{{{ int32 outRecord(register char *packet, int32 bytes )*/
|
|
int32 outRecord(register char *packet, int32 bytes )
|
|
{
|
|
int32 i;
|
|
int32 j;
|
|
time_t now, then=clock();
|
|
|
|
link_io_ABORTCHECK;
|
|
|
|
/*
|
|
if (outveryfast(packet, C012, bytes)) return 1;
|
|
linkio_error ("timeout in outRecord\n");
|
|
goto abort;
|
|
*/
|
|
|
|
for (j=0; j<bytes; j++ ) {
|
|
for (i=0; 1; i++ ) {
|
|
if (OUTPUT_READY) {
|
|
OUTBYTE(*packet++);
|
|
break;
|
|
}
|
|
else if (i>=failed) {
|
|
i=0;
|
|
now=clock();
|
|
if ((now - then) > (time_t) (CLOCKS_PER_SEC * time_out_seconds)) {
|
|
linkio_error ("timeout in outRecord\n");
|
|
goto abort;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return(1);
|
|
|
|
link_io_EXITZERO;
|
|
}
|
|
/*}}} */
|
|
|
|
/*{{{ int32 inRecord(register char *packet, int32 bytes )*/
|
|
int32 inRecord(register char *packet, int32 bytes )
|
|
{
|
|
int32 j;
|
|
int32 i;
|
|
time_t now, then=clock();
|
|
|
|
link_io_ABORTCHECK;
|
|
|
|
for (j=0; j<bytes; j++ ) {
|
|
for (i=0; 1; i++ ) {
|
|
if (INPUT_READY) {
|
|
*packet++ = INBYTE();
|
|
break;
|
|
}
|
|
else if (i>=failed) {
|
|
i=0;
|
|
now=clock();
|
|
if ((now - then) > (time_t) (CLOCKS_PER_SEC * time_out_seconds)) {
|
|
linkio_error ("timeout in inRecord\n");
|
|
goto abort;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return(1);
|
|
|
|
link_io_EXITZERO;
|
|
}
|
|
/*}}} */
|
|
|
|
/*{{{ int32 inputReady(void)*/
|
|
int32 inputReady(void)
|
|
{
|
|
int32 t=INPUT_READY;
|
|
|
|
return t;
|
|
}
|
|
/*}}} */
|
|
/*{{{ int32 altRecord()*/
|
|
int32 altRecord(void)
|
|
{
|
|
return (inputReady());
|
|
}
|
|
/*}}} */
|
|
/*{{{ int32 fifo_ok_status(void)*/
|
|
int32 fifo_ok_status(void)
|
|
{
|
|
return (1 & read_C012(ok_to_fifo));
|
|
}
|
|
/*}}} */
|
|
/*}}} */
|
|
#endif
|
|
|
|
#ifdef UNIX
|
|
/*{{{ UNIX support*/
|
|
#include <sys/types.h>
|
|
#include <sys/fcntl.h>
|
|
#include <sys/dbi0110.h>
|
|
static int32 linkfd = -1;
|
|
static char device_name[256];
|
|
|
|
void setLA ( int32 addr )
|
|
{
|
|
if (addr == 0x150) {
|
|
strcpy ( device_name, "/dev/bviii0" );
|
|
}
|
|
else if (addr == 0x200) {
|
|
strcpy ( device_name, "/dev/bviii1" );
|
|
}
|
|
}
|
|
|
|
int32 inputReady(void);
|
|
|
|
void
|
|
initLA (void)
|
|
{
|
|
|
|
if((linkfd = open(device_name, O_RDWR)) == -1) {
|
|
link_io_error("can't open link adaptor \"%s\".\n", device_name );
|
|
}
|
|
inputReady();
|
|
}
|
|
|
|
static char
|
|
inByte()
|
|
{
|
|
|
|
char b;
|
|
read( linkfd, &b, 1 );
|
|
return b;
|
|
}
|
|
|
|
long
|
|
outputOrFail ( unsigned char b)
|
|
{
|
|
/* should set up to do ndelay style stuff,and check status*/
|
|
write(linkfd, &b, 1);
|
|
return 1;
|
|
}
|
|
|
|
long
|
|
inputOrFail ( unsigned char *b)
|
|
{
|
|
if(read(linkfd, b, 1) != 1) {
|
|
link_io_error("Failed to write 1 byte to link adaptor.\n");
|
|
}
|
|
return 1;
|
|
}
|
|
void
|
|
reset()
|
|
{
|
|
union B008_IO dat;
|
|
dat.set.op = RESET;
|
|
dat.set.val = 0;
|
|
|
|
ioctl(linkfd,SETFLAGS, &dat);
|
|
|
|
}
|
|
long
|
|
outRecord(char *packet, int32 bytes )
|
|
{
|
|
int32 byteswritten;
|
|
|
|
if ((byteswritten = write(linkfd,packet, bytes)) != bytes) {
|
|
link_io_error("Tried to write %ld bytes, got %ld.\n",bytes, byteswritten);
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
long
|
|
inRecord(char *packet, int32 bytes )
|
|
{
|
|
return read (linkfd,packet, bytes);
|
|
}
|
|
|
|
int32 inputReady (void)
|
|
{
|
|
union B008_IO dat;
|
|
|
|
if (ioctl(linkfd,READFLAGS, &dat) == (-1)) {
|
|
printf ("IOCTL failed\n" );
|
|
return -1;
|
|
}
|
|
return dat.status.read_f;
|
|
}
|
|
|
|
|
|
int32 outputReady ( void )
|
|
{
|
|
union B008_IO dat;
|
|
|
|
if (ioctl(linkfd,READFLAGS, &dat) == (-1)) {
|
|
printf ("IOCTL failed\n" );
|
|
return -1;
|
|
}
|
|
|
|
return dat.status.write_f;
|
|
}
|
|
|
|
|
|
int32 altRecord(void)
|
|
{
|
|
return inputReady();
|
|
}
|
|
/*}}} */
|
|
#endif
|
|
|
|
#ifdef TRANNY
|
|
/*{{{ transputer direct link support code*/
|
|
#include <process.h>
|
|
#include <channel.h>
|
|
Channel *out_link = (Channel *) (0x80000000 | 0x0c);
|
|
Channel *in_link = (Channel *) (0x80000000 | 0x1c);
|
|
|
|
/*{{{ void initLA (void)*/
|
|
void initLA (void)
|
|
{
|
|
}
|
|
/*}}} */
|
|
/*{{{ void setLA ( int32 slot )*/
|
|
void setLA ( int32 slot )
|
|
{
|
|
out_link = (Channel *) (0x80000000 | (slot<<2));
|
|
in_link = (Channel *) (0x80000000 | ((slot+4)<<2));
|
|
}
|
|
/*}}} */
|
|
/*{{{ static char inByte()*/
|
|
static char inByte()
|
|
{
|
|
|
|
char b;
|
|
ChanIn ( in_link, &b, 1 );
|
|
return b;
|
|
}
|
|
/*}}} */
|
|
/*{{{ void resetLoop()*/
|
|
void resetLoop()
|
|
{
|
|
ProcWait ( 1000 );
|
|
}
|
|
/*}}} */
|
|
/*{{{ void reset()*/
|
|
void reset()
|
|
{
|
|
ChanReset(in_link);
|
|
ChanReset(out_link);
|
|
|
|
resetLoop();
|
|
}
|
|
/*}}} */
|
|
/*{{{ int32 outRecord(char *packet, int32 bytes )*/
|
|
int32 outRecord(char *packet, int32 bytes )
|
|
{
|
|
int32 kill_time;
|
|
|
|
kill_time = ProcTimePlus ( ProcTime(), 15625 * time_out_seconds );
|
|
|
|
if (ChanOutTimeFail ( out_link, packet, bytes, kill_time )) {
|
|
link_io_error ( "outRecord managed %ld of %ld\n", 0, bytes );
|
|
}
|
|
return(1);
|
|
}
|
|
/*}}} */
|
|
/*{{{ int32 inRecord(char *packet, int32 bytes )*/
|
|
int32 inRecord(char *packet, int32 bytes )
|
|
{
|
|
int32 kill_time;
|
|
|
|
kill_time = ProcTimePlus ( ProcTime(), 15625 * time_out_seconds );
|
|
|
|
if (ChanInTimeFail ( in_link, packet, bytes, kill_time )) {
|
|
ChanReset (in_link);
|
|
return(0);
|
|
}
|
|
else
|
|
return(1);
|
|
}
|
|
/*}}} */
|
|
/*{{{ int32 inputReady (void)*/
|
|
int32 inputReady (void)
|
|
{
|
|
return ( ProcSkipAlt ( in_link, NULL ) == 0);
|
|
}
|
|
/*}}} */
|
|
/*{{{ int32 altRecord()*/
|
|
int32 altRecord(void)
|
|
{
|
|
return inputReady();
|
|
}
|
|
/*}}} */
|
|
/*}}} */
|
|
#endif
|
|
|