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>
767 lines
17 KiB
C++
767 lines
17 KiB
C++
/*{{{ header*/
|
|
/****************************************************************************/
|
|
/* */
|
|
/* DIVISION */
|
|
/* -------- */
|
|
/* */
|
|
/* (C) Copyright 1990 DIVISION Limited */
|
|
/* */
|
|
/****************************************************************************/
|
|
|
|
/*
|
|
PROJECT: --
|
|
SUBSYSTEM: TTM100 860 RPC KERNEL
|
|
|
|
MODULE: dnet
|
|
FILE: dnc.c
|
|
|
|
AUTHOR: PJA
|
|
DATE: 8th feb 1991
|
|
|
|
*/
|
|
|
|
/*}}} */
|
|
/*{{{ function*/
|
|
/*
|
|
|
|
FUNCTION:- dNet communications support for i860
|
|
|
|
*/
|
|
/*}}} */
|
|
/*{{{ includes and externs*/
|
|
extern void _lockCCB(void);
|
|
extern void _freeCCB(void);
|
|
|
|
/* extern int command_no; */
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include "dpltypes.h"
|
|
#include "cm200io.h"
|
|
|
|
extern Set();
|
|
extern dnc_Wait_count(void *, int);
|
|
|
|
#define start_transaction(t,n) \
|
|
_lockCCB(); \
|
|
Wait (&output_ccb->lock ); \
|
|
output_ccb->command_type = t; \
|
|
output_ccb->command_no = n; \
|
|
output_ccb->ack = 1
|
|
|
|
#define end_transaction() \
|
|
Wait (&output_ccb->ack); \
|
|
bla(100); \
|
|
_freeCCB()
|
|
|
|
/* #define end_transaction() dnc_Wait_count (&output_ccb->ack, 500) */
|
|
|
|
#define event() Set(&ioc->tevent,1)
|
|
/*}}} */
|
|
|
|
int *uncached_input_block=(int *) 0;
|
|
int *uncached_output_block=(int *) 0;
|
|
int *uncached_general_block=(int *) 0;
|
|
|
|
/* NOTE under velocirender, all data packets are <= 256 bytes */
|
|
|
|
/*{{{ void dN_send (int Dnode, int size, char *block, int sync)*/
|
|
void dN_send (int Dnode, int size, char *block, int sync)
|
|
{
|
|
/* i860 sends a block to transputer for DIVNET */
|
|
|
|
int *dptr = (int *) &output_ccb->data[0];
|
|
|
|
memcpy ( uncached_output_block, block, size );
|
|
start_transaction(IO_DNC_SEND, size);
|
|
|
|
*dptr++ = Dnode;
|
|
*dptr = (int) uncached_output_block; /* address of outgoing block */
|
|
|
|
event();
|
|
|
|
if (sync) end_transaction(); /* Wait for Ack from TP */
|
|
|
|
}
|
|
/*}}} */
|
|
/*{{{ void dN_receive (int *Fnode, int *size, char *block, int sync )*/
|
|
void dN_receive (int *Fnode, int *size, char *block, int sync )
|
|
{
|
|
/* i860 wants a block off transputer from DIVNET */
|
|
|
|
int *dptr = (int *) &output_ccb->data[0];
|
|
|
|
start_transaction(IO_DNC_RECEIVE, *size);
|
|
|
|
/* direct input to ccb then memcpy but N O C A C H E F L U S H ! */
|
|
|
|
dptr[0] = *Fnode;
|
|
dptr[1] = (int) uncached_input_block; /* address of block */
|
|
|
|
event();
|
|
|
|
if (sync) {
|
|
end_transaction();
|
|
*size = input_ccb->command_no;
|
|
|
|
memcpy ( block, uncached_input_block, *size );
|
|
|
|
if (*Fnode == 0) {
|
|
*Fnode = input_ccb->ack;
|
|
input_ccb->ack=0;
|
|
}
|
|
}
|
|
}
|
|
/*}}} */
|
|
|
|
/*{{{ void dN_mynode (int *mynode)*/
|
|
void dN_mynode (int *mynode)
|
|
{
|
|
/* ENDHACK */
|
|
start_transaction(IO_DNC_MYID, 0);
|
|
|
|
event();
|
|
|
|
end_transaction();
|
|
|
|
*mynode = input_ccb->command_no;
|
|
}
|
|
/*}}} */
|
|
/*{{{ void dN_nodes (int *nodecnt)*/
|
|
void dN_nodes (int *nodecnt)
|
|
{
|
|
start_transaction(IO_DNC_NODES, 0);
|
|
|
|
event();
|
|
|
|
end_transaction();
|
|
|
|
*nodecnt = input_ccb->command_no;
|
|
}
|
|
/*}}} */
|
|
/*{{{ void dN_poll (int *nodecnt)*/
|
|
void dN_poll (int *ready)
|
|
{
|
|
start_transaction(IO_DNC_POLL, 0);
|
|
|
|
event();
|
|
|
|
end_transaction();
|
|
|
|
*ready = input_ccb->command_no;
|
|
}
|
|
/*}}} */
|
|
/*{{{ void dN_timer (int *tranny_clk)*/
|
|
void dN_timer (int *tranny_clk)
|
|
{
|
|
int *dptr = (int *) &input_ccb->data[0];
|
|
|
|
start_transaction(IO_TIMER, 0);
|
|
|
|
event();
|
|
|
|
end_transaction();
|
|
|
|
*tranny_clk=*dptr;
|
|
}
|
|
/*}}} */
|
|
/*{{{ void dN_wait ( int *Fnode, int *size )*/
|
|
void dN_wait ( int *Fnode, int *size )
|
|
{
|
|
end_transaction();
|
|
|
|
*size = input_ccb->command_no;
|
|
if (*Fnode == 0) {
|
|
*Fnode = input_ccb->ack;
|
|
input_ccb->ack=0;
|
|
}
|
|
}
|
|
/*}}} */
|
|
/*{{{ void dN_wait_ack ()*/
|
|
void dN_wait_ack ()
|
|
{
|
|
end_transaction();
|
|
}
|
|
/*}}} */
|
|
|
|
/*{{{ void dN_ld_run (int linkno)*/
|
|
void dN_ld_run (int linkno)
|
|
{
|
|
start_transaction(IO_LD_RUN_DRIVER, linkno);
|
|
|
|
flush();
|
|
event();
|
|
|
|
end_transaction();
|
|
}
|
|
/*}}} */
|
|
/*{{{ void dN_ld_out_noflush (int linkno, char *data, int size)*/
|
|
void dN_ld_out_noflush (int linkno, char *data, int size)
|
|
{
|
|
int *dptr = (int *) &output_ccb->data[0];
|
|
|
|
start_transaction(IO_LD_LINK_OUT, linkno);
|
|
|
|
*dptr++=(int) data;
|
|
*dptr++=size;
|
|
|
|
event();
|
|
|
|
end_transaction();
|
|
}
|
|
/*}}} */
|
|
/*{{{ void dN_ld_out (int linkno, char *data, int size)*/
|
|
void dN_ld_out (int linkno, char *data, int size)
|
|
{
|
|
int *dptr = (int *) &output_ccb->data[0];
|
|
|
|
start_transaction(IO_LD_LINK_OUT, linkno);
|
|
|
|
*dptr++=(int) data;
|
|
*dptr++=size;
|
|
|
|
flush();
|
|
event();
|
|
|
|
end_transaction();
|
|
}
|
|
/*}}} */
|
|
/*{{{ void dN_ld_ccb_out (int linkno, char *data, int size)*/
|
|
void dN_ld_ccb_out (int linkno, char *data, int size)
|
|
{
|
|
|
|
int i, ndbl=(size+7)>>3;
|
|
double *ds=(double *) data, *dd=(double *) &output_ccb->data[0];
|
|
|
|
start_transaction(IO_LD_CCB_LINK_OUT, linkno|(size<<8));
|
|
|
|
for (i=0; i<ndbl; i++ ) {
|
|
*dd++=*ds++;
|
|
}
|
|
|
|
event();
|
|
end_transaction();
|
|
}
|
|
/*}}} */
|
|
/*{{{ void dN_ld_ccb_in (int linkno, char *data, int size)*/
|
|
void dN_ld_ccb_in (int linkno, char *data, int size)
|
|
{
|
|
int *dptr = (int *) &output_ccb->data[0];
|
|
|
|
start_transaction(IO_LD_LINK_IN, linkno);
|
|
|
|
*dptr++=(int) data;
|
|
*dptr++=size;
|
|
|
|
event();
|
|
end_transaction();
|
|
}
|
|
/*}}} */
|
|
/*{{{ void dN_ld_in (int linkno, char *data, int size)*/
|
|
void dN_ld_in (int linkno, char *data, int size)
|
|
{
|
|
int *dptr = (int *) &output_ccb->data[0];
|
|
|
|
start_transaction(IO_LD_LINK_IN, linkno);
|
|
|
|
*dptr++=(int) data;
|
|
*dptr++=size;
|
|
|
|
flush();
|
|
event();
|
|
|
|
end_transaction();
|
|
}
|
|
/*}}} */
|
|
/*{{{ void dN_ld_out_2D (int linkno, char *data, int width, int stride, int length )*/
|
|
void dN_ld_out_2D (int linkno, char *data, int width, int stride, int length )
|
|
{
|
|
int *dptr = (int *) &output_ccb->data[0];
|
|
|
|
start_transaction(IO_LD_LINK_OUT_2D, linkno);
|
|
|
|
*dptr++=(int) data;
|
|
*dptr++=width;
|
|
*dptr++=stride;
|
|
*dptr++=length;
|
|
|
|
flush();
|
|
event();
|
|
|
|
end_transaction();
|
|
}
|
|
/*}}} */
|
|
/*{{{ void dN_ld_in_2D (int linkno, char *data, int width, int stride, int length )*/
|
|
void dN_ld_in_2D (int linkno, char *data, int width, int stride, int length )
|
|
{
|
|
int *dptr = (int *) &output_ccb->data[0];
|
|
|
|
start_transaction(IO_LD_LINK_IN_2D, linkno);
|
|
|
|
*dptr++=(int) data;
|
|
*dptr++=width;
|
|
*dptr++=stride;
|
|
*dptr++=length;
|
|
|
|
flush();
|
|
event();
|
|
|
|
end_transaction();
|
|
}
|
|
/*}}} */
|
|
/*{{{ int dN_ld_stat (int linkno)*/
|
|
int dN_ld_stat (int linkno)
|
|
{
|
|
int *dptr = (int *) &input_ccb->data[0];
|
|
|
|
start_transaction(IO_LD_LINK_STATUS, linkno );
|
|
|
|
event();
|
|
|
|
end_transaction();
|
|
|
|
return(*dptr);
|
|
}
|
|
/*}}} */
|
|
|
|
/*{{{ int stat ( int link )*/
|
|
static int stat ( int link )
|
|
{
|
|
return ( dN_ld_stat(link));
|
|
}
|
|
/*}}} */
|
|
/*{{{ void spin( int link )*/
|
|
void spin( int link )
|
|
{
|
|
int tries=0;
|
|
while (stat(link)!=0) {
|
|
tries++;
|
|
}
|
|
}
|
|
/*}}} */
|
|
|
|
/* pxpl5 support pja august 1993 */
|
|
#define pxpl5_init 0
|
|
#define pxpl5_dma 1
|
|
#define pxpl5_texels 2
|
|
#define pxpl5_microwords 3
|
|
#define pxpl5_microload 4
|
|
#define pxpl5_pixels 5
|
|
#define pxpl5_fx_texels 6
|
|
|
|
static int *peek_addr=NULL;
|
|
|
|
/*{{{ void dN_pxpl5_readpixels ( int *data, int x, int y, int pixels )*/
|
|
void dN_pxpl5_readpixels ( int *data, int x, int y, int pixels )
|
|
{
|
|
/*
|
|
implemented as a copy from texel store to ccb->data[5], then interrupt
|
|
tranny, pointing it at ccb->data[5], from where it copies into the texture
|
|
FIFO
|
|
*/
|
|
int *src, *dst, i, *dptr=(int *) (&output_ccb->data[0]);
|
|
|
|
/* printf ("dN_pixels waiting for ccb->lock\n" ); */
|
|
|
|
start_transaction ( IO_PXPL5, 0 );
|
|
dptr[0]=pxpl5_pixels;
|
|
dptr[1]=x;
|
|
dptr[2]=y;
|
|
dptr[3]=pixels;
|
|
dptr[4]=(int) (&dptr[5]);
|
|
|
|
Set (&ioc->tevent, 1);
|
|
|
|
end_transaction();
|
|
|
|
memcpy ( data, (char *) (&dptr[5]), 4*pixels );
|
|
}
|
|
/*}}} */
|
|
|
|
/*{{{ void dN_pxpl5_init ( int magicL, int magicR, int clk_speed )*/
|
|
void dN_pxpl5_init ( int magicL, int magicR )
|
|
{
|
|
int *dptr=(int *) (&output_ccb->data[0]);
|
|
|
|
start_transaction ( IO_PXPL5, 0 );
|
|
|
|
dptr[0]=pxpl5_init;
|
|
dptr[1]=(int) uncached_general_block;
|
|
dptr[2]=magicL;
|
|
dptr[3]=magicR;
|
|
|
|
setpxpl5VideoMode ( magicL );
|
|
|
|
Set (&ioc->tevent, 1);
|
|
|
|
end_transaction();
|
|
}
|
|
/*}}} */
|
|
/*{{{ int dN_pxpl5_dma_done ()*/
|
|
int dN_pxpl5_dma_done ()
|
|
{
|
|
int t=1;
|
|
|
|
if (peek_addr) {
|
|
t=i860_locked_read(peek_addr);
|
|
}
|
|
|
|
return t;
|
|
}
|
|
/*}}} */
|
|
/*{{{ void dN_pxpl5_dma ( int address, int *ack_address, int *end_of_texture_seq )*/
|
|
int dN_pxpl5_dma ( int address, int *ack_address,
|
|
int *end_of_texture_seq,
|
|
vfptr pre_dma )
|
|
{
|
|
int *dptr=(int *) (&output_ccb->data[0]);
|
|
int t, then, now;
|
|
|
|
/*
|
|
printf ("dN_pxpl5_dma 0x%x ack_address 0x%x\n", address, ack_address );
|
|
*/
|
|
|
|
/* hits ram every 250 blas, around 5uS */
|
|
|
|
dN_timer ( &then );
|
|
if (peek_addr)
|
|
wait_locked_nonzero ( peek_addr, 300 );
|
|
dN_timer ( &now );
|
|
|
|
peek_addr=ack_address;
|
|
|
|
if (pre_dma)
|
|
(*pre_dma)();
|
|
|
|
ack_address[0]=0;
|
|
ack_address[2]=(int) end_of_texture_seq;
|
|
|
|
/*
|
|
printf ("dN_pxpl5_dma Wait on lock\n" );
|
|
*/
|
|
|
|
start_transaction ( IO_PXPL5, 0 );
|
|
|
|
*peek_addr=0x0;
|
|
|
|
dptr[0]=pxpl5_dma;
|
|
dptr[1]=address;
|
|
dptr[2]=(int) ack_address;
|
|
|
|
Set (&ioc->tevent, 1);
|
|
|
|
end_transaction();
|
|
return (now-then);
|
|
|
|
/*
|
|
printf ("dN_pxpl5_dma got ack\n" );
|
|
*/
|
|
}
|
|
/*}}} */
|
|
/*{{{ void dN_pxpl5_texels ( int pxpl5_address, int *texelptr, int texels )*/
|
|
void dN_pxpl5_texels ( int pxpl5_address, int *texelptr, int texels )
|
|
{
|
|
/*
|
|
implemented as a copy from texel store to ccb->data[5], then interrupt
|
|
tranny, pointing it at ccb->data[5], from where it copies into the texture
|
|
FIFO
|
|
*/
|
|
int *src, *dst, i, *dptr=(int *) (&output_ccb->data[0]);
|
|
|
|
/* printf ("dN_texels waiting for ccb->lock\n" ); */
|
|
|
|
start_transaction ( IO_PXPL5, 0 );
|
|
|
|
src=texelptr;
|
|
dst=&dptr[5];
|
|
|
|
/* convert to pxpl5 algnment */
|
|
for (i=0; i<texels; i++ ) {
|
|
unsigned char *csrc=(unsigned char *) src, r, g, b;
|
|
|
|
r=0xff & csrc[3];
|
|
g=0xff & csrc[2];
|
|
b=0xff & csrc[1];
|
|
|
|
*dst++=(int) r | ((int) g) << 8 | ((int) b) << 16;
|
|
src++;
|
|
}
|
|
|
|
dptr[0]=pxpl5_texels;
|
|
dptr[1]=pxpl5_address;
|
|
dptr[2]=(int) (&dptr[5]);
|
|
dptr[3]=texels;
|
|
|
|
Set (&ioc->tevent, 1);
|
|
|
|
end_transaction();
|
|
}
|
|
/*}}} */
|
|
/*{{{ void dN_pxpl5_texture24 ( int *texture, int pxpl5_address, int edge )*/
|
|
void dN_pxpl5_texture24 ( int *texture, int pxpl5_address, int edge )
|
|
{
|
|
int texels=edge*edge;
|
|
|
|
while (texels) {
|
|
if (peek_addr)
|
|
wait_locked_nonzero ( peek_addr, 800 );
|
|
|
|
if (peek_addr)
|
|
wait_locked_nonzero ( peek_addr, 800 );
|
|
|
|
dN_pxpl5_texels ( pxpl5_address, texture, 32 );
|
|
|
|
texels-=32;
|
|
pxpl5_address+=32;
|
|
texture+=32;
|
|
}
|
|
if (peek_addr)
|
|
wait_locked_nonzero ( peek_addr, 800 );
|
|
|
|
if (peek_addr)
|
|
wait_locked_nonzero ( peek_addr, 800 );
|
|
|
|
dN_pxpl5_texels ( pxpl5_address-32, texture-32, 32 );
|
|
}
|
|
/*}}} */
|
|
/*{{{ void dN_pxpl5_fx_texels ( int pxpl5_address, int *texelptr, int texels )*/
|
|
void dN_pxpl5_fx_texels ( int pxpl5_address, int *texelptr, int texels )
|
|
{
|
|
/*
|
|
implemented as a copy from texel store to ccb->data[5], then interrupt
|
|
tranny, pointing it at ccb->data[5], from where it copies into the texture
|
|
FIFO
|
|
*/
|
|
int *src, *dst, i, *dptr=(int *) (&output_ccb->data[0]);
|
|
|
|
start_transaction ( IO_PXPL5, 0 );
|
|
|
|
src=texelptr;
|
|
dst=&dptr[5];
|
|
|
|
/* convert to pxpl5 algnment */
|
|
for (i=0; i<texels; i++ ) {
|
|
unsigned char *csrc=(unsigned char *) src, r, g, b;
|
|
|
|
r=0xff & csrc[3];
|
|
g=0xff & csrc[2];
|
|
b=0xff & csrc[1];
|
|
|
|
*dst++=(int) r | ((int) g) << 8 | ((int) b) << 16;
|
|
src++;
|
|
}
|
|
|
|
dptr[0]=pxpl5_fx_texels;
|
|
dptr[1]=pxpl5_address;
|
|
dptr[2]=(int) (&dptr[5]);
|
|
dptr[3]=texels;
|
|
|
|
Set (&ioc->tevent, 1);
|
|
|
|
end_transaction();
|
|
}
|
|
/*}}} */
|
|
/*{{{ void dN_pxpl5_fx_texture24 ( int *texture, int pxpl5_address, int edge )*/
|
|
void dN_pxpl5_fx_texture24 ( int *texture, int pxpl5_address, int edge )
|
|
{
|
|
int texels=edge*edge;
|
|
|
|
while (texels) {
|
|
if (peek_addr)
|
|
wait_locked_nonzero ( peek_addr, 800 );
|
|
|
|
if (peek_addr)
|
|
wait_locked_nonzero ( peek_addr, 800 );
|
|
|
|
dN_pxpl5_fx_texels ( pxpl5_address, texture, 32 );
|
|
|
|
texels-=32;
|
|
pxpl5_address+=32;
|
|
texture+=32;
|
|
}
|
|
if (peek_addr)
|
|
wait_locked_nonzero ( peek_addr, 800 );
|
|
}
|
|
/*}}} */
|
|
|
|
/*{{{ static void pxpl5_texels_8 ( int pxpl5_address, int *texelptr, int texels )*/
|
|
static void pxpl5_texels_8 ( int pxpl5_address, int *texelptr, int texels )
|
|
{
|
|
int *src, *dst, *dptr=(int *) (&output_ccb->data[0]);
|
|
|
|
start_transaction ( IO_PXPL5, 0 );
|
|
|
|
src=texelptr;
|
|
dst=&dptr[5];
|
|
|
|
memcpy ( dst, src, texels*sizeof(int));
|
|
|
|
dptr[0]=pxpl5_texels;
|
|
dptr[1]=pxpl5_address;
|
|
dptr[2]=(int) dst;
|
|
dptr[3]=texels;
|
|
|
|
Set (&ioc->tevent, 1);
|
|
|
|
end_transaction();
|
|
}
|
|
/*}}} */
|
|
|
|
/*{{{ static int luminize ( int texel )*/
|
|
static int luminize ( int texel )
|
|
{
|
|
/* returns a 6-bit luminance value from a 24-bit texel */
|
|
int r, g, b;
|
|
|
|
r=(texel>>24) & 0xff;
|
|
g=(texel>>16) & 0xff;
|
|
b=(texel>>8) & 0xfe;
|
|
|
|
r = ((r*13) + (b*7) + (g*44)) >> 8;
|
|
|
|
if (r > 63) r=63;
|
|
|
|
return r;
|
|
}
|
|
|
|
/*}}} */
|
|
/*{{{ void dN_pxpl5_texture8 ( int *texture, int pxpl5_address, int edge, int wrap )*/
|
|
void dN_pxpl5_texture8 ( int *texture, int pxpl5_address, int edge, int wrap )
|
|
{
|
|
int texels=0, t, s;
|
|
int *scratch=malloc(64*sizeof(int));
|
|
int *thisRow, *nextRow;
|
|
|
|
for (t=0; t<edge; t++ ) {
|
|
/*{{{ set up pointers to rows*/
|
|
thisRow = texture + (t * edge);
|
|
nextRow = thisRow + edge;
|
|
texels = 0;
|
|
|
|
if (t==(edge-1)) {
|
|
if (wrap)
|
|
nextRow=texture;
|
|
else
|
|
nextRow=thisRow;
|
|
}
|
|
|
|
/*}}} */
|
|
for (s=0; s<edge; s++ ) {
|
|
/*{{{ locals*/
|
|
int lower_left,
|
|
lower_right,
|
|
upper_left,
|
|
upper_right, t;
|
|
/*}}} */
|
|
|
|
lower_left =luminize (thisRow[s]);
|
|
lower_right=luminize (thisRow[s+1]);
|
|
|
|
upper_left =luminize (nextRow[s]);
|
|
upper_right=luminize (nextRow[s+1]);
|
|
|
|
if (s==(edge-1)) {
|
|
if (wrap) {
|
|
lower_right=luminize(thisRow[0]);
|
|
upper_right=luminize(nextRow[0]);
|
|
}
|
|
else {
|
|
lower_right=lower_left;
|
|
upper_right=upper_left;
|
|
}
|
|
}
|
|
t = lower_left;
|
|
t |= (lower_right << 6);
|
|
t |= (upper_left << 12);
|
|
t |= (upper_right << 18);
|
|
|
|
scratch[texels]=t;
|
|
texels++;
|
|
|
|
if (texels == 32) {
|
|
/*{{{ */
|
|
if (peek_addr)
|
|
wait_locked_nonzero ( peek_addr, 800 );
|
|
|
|
if (peek_addr)
|
|
wait_locked_nonzero ( peek_addr, 800 );
|
|
/*}}} */
|
|
pxpl5_texels_8 ( pxpl5_address, scratch, 32 );
|
|
pxpl5_address+=32;
|
|
|
|
texels=0;
|
|
}
|
|
}
|
|
}
|
|
/* re-send last few to flush fifo */
|
|
if (peek_addr)
|
|
wait_locked_nonzero ( peek_addr, 800 );
|
|
|
|
if (peek_addr)
|
|
wait_locked_nonzero ( peek_addr, 800 );
|
|
|
|
pxpl5_texels_8 ( pxpl5_address-32, scratch, 32 );
|
|
|
|
free(scratch);
|
|
}
|
|
/*}}} */
|
|
|
|
/*{{{ void dN_pxpl5_microwords ( int *ucode, int baseWord, int uwords )*/
|
|
void dN_pxpl5_microwords ( int *ucode, int baseWord, int uwords )
|
|
{
|
|
/*
|
|
implemented as a copy from ucode store to ccb->data[5], then interrupt
|
|
tranny, pointing it at ccb->data[5], from where it copies into the ucode
|
|
store
|
|
*/
|
|
int *dptr=(int *) (&output_ccb->data[0]);
|
|
|
|
start_transaction ( IO_PXPL5, 0 );
|
|
|
|
memcpy ( &dptr[5], ucode, uwords*sizeof(int));
|
|
|
|
dptr[0]=pxpl5_microwords;
|
|
dptr[1]=(int) (&dptr[5]);
|
|
dptr[2]=baseWord;
|
|
dptr[3]=uwords;
|
|
|
|
Set (&ioc->tevent, 1);
|
|
|
|
end_transaction();
|
|
}
|
|
/*}}} */
|
|
/*{{{ void dN_pxpl5_microcode ( int *ucode, int uwords )*/
|
|
void dN_pxpl5_microcode ( int *ucode, int uwords )
|
|
{
|
|
/* firstly send texels in 64-chunks */
|
|
int baseWord=0;
|
|
|
|
while (dN_pxpl5_dma_done() == 0)
|
|
;
|
|
|
|
while (uwords > 32) {
|
|
dN_pxpl5_microwords ( ucode, baseWord, 32 );
|
|
|
|
ucode+=32;
|
|
uwords-=32;
|
|
baseWord+=32;
|
|
}
|
|
if (uwords)
|
|
dN_pxpl5_microwords ( ucode, baseWord, uwords );
|
|
|
|
/* now tell tranny to load microcode store */
|
|
{
|
|
int *dptr=(int *) (&output_ccb->data[0]);
|
|
|
|
start_transaction ( IO_PXPL5, 0 );
|
|
|
|
dptr[0]=pxpl5_microload;
|
|
|
|
Set (&ioc->tevent, 1);
|
|
|
|
end_transaction();
|
|
}
|
|
}
|
|
/*}}} */
|
|
|