📄 dptarget.c
字号:
} /* send the buffer */ nr_WriteInt(chan, cp->tx + DPM_SIZE, (uInt16)bp->bufsize); nr_WriteBuf(chan, bp->buf, cp->tx + DPM_DATA, (Int16) bp->bufsize); bp->flags &= DPMSG_WRAP; nr_WriteInt(chan, cp->tx + DPM_FLAGS, (uInt16)bp->flags | (DPMSG_READY|DPMSG_START|DPMSG_END)); /* notify NetROM that the buffer is ready */ dummy = nr_ReadByte(cp, DP_MRI); /* advance the msg pointer */ if(bp->flags & DPMSG_WRAP) { cp->tx = cp->txbase; } else { cp->tx += DPM_MSGSIZE; } /* clear the buffer structure */ bp->index = 0; bp->bufsize = 0; return Err_NoError;}/*** Function: nr_GetMsg** Description: This routine reads message from dualport ram.** It returns different statuses, depending on whether or not** message data is present, or the message overflows the buffer. ** The number of bytes read into the message buffer is changed** by side effect. ** ** Parameters:** chan channel to read from, 0-3** buf buffer to read into** len number of bytes expected, or max bytes for this buffer** bytesread number of bytes actually received (nr_GetMsg will set this)**** Returns:** Err_BadChan if the chan is invalid** GM_NODATA only returned when not in blocking I/O mode** GM_MSGCOMPLETE** GM_NOTDONE** GM_MSGOVERFLOW*/Int16nr_GetMsg( uInt16 chan, char* buf, uInt16 len, uInt16* bytesread ){ register DpChannel *cp; Int16 done = 0; Int16 nbytes = 0; register uInt16 flags, size;#ifdef VETHER Int16 msg_len = 0;#endif if( chan >= DP_MAXCHANNELS ) /* Invalid channel! */ return Err_BadChan; /* get a pointer to the channel */ cp = &channels[chan]; /* look for the whole message */ while(done == 0) { /* wait for the buffer to become valid */ while(cp->rx == (-1) ) { /* poll for new buffers */ nr_ProcessMsgs(chan); /* did we get a message? */ if(cp->rx == (-1) ) {#ifdef VETHER if((cp->chanflags & CF_NOWAITIO) || (nbytes == 0)) {#else if(cp->chanflags & CF_NOWAITIO) {#endif *bytesread = nbytes; return(nbytes == 0 ? GM_NODATA : GM_NOTDONE); } nr_YieldCPU(); } } /* read the status and size of the new message block */ flags = nr_ReadInt(chan, cp->rx + DPM_FLAGS); size = nr_ReadInt(chan, cp->rx + DPM_SIZE);#ifdef VETHER /* get whole msg len from first pkt of msg */ if (nbytes == 0) { /* if ((flags & DPMSG_START) == 0) printf("no START: %04x ", flags & 0xffff); */ msg_len = (size >> 6) | (flags & DPMSG_1K_BIT); size = size & 0x3f; }#endif /* copy data into the buffer */ if(size > len) { *bytesread = nbytes; return(GM_MSGOVERFLOW); } nr_ReadBuf(chan, cp->rx + DPM_DATA, (uChar*)buf, (Int16)size); /* return the buffer */ nr_WriteInt(chan, cp->rx + DPM_FLAGS, flags & ~DPMSG_READY); /* update our buffer pointers */ buf += size; nbytes += size; len -= size; /* advance the read pointer */ if(flags & DPMSG_WRAP) { cp->rx = cp->rxbase; } else { cp->rx += DPM_MSGSIZE; } /* see if there are more messages waiting */ if(cp->rx == cp->rxlim) { cp->rx = (-1); } /* was this the end of the message? */ if((flags & DPMSG_END) != 0) done = 1; } *bytesread = nbytes;#ifdef VETHER if (nbytes != msg_len) { /* printf("chan_getmsg: 1st pkt len=%d, got %d\n", msg_len, nbytes); */ return(GM_NOTDONE); } else #endif return(GM_MSGCOMPLETE);}/*** Function: nr_PutMsg** Description: send a message to NetROM**** Parameters:** chan channel to write to, 0-3** buf buffer to xmit** len length of buffer to xmit**** Returns:** Err_NoError if the message was sent successfully** Err_NotReady if NetROM is not ready to process messages** Err_BadChan if the chan is invalid*/Int16nr_PutMsg( uInt16 chan, char *buf, uInt16 len ){ register DpChannel *cp; register Int16 num_sent = 0; uInt16 size, num_left = len, ovf_size; register uInt16 flags; if( chan >= DP_MAXCHANNELS ) /* Invalid channel! */ return Err_BadChan; if( !nr_ChanReady(chan) ) /* NetROM isn't ready to process msgs */ return Err_NotReady; /* get a pointer to the channel */ cp = &channels[chan]; while(num_sent < len) { /* wait for the buffer */ while(1) { flags = nr_ReadInt(chan, cp->tx + DPM_FLAGS); if(flags != nr_ReadInt(chan, cp->tx + DPM_FLAGS)) { /* read failed on the verify, NetROM must be writing */ continue; } if((flags & DPMSG_READY) == 0) break; else { nr_YieldCPU(); } } /* get the number of bytes to send in DP struct and overflow */ if(num_left >= DP_DATA_SIZE) { size = DP_DATA_SIZE; if (num_left >= MAX_MSG_SIZE) ovf_size = MAX_OVF_MSG_SIZE; else ovf_size = num_left - DP_DATA_SIZE; } else { size = num_left; ovf_size = 0; } /* fill the currently available DP buffer */ /* Put full msg size in upper bits of first size field */ if (num_sent == 0) { nr_WriteInt(chan, cp->tx + DPM_SIZE, (len << 6) | size); } else nr_WriteInt(chan, cp->tx + DPM_SIZE, size); nr_WriteBuf(chan, (uChar*)buf, cp->tx + DPM_DATA, size); /* get the flags to write */ flags = (flags & DPMSG_WRAP) | DPMSG_READY; if(num_sent == 0) { flags |= DPMSG_START; /* or in 1K bit of msg len */ flags = flags | (len & DPMSG_1K_BIT); } num_sent += size; num_left -= size; if(num_sent >= len) flags |= DPMSG_END; nr_WriteInt(chan, cp->tx + DPM_FLAGS, flags); /* notify NetROM that the buffer is ready */ dummy = nr_ReadByte(cp, DP_MRI); /* adjust pointers */ buf += size; /* advance the msg pointer */ if(flags & DPMSG_WRAP) { cp->tx = cp->txbase; cp->txovf = cp->txovfbase; } else { cp->tx += DPM_MSGSIZE; cp->txovf += MAX_OVF_MSG_SIZE; } } return Err_NoError;}/*** Function: nr_Resync** Description: Requests that NetROM clear out TX & RX buffers for all chans** Blocks until NetROM is finished** Note: nr_Resync must be paired with nr_ConfigDP; if not, ** NetROM and the target will get out of sync**** Parameters:** chan channel to use for resync**** Returns:** Err_BadChan if channel is not in range 0 <= chan < MAXCHANNELS** Err_NotReady if NetROM is not ready to process requests** Err_NoError otherwise*/Int16nr_Resync( uInt16 chan ){ register DpChannel *cp; if( chan >= DP_MAXCHANNELS ) /* Invalid channel! */ return Err_BadChan; if( !nr_ChanReady(chan) ) /* Avoid hang if NetROM is not ready */ return Err_NotReady; cp = &channels[chan]; nr_WriteByte( cp, DP_NR_DONE, False ); /* Force flag to False */ /* Request that NetROM resync the chans */ do{ nr_WriteByte(cp, DP_OOBFLAG, OOBFLAG_RESYNC ); } while( nr_ReadByte(cp, DP_OOBFLAG) != OOBFLAG_RESYNC ); /* Notify NetROM that the it has something to read */ dummy = nr_ReadByte(cp, DP_MRI); /* Block until NetROM finishes the resync */ /* If your code hangs here, NetROM is not resyncing when asked to */ while( False == nr_ReadByte(cp, DP_NR_DONE) ) {} return Err_NoError;}/*** Function: nr_Reset** Description: Requests that NetROM reset the target**** Parameters:** chan channel used for reset message **** Returns:** Err_NoError if the OOB msg was sent successfully** Err_NotReady if NetROM is not ready to process messages** Err_BadChan if the chan is invalid (0,1,2,3 are valid on NR5xx)*/Int16nr_Reset( uInt16 chan ){ return nr_PutOOBMsg(chan, DP_OOB_RESET, NULL, 0);}/*** Function: nr_IntAck** Description: Acknowledges a previous interrupt to the target** ** Parameters:** chan channel to acknowledge interrupt on**** Returns:** Err_NoError if the OOB msg was sent successfully** Err_NotReady if NetROM is not ready to process messages** Err_BadChan if the chan is invalid (0,1,2,3 are valid on NR5xx)*/Int16nr_IntAck( uInt16 chan ){ return nr_PutOOBMsg(chan, DP_OOB_INTACK, NULL, 0);}/*** Function: nr_Cputs** Description: Puts a string to the NetROM console; the** message won't be transmitted to the host**** Parameters:** chan channel to write message through** len length of message, less than 56**** Returns:** Err_NoError if the OOB msg was sent successfully** Err_NotReady if NetROM is not ready to process messages** Err_BadChan if the chan is invalid (0,1,2,3 are valid on NR5xx)** Err_BadLength if the "size" of the buffer is too big** Err_BadCommand if the command is invalid*/Int16nr_Cputs( uInt16 chan, char *buf, uInt16 len ){ char localbuf[60]; if(len > 55) return Err_BadLength; /* Ensure zero-termination */ memcpy( (uChar*)localbuf, (uChar*)buf, len ); localbuf[len] = NULL; return nr_PutOOBMsg(chan, DP_OOB_CPUTS, localbuf, len+1);}#if (READONLY_TARGET == True )/*** Function: nr_SetMem** Description: Requests that NetROM set a block of overlay memory** Note: 1. target must run from RAM while NetROM sets the memory** 2. Total msg size = len+6 = len+sizeof(addr)+sizeof(len)**** Parameters:** chan channel to write to** addr start address for write** buf data to write** len length of buf; must be less than 54 bytes**** Returns:** Err_NoError if successful** Err_BadLength if length is invalid; max block size is 54 bytes** Err_BadChan if the chan is invalid** Err_BadAddress if the address is invalid, i.e. outside ROM*/Int16nr_SetMem( uInt16 chan, uInt32 addr, char* buf, uInt16 len ){ DpSetMemBuf setmem_buf; register DpChannel *cp; uInt16 size; if( chan >= DP_MAXCHANNELS ) /* Invalid channel! */ return Err_BadChan; if( len == 0 || len > DP_DATA_SIZE-6 ) /* Invalid length! */ return Err_BadLength; if( !nr_InROM(addr) ) /* Invalid address! */ return Err_BadAddress; addr -= (uInt32)ROMSTART; /* NetROM references addresses from ROMSTART */ cp = &channels[chan]; /* Get a pointer to the channel */ setmem_buf.addr = swap32(addr); /* Fix big/little -endian */ memcpy( setmem_buf.data, (uChar*)buf, len ); size = len + 4; /* buf length + sizeof(addr) */ if(emoffonwrite_set == True) { nr_PutOOBMsg(chan, DP_OOB_EMOFFONWRITE, NULL, 0); emoffonwrite_set = False; } /* The following nr_PutOOBMsg call should be atomic ** If it is not, make sure that you don't write other messages ** to this channel after you've begun the SetMem sequence! */ nr_InterruptsOFF(); nr_PutOOBMsg(chan, DP_OOB_SETMEM, (char*)&setmem_buf, size); nr_InterruptsON(); return Err_NoError;}#else /* READONLY_TARGET != True *//*** Function: nr_SetMem** Description: Sets a block of overlay memory, up to 54 bytes** This target can write its own memory.** length, channel, and address are checked to** keep this routine consisten with the read-only version**** Parameters:** chan channel to write to** addr start address for write** buf data to write** len length of buf; must be less than 54 bytes**** Returns:** Err_NoError if successful** Err_BadLength if length is invalid** Err_BadChan if the chan is invalid** Err_BadAddress if the address is invalid, i.e. outside ROM*/Int16nr_SetMem( uInt16 chan, uInt32 addr, char *buf, uInt16 len ){ if( !nr_InROM(addr) ) /* Invalid address! */ return Err_BadAddress; if( chan >= DP_MAXCHANNELS ) /* Invalid channel! */ return Err_BadChan; if( len == 0 || len > DP_DATA_SIZE-6 ) /* Invalid length! */ return Err_BadLength; memcpy( (uChar*)addr, (uChar*)buf, (long)len );}#endif /* READONLY_TARGET == True *//*** Function: nr_SetEmOffOnWrite** Parameters:**** Description: After calling this, NetROM will set emulation off** before writing to PodMem. See nr_SetMem().** The default, set in nr_ConfigDP(), is** emoffonwrite_set = False.** Returns:*/voidnr_SetEmOffOnWrite(void){ emoffonwrite_set = True; }/*** Function: nr_WriteInt** Description: Writes a uInt16 to dp RAM** Warning: Assumes 'chan' is valid!**** Parameters:** chan channel to write to** addr start address for write** val data to write**** Returns:*/STATIC voidnr_WriteInt( uInt16 chan, uInt32 addr, register uInt16 val ){ register DpChannel *cp = &channels[chan]; register uInt16 valLSB = (uInt16)val & 0xFF; register uInt16 valMSB = (uInt16)(val >> 8) & 0xFF; /* Write in network byte order, LSB first ** This avoids writing the message-ready bit before other flags, ** which could lead to garbled messages. Make sure that the ** write succeeded--NetROM and target may have been in contention. */ do { nr_WriteByte(cp, addr + 1, valLSB ); nr_WriteByte(cp, addr, valMSB ); } while (val != nr_ReadInt(chan, addr) );}/*** Function: nr_ReadInt** Description: Reads a uInt16 from DP RAM** Warning: Assumes 'chan' is valid**** Parameters:** chan channel to read from** addr start address for read**** Returns:** Int16 from DP RAM*/STATIC uInt16nr_ReadInt( uInt16 chan, uInt32 addr ){ register uInt16 val; register DpChannel *cp = &channels[chan];
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -