📄 dptarget.c
字号:
/*** File: dptarget.c** Description:** This file contains routines which are meant to be used by target** systems when communicating with the NetROM emulator through Pod 0's** dualport ram.**** Copyright (c) 1996 Applied Microsystems Corporation** All Rights Reserved**** Redistribution and use in source and binary forms are permitted ** provided that the above copyright notice and this paragraph are ** duplicated in all such forms and that any documentation,** advertising materials, and other materials related to such** distribution and use acknowledge that the software was developed ** by Applied Microsystems Corp. (the Company). The name of the ** Company may not be used to endorse or promote products derived** from this software without specific prior written permission. ** THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR ** IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED** WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. **** Modification History: 2/18/94 fdv add two out of band characters to readaddr protocol: RA_RESET and RA_RESYNC. RA_RESET lets the target trigger a tgtreset. RA_RESYNC lets the target trigger the netrom initialize the dualport. 4/7/94 fdv 1. fixed ra_reset and ra_resync. 2. modified read addr reads to "read away" cause of problem seen with ev960ca demo board. 5/4/94 fdv added MISC out of band character to readaddr: subfunction is receive interrupt ack. 5/27/94 fdv added MISC out of band character to readaddr: subfunction is turn off emulate before ra_setmem. 6/16/94 fdv fix to emoffonwrite, it was being called on every set_mem 2/23/95 sch Add virtual ethernet, both ReadAddr and ReadWrite 8/21/95 sch Add read after write check to dp_readint(). This fixes a data corruption problem when sending large amounts of data to the host with little traffic from the host. sch Cleanup: Change xchannels back to channels, delete unused OVERFLOW_MSGS code. sch Add protocol to end of ra_resync(). Wait for NetROM to turn off RI and then turn it back on before exiting, so the target will not try to send or receive until NetROM is done with the resync. sch More cleanup. Fix declarations of several routines so they will agree with their usage. sch In config_dpram, avoid divides when setting oobthresh for readaddr. sch In dp_bread and dp_bwrite, call READ_POD and WRITE_POD if HASCHACHE is true. These routines will deal with turning off the cache. 10/12/95 sch Clean up the ra_resync mod. Take out delay at start. Only wait for RI to go on before returning (NetROM will turn it off before acking the last RE_RESYNC char).*//********************************************************************** Porting notes: OVERVIEW This file contains routines which are meant to be used by target systems when communicating with the NetROM emulator through Pod 0's dualport ram. These routines are byte-oriented for both transmit and receive; however, multibytes messages are passed between target and NetROM whenever possible, to reduce handshaking overhead. Data is collected at the target/NetROM interface a byte at a time and passed over in messages. Messages are fixed-size, fixed format data structures, whose format is as follows: ----------------------------------------- | Flags | Size | Data | ----------------------------------------- ^ ^ ^ | | | 2 bytes | | 2 bytes | 60 bytes Flag values are: 0x8000 Message ready bit 0x0001 Start of message bit (for multiple structure messages) 0x0002 End of message bit (for multiple structure messages) 0x0004 Message structure Wrap bit The Start and End bits are both set in single structure messages. The Wrap bit is used to mark the end of an array of structures (for example, the transmit array). The size field of the structure indicates how many of the data bytes are valid. The size does not include the Flags or the Size field. The message structure is described in more detail in the include file, dualport.h. The protocol between target and NetROM has two distinct flavors; one for targets which are capable of writing dualport ram and one for targets which can only read dualport ram. In general, the target will poll dualport ram for messages; messages will be ready to process when the Ready bit is set. The scenarios for transmitting data to NetROM are different for targets which have write capability and those which do not; they are described below. A key feature of the transmit path from target to NetROM is the target's ability to cause an interrupt to the NetROM by *reading* special areas of dualport ram. When NetROM receives the interrupt, it uses the target's read address to extract an eight-bit value. The value is equal to the offset of the target's read address from the start of the interrupt-causing area of dualport ram. *** Note *** an important issue in communicating with the NetROM is avoiding collisions when accessing dualport ram. In situations where the target and NetROM both access the same dualport address, the target will lose. That is, it will read garbage, or its writes may fail. This is an unavoidable issue, caused by the asynchronous nature of target accesses to emulation pod memory, including dualport ram. Avoiding access collisions when the target sends data to NetROM is accomplished by the NetROM not polling for messages written by the target. Rather, when the target is done writing a message, it sends an interrupt to the NetROM by reading a special address in dualport ram. Only when the NetROM receives the interrupt will it check dualport ram for messages from the target. If the target cannot write dualport ram, all data is passed by read-address interrupts, so access collisions are not a problem. Access collisions when the NetROM writes messages are unavoidable because the target must poll dualport ram for messages. However, the NetROM will only write each byte of ram one time, so the target can verify the Ready bit being set in a message, simply by reading the flags field twice. Since NetROM will only set the Ready bit after it has written the message data, the target only needs to perform a "verification" on the flags fields of message structures. READ-WRITE TARGETS Targets which can write dualport ram will use a dualport memory layout consisting of an array of 64-byte structures. There will be 15 receive structures and 16 transmit data structures. Receive structures will contain messages written by NetROM and transmit structure will be used to send data to NetROM. The configuration/status structure is used to indicate whether or not NetROM is ready to process messages, and reading parts of the configuration/status structure will send interrupts to NetROM. -------------------------------------------- | Configuration/Status Structure (*) | -------------------------------------------- | RX Message Structure 0 | -------------------------------------------- | ... | -------------------------------------------- | RX Message Structure 14 | -------------------------------------------- | TX Message Structure 0 | -------------------------------------------- | ... | -------------------------------------------- | TX Message Structure 15 | -------------------------------------------- The configuration/status structure for targets with write capability is simple: -------------------------------------------- | Interrupt Area | TX | RX | Reserved | -------------------------------------------- ^ ^ ^ ^ | | | | 8 bytes | | | 1 byte | | 1 byte | 54 bytes The target may read from the interrupt area to generate an interrupt to the NetROM. Upon receipt of this interrupt, the NetROM will check the dualport message area for messages from the target. The TX and RX bytes are used to indicate when the NetROM is ready to process messages and interrupts. *** The target should not cause interrupts unless these bytes are set, because NetROM will not detect a missed interrupt. *** READ-ONLY TARGETS Targets which can read but not write dualport ram must use a different mechanism to send data to the NetROM. NetROM contains a special area of memory in Pod 0 which, when read by the target, causes an interrupt to be generated to NetROM's processor. NetROM can determine which address within the 256-byte area was read, and uses this address to calculate an 8-bit number. Using this mechanism, it is possible for the target to send 8-bit data to the NetROM. Sending certain 8-bit values is done in two steps. This is because there are situations in which it is necessary to send out-of-band data to the NetROM; that is, data which is relevant to the protocol but not the the content of messages the target wants to send. For example, when the target reads a message structure written by the NetROM, it cannot clear the Ready bit in the message's flags. Thus, it uses a special value (that is, address) to acknowlege messages received from the NetROM. Distinguishing between ACKs (0xF8) and equivalent values in message data would require a character-stuffing protocol, which is not currently supported. Thus data values greater than 0xF8 are sent in two or more pieces. The first, an "escape" character (0xF9), tells NetROM to add 0xF8 to the next character received. The second piece is the original value minus 0xF8. This "character stuffing" only needs to be done for values greater than 0xF8. The SET character (0xF2) is used when the target system wishes to request that NetROM modify the contents of emulation memory. After receiving the SET character, NetROM will interpret the next four characters as an offset into emulation memory, received most-significant byte first. Following the offset is an 8-bit value to be written. Note that the target software should run from RAM from the time it transmits the value character to the time that NetROM acknowleges the value character. This is to prevent memory contention problems. The set function is implemented by ra_setmem() in this file. The START and END characters are used to delineate a complete message being sent via the read-address protocol. They are analogous to the START and END bits in a dualport message structure. These out-of-band characters are useful when using a UDP transport between NetROM and the host system, since each UDP datagram will contain a complete message. Sending messages is implmented in the ra_putmsg() routine in this file. There is an added subtlety in the read-address protocol, which is that NetROM is unable to detect missed interrupts. As a result, prior to sending each character, the target must be sure that NetROM is listening for interrupts, and that the character that was sent was received. There are two fields in the configuration/status structure which accomplish this; one which is set when the NetROM is listening for interrupts, and one which is incremented for each character (including control characters) that the target sends. These are described below. Note that the values of all escape characters are different for target systems which perform burst reads from emulation pod 0. Consult your netrom manual for information on these types of systems. The target receives messages from the NetROM using a similar protocol to that used by the read-write target. However, it must acknowlege each message with a special character, since it cannot clear Ready bits itself. /-------- 256-byte read-address area; target reads of this area | generate interrupts to the NetROM. | | /-- -------------------------------------------- | | | | | | -- 248-byte ASCII Read-address Data -- --->| | | | -------------------------------------------- | | Control Read-address Data (8 bytes) | \-- -------------------------------------------- | Configuration/Status Structure | -------------------------------------------- | RX Message Structure 0 | -------------------------------------------- | ... | -------------------------------------------- | RX Message Structure 26 | -------------------------------------------- The layout of the control read-address data area. -------------------------------------------------------------- | PACK | ESC | SET | START | END | RESET | RESYNC | MISC | -------------------------------------------------------------- ^ ^ ^ ^ ^ ^ ^ ^ | | | | | | | | 1 byte | | | | | | | 1 byte | | | | | | 1 byte | | | | | 1 byte | | | | 1 byte | | | 1 byte | | 1 byte | 1 byte The PACK byte is used to tell NetROM that a single message has been received from dualport RAM. This byte should be read after *every* dualport message. The ESC byte is used to tell NetROM that the data being transmitted is greater or equal in value than 248 (0xF8). When NetROM receives an ESC character, it will add 0xF8 to the character which follows, and pass the result to higher level protocols as if it were received in a single transmission. RESET lets the target trigger a tgtreset. RESYNC lets the target trigger the netrom initialize the dualport. MISC allows more control by parsing the next char for a subfunction. The subfuntions are: 0x1 Receive Interrupt Acknowledge. 0x2 turn off emulate mode before performing ra_setmem. The layout of the configuration/status structures. -------------------------------------------- | RI | ACK | Reserved | -------------------------------------------- ^ ^ ^ | | | 1 byte | | 1 byte | 62 bytes The RI bit indicates that NetROM is ready to handle interrupts. The ACK byte is an 8-bit counter, which is incremented for each character which the NetROM receives, including control characters such as acks. ABOUT THIS FILE This file contains routines which communicate with the NetROM. To be able to send and receive characters, target-side programmers need only port the clearly marked section at the top of the file. A hook is provided for tasking systems which need to allow processes to run; this is the YIELD_CPU macro. The routine c_dpcons_hdlr() handles receipt of messages from the NetROM. Since the NetROM cannot cause target-side interrupts, it is called when the target checks for data. The entry points that the target programmer needs to use are: config_dpram initializes control structures and configures the target to use dualport in a read-only or read- write fashion. set_dp_blockio allows the target programmer to set or clear a bit in the control structure. When set, the interface routines merely poll for data and return if none is present. Otherwise they will wait for data to appear. dp_chanready returns 1 if the NetROM is ready to process messages; 0 otherwise. chan_kbhit returns 1 if a character is waiting at the dualport interface; 0 otherwise. ra_putch sends a character to the NetROM using the read-address interface. This routine handles all of the appropriate software handshaking. chan_putch sends a character to the NetROM. Actually, it stores characters until the message structure is full or chan_flushtx() is called. This reduces protocol overhead. chan_flushtx sends any characters which have been stored but not yet passed to the NetROM. ra_getch reads a character from the NetROM, if one is present, using the RX message structures of the read-address protocol. chan_getch reads a character from the NetROM, if one is present, using the RX message structures of the readwrite protocol. ra_getmsg reads a message from dualport ram, when using the read-address protocol. chan_getmsg reads a message from dualport ram, when using the readwrite protocol. ra_putmsg sends a complete message delineated by the START and END out-of-band characters. chan_putmsg sends a complete message delineated by the START and END bits in the dualport message structures. This differs from the ra_putch() routine, which treats each dualport message structure as a complete message. ra_setmem requests that NetROM write a byte of emulation memory. if ra_emoffonwrite has been called, emulation memory is turned off before the byte is written. ra_reset requests that NetROM reset the target. ra_resync requests that NetROM re-initialize it's dualport parameters. ra_rx_intr_ack acknowledges a receive interrupt ra_emoffonwrite see ra_setmem Note that the getmsg() routines are used to incrementally fill an input buffer. When used in a polling mode, they return one of four status values: GM_NODATA indicates that no data has arrived since the last poll; GM_MSGCOMPLETE indicates that new data has arrived and that the input buffer now holds the complete message; GM_NOTDONE indicates that data has arrived but that the message is not yet complete; GM_MSGOVERFLOW indicates that more data has arrived, but that it has overflown the input buffer. In a non-polling mode, these routines will return either GM_MSGCOMPLETE or GM_MSGOVERFLOW.*********************************************************************//* Local Defines */#define DUMMY_READ#include "wdb/dpconfig.h" /* This file must be ported to the new target */#include "wdb/dptarget.h" #include "wdb/dualport.h"#include "stdio.h"/* declarations */STATIC void c_dpcons_hdlr();void chan_flushtx();void set_dp_blockio();void ra_putch();int do_emoffonwrite();/* global data */STATIC DpChannel channels[DP_MAXCHANNELS];#ifdef READONLY_TARGETSTATIC int emoffonwrite_set;#endif#ifndef RAWRITES_ONLYSTATIC uInt16 dp_readint();void dp_bwrite();void dp_bread();#ifndef READONLY_TARGET/* writes an int to dp ram */STATIC voiddp_writeint(addr,val)uInt32 addr;uInt16 val;{ /* write in network byte order, lsb first */ WRITE_POD(&channels[0], addr + 1, (uInt32)val & 0xFF); WRITE_POD(&channels[0], addr, (uInt32)(val >> 8) & 0xFF); /* Check that the write was sucessful. See change log dated 8/21/95 at the top of this file for details. */ while (val != dp_readint(addr)) { WRITE_POD(&channels[0], addr + 1, (uInt32)val & 0xFF); WRITE_POD(&channels[0], addr, (uInt32)(val >> 8) & 0xFF); }}#endif/* read an int from dpram */STATIC uInt16dp_readint(addr)uInt32 addr;{ uInt16 val; /* read the msb first, in case it contains flags */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -