/*{{{ 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 #include #include #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; idata[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; itevent, 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; itevent, 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; tdata[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(); } } /*}}} */