dptarget.c
上传用户:nvosite88
上传日期:2007-01-17
资源大小:4983k
文件大小:53k
源码类别:

VxWorks

开发平台:

C/C++

  1. /*
  2. **  File:   dptarget.c
  3. **  Description:
  4. **    This file contains routines which are meant to be used by target
  5. **    systems when communicating with the NetROM emulator through Pod 0's
  6. **    dualport ram.
  7. **
  8. **      Copyright (c) 1996 Applied Microsystems Corporation
  9. **                          All Rights Reserved
  10. **
  11. ** Redistribution and use in source and binary forms are permitted 
  12. ** provided that the above copyright notice and this paragraph are 
  13. ** duplicated in all such forms and that any documentation,
  14. ** advertising materials, and other materials related to such
  15. ** distribution and use acknowledge that the software was developed 
  16. ** by Applied Microsystems Corp. (the Company).  The name of the 
  17. ** Company may not be used to endorse or promote products derived
  18. ** from this software without specific prior written permission. 
  19. ** THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 
  20. ** IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  21. ** WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 
  22. **
  23. **  Modification History:
  24.    2/18/94 fdv add two out of band characters to readaddr protocol:
  25.                 RA_RESET and RA_RESYNC.
  26.                 RA_RESET lets the target trigger a tgtreset.
  27.                 RA_RESYNC lets the target trigger the netrom initialize
  28.                     the dualport.
  29.    4/7/94 fdv 1. fixed ra_reset and ra_resync. 2. modified read addr reads
  30.               to "read away" cause of problem seen with ev960ca demo board.
  31.  
  32.    5/4/94 fdv added MISC out of band character to readaddr:
  33. subfunction is receive interrupt ack.
  34.    5/27/94 fdv added MISC out of band character to readaddr:
  35. subfunction is turn off emulate before ra_setmem.
  36.    6/16/94 fdv fix to emoffonwrite, it was being called on every set_mem
  37.    2/23/95 sch Add virtual ethernet, both ReadAddr and ReadWrite
  38.    8/21/95 sch Add read after write check to dp_readint().  This
  39.                fixes a data corruption problem when sending large
  40.                amounts of data to the host with little traffic from
  41.                the host.
  42.    sch Cleanup: Change xchannels back to channels, delete unused
  43.                OVERFLOW_MSGS code.
  44.    sch Add protocol to end of ra_resync().  Wait for NetROM to
  45.        turn off RI and then turn it back on before exiting, so
  46.        the target will not try to send or receive until NetROM
  47.        is done with the resync.
  48.    sch More cleanup.  Fix declarations of several routines so 
  49.        they will agree with their usage.
  50.    sch In config_dpram, avoid divides when setting oobthresh
  51.        for readaddr.
  52.    sch In dp_bread and dp_bwrite, call READ_POD and WRITE_POD
  53.        if HASCHACHE is true.  These routines will deal with
  54.        turning off the cache.
  55.     10/12/95 sch Clean up the ra_resync mod.  Take out delay at start.
  56.            Only wait for RI to go on before returning (NetROM will turn
  57.            it off before acking the last RE_RESYNC char).
  58. */
  59. /**********************************************************************
  60.     Porting notes:
  61.                                 OVERVIEW
  62.         This file contains routines which are meant to be used by target
  63.     systems when communicating with the NetROM emulator through Pod 0's
  64.     dualport ram.  These routines are byte-oriented for both transmit and
  65.     receive; however, multibytes messages are passed between target and
  66.     NetROM whenever possible, to reduce handshaking overhead.  Data is
  67.     collected at the target/NetROM interface a byte at a time and passed
  68.     over in messages.
  69.         Messages are fixed-size, fixed format data structures, whose format
  70.     is as follows:
  71.                 -----------------------------------------
  72.                 | Flags | Size |         Data           |
  73.                 -----------------------------------------
  74.                     ^      ^               ^
  75.                     |      |               |
  76.                   2 bytes  |               |
  77.                         2 bytes            |
  78.                                        60 bytes
  79.     Flag values are:
  80.         0x8000          Message ready bit
  81.         0x0001          Start of message bit (for multiple structure messages)
  82.         0x0002          End of message bit (for multiple structure messages)
  83.         0x0004          Message structure Wrap bit
  84.     The Start and End bits are both set in single structure messages.
  85.     The Wrap bit is used to mark the end of an array of structures (for
  86.     example, the transmit array).
  87.     The size field of the structure indicates how many of the data bytes
  88.     are valid.  The size does not include the Flags or the Size field.
  89.     The message structure is described in more detail in the include file,
  90.     dualport.h.
  91.         The protocol between target and NetROM has two distinct flavors;
  92.     one for targets which are capable of writing dualport ram and one for
  93.     targets which can only read dualport ram.  In general, the target will
  94.     poll dualport ram for messages; messages will be ready to process when the
  95.     Ready bit is set.  The scenarios for transmitting data to NetROM are
  96.     different for targets which have write capability and those which do
  97.     not; they are described below.  A key feature of the transmit path
  98.     from target to NetROM is the target's ability to cause an interrupt
  99.     to the NetROM by *reading* special areas of dualport ram.  When NetROM
  100.     receives the interrupt, it uses the target's read address to extract
  101.     an eight-bit value.  The value is equal to the offset of the target's
  102.     read address from the start of the interrupt-causing area of dualport
  103.     ram.
  104.         *** Note *** an important issue in communicating with the NetROM is
  105.     avoiding collisions when accessing dualport ram.  In situations where
  106.     the target and NetROM both access the same dualport address, the target
  107.     will lose.  That is, it will read garbage, or its writes may fail.  This
  108.     is an unavoidable issue, caused by the asynchronous nature of target
  109.     accesses to emulation pod memory, including dualport ram.
  110.         Avoiding access collisions when the target sends data to NetROM is
  111.     accomplished by the NetROM not polling for messages written by the
  112.     target.  Rather, when the target is done writing a message, it sends an
  113.     interrupt to the NetROM by reading a special address in dualport ram.
  114.     Only when the NetROM receives the interrupt will it check dualport ram for
  115.     messages from the target.  If the target cannot write dualport ram,
  116.     all data is passed by read-address interrupts, so access collisions are
  117.     not a problem.
  118.         Access collisions when the NetROM writes messages are unavoidable
  119.     because the target must poll dualport ram for messages.  However, the
  120.     NetROM will only write each byte of ram one time, so the target can
  121.     verify the Ready bit being set in a message, simply by reading the flags
  122.     field twice.  Since NetROM will only set the Ready bit after it has
  123.     written the message data, the target only needs to perform a "verification"
  124.     on the flags fields of message structures.
  125.                             READ-WRITE TARGETS
  126.         Targets which can write dualport ram will use a dualport memory layout
  127.     consisting of an array of 64-byte structures.  There will be 15 receive
  128.     structures and 16 transmit data structures.  Receive structures will
  129.     contain messages written by NetROM and transmit structure will be
  130.     used to send data to NetROM.  The configuration/status structure is
  131.     used to indicate whether or not NetROM is ready to process messages,
  132.     and reading parts of the configuration/status structure will send
  133.     interrupts to NetROM.
  134.                 --------------------------------------------
  135.                 |       Configuration/Status Structure (*) |
  136.                 --------------------------------------------
  137.                 |       RX Message Structure 0             |
  138.                 --------------------------------------------
  139.                 |               ...                        |
  140.                 --------------------------------------------
  141.                 |       RX Message Structure 14            |
  142.                 --------------------------------------------
  143.                 |       TX Message Structure 0             |
  144.                 --------------------------------------------
  145.                 |               ...                        |
  146.                 --------------------------------------------
  147.                 |       TX Message Structure 15            |
  148.                 --------------------------------------------
  149.         The configuration/status structure for targets with write
  150.     capability is simple:
  151.                 --------------------------------------------
  152.                 | Interrupt Area | TX | RX |   Reserved    |
  153.                 --------------------------------------------
  154.                         ^           ^    ^          ^
  155.                         |           |    |          |
  156.                      8 bytes        |    |          |
  157.                                   1 byte |          |
  158.                                        1 byte       |
  159.                                                 54 bytes
  160.     The target may read from the interrupt area to generate an interrupt
  161.     to the NetROM.  Upon receipt of this interrupt, the NetROM will check
  162.     the dualport message area for messages from the target.  The TX and
  163.     RX bytes are used to indicate when the NetROM is ready to process
  164.     messages and interrupts.  *** The target should not cause interrupts
  165.     unless these bytes are set, because NetROM will not detect a missed
  166.     interrupt. ***
  167.                             READ-ONLY TARGETS
  168. Targets which can read but not write dualport ram must use a
  169.     different mechanism to send data to the NetROM.  NetROM
  170.     contains a special area of memory in Pod 0 which, when read by the
  171.     target, causes an interrupt to be generated to NetROM's processor.
  172.     NetROM can determine which address within the 256-byte area was
  173.     read, and uses this address to calculate an 8-bit number.  Using
  174.     this mechanism, it is possible for the target to send 8-bit data to
  175.     the NetROM.  Sending certain 8-bit values is done in two steps.
  176.     This is because there are situations in which it is necessary to
  177.     send out-of-band data to the NetROM; that is, data which is
  178.     relevant to the protocol but not the the content of messages the
  179.     target wants to send.  For example, when the target reads a message
  180.     structure written by the NetROM, it cannot clear the Ready bit in
  181.     the message's flags.  Thus, it uses a special value (that is,
  182.     address) to acknowlege messages received from the NetROM.
  183.     Distinguishing between ACKs (0xF8) and equivalent values in message
  184.     data would require a character-stuffing protocol, which is not
  185.     currently supported.  Thus data values greater than 0xF8 are sent
  186.     in two or more pieces. The first, an "escape" character (0xF9),
  187.     tells NetROM to add 0xF8 to the next character received. The second
  188.     piece is the original value minus 0xF8.  This "character stuffing"
  189.     only needs to be done for values greater than 0xF8.
  190. The SET character (0xF2) is used when the target system wishes to 
  191.     request that NetROM modify the contents of emulation memory.  After
  192.     receiving the SET character, NetROM will interpret the next four
  193.     characters as an offset into emulation memory, received most-significant
  194.     byte first.  Following the offset is an 8-bit value to be written.  Note
  195.     that the target software should run from RAM from the time it transmits
  196.     the value character to the time that NetROM acknowleges the value
  197.     character.  This is to prevent memory contention problems.  The set
  198.     function is implemented by ra_setmem() in this file.
  199. The START and END characters are used to delineate a complete message
  200.     being sent via the read-address protocol.  They are analogous to the START
  201.     and END bits in a dualport message structure.  These out-of-band
  202.     characters are useful when using a UDP transport between NetROM and the
  203.     host system, since each UDP datagram will contain a complete message.
  204.     Sending messages is implmented in the ra_putmsg() routine in this file.
  205.         There is an added subtlety in the read-address protocol, which is
  206.     that NetROM is unable to detect missed interrupts.  As a result, prior
  207.     to sending each character, the target must be sure that NetROM is
  208.     listening for interrupts, and that the character that was sent was
  209.     received.  There are two fields in the configuration/status structure
  210.     which accomplish this; one which is set when the NetROM is listening
  211.     for interrupts, and one which is incremented for each character
  212.     (including control characters) that the target sends.  These are described
  213.     below.  Note that the values of all escape characters are different for 
  214.     target systems which perform burst reads from emulation pod 0.  Consult
  215.     your netrom manual for information on these types of systems.
  216.         The target receives messages from the NetROM using a similar
  217.     protocol to that used by the read-write target.  However, it must
  218.     acknowlege each message with a special character, since it cannot
  219.     clear Ready bits itself.
  220.     /--------  256-byte read-address area; target reads of this area
  221.     |       generate interrupts to the NetROM.
  222.     |
  223.     |   /--     --------------------------------------------
  224.     |   |       |                                          |
  225.     |   |       --     248-byte ASCII Read-address Data   --
  226.     --->|       |                                          |
  227.         |       --------------------------------------------
  228.         |       |    Control Read-address Data (8 bytes)  |
  229.         --     --------------------------------------------
  230.                 |       Configuration/Status Structure     |
  231.                 --------------------------------------------
  232.                 |       RX Message Structure 0             |
  233.                 --------------------------------------------
  234.                 |               ...                        |
  235.                 --------------------------------------------
  236.                 |       RX Message Structure 26            |
  237.                 --------------------------------------------
  238.      The layout of the control read-address data area.
  239.      --------------------------------------------------------------
  240.      | PACK | ESC | SET | START | END | RESET | RESYNC | MISC |
  241.      --------------------------------------------------------------
  242.         ^      ^     ^      ^      ^      ^        ^       ^
  243.         |      |     |      |      |      |        |       |
  244.      1 byte    |     |      |      |      |        |       |
  245.             1 byte   |      |      |      |        |       | 
  246.           1 byte    |      |      |        |       |
  247.          1 byte    |      |        |       |
  248.         1 byte    |        |       |
  249.        1 byte      |       |
  250. 1 byte     |
  251.                                                          1 byte
  252.     The PACK byte is used to tell NetROM that a single message has been
  253.     received from dualport RAM.  This byte should be read after *every*
  254.     dualport message.  The ESC byte is used to tell NetROM that the data
  255.     being transmitted is greater or equal in value than 248 (0xF8).  When
  256.     NetROM receives an ESC character, it will add 0xF8 to the character
  257.     which follows, and pass the result to higher level protocols as if it
  258.     were received in a single transmission. RESET lets the target trigger 
  259.     a tgtreset. RESYNC lets the target trigger the netrom initialize the 
  260.     dualport. MISC allows more control by parsing the next char for a
  261.     subfunction. The subfuntions are:
  262. 0x1  Receive Interrupt Acknowledge.
  263. 0x2  turn off emulate mode before performing ra_setmem.
  264.         The layout of the configuration/status structures.
  265.                 --------------------------------------------
  266.                 | RI | ACK |           Reserved            |
  267.                 --------------------------------------------
  268.                    ^    ^                  ^
  269.                    |    |                  |
  270.                 1 byte  |                  |
  271.                      1 byte                |
  272.                                        62 bytes
  273.     The RI bit indicates that NetROM is ready to handle interrupts.
  274.     The ACK byte is an 8-bit counter, which is incremented for each character
  275.     which the NetROM receives, including control characters such as
  276.     acks.
  277.                                 ABOUT THIS FILE
  278.         This file contains routines which communicate with the NetROM.  To
  279.     be able to send and receive characters, target-side programmers need
  280.     only port the clearly marked section at the top of the file.  A hook
  281.     is provided for tasking systems which need to allow processes to run;
  282.     this is the YIELD_CPU macro.  The routine c_dpcons_hdlr() handles
  283.     receipt of messages from the NetROM.  Since the NetROM cannot cause
  284.     target-side interrupts, it is called when the target checks for data.
  285.         The entry points that the target programmer needs to use are:
  286.             config_dpram        initializes control structures and configures
  287.                         the target to use dualport in a read-only or read-
  288.                         write fashion.
  289.             set_dp_blockio      allows the target programmer to set or
  290.                         clear a bit in the control structure.  When set,
  291.                         the interface routines merely poll for data and
  292.                         return if none is present.  Otherwise they will
  293.                         wait for data to appear.
  294.             dp_chanready        returns 1 if the NetROM is ready to
  295.                         process messages; 0 otherwise.
  296.     chan_kbhit returns 1 if a character is waiting at the 
  297. dualport interface; 0 otherwise.
  298.             ra_putch            sends a character to the NetROM using the
  299.                         read-address interface.  This routine handles all
  300.                         of the appropriate software handshaking.
  301.             chan_putch          sends a character to the NetROM.  Actually,
  302.                         it stores characters until the message structure is
  303.                         full or chan_flushtx() is called.  This reduces
  304.                         protocol overhead.
  305.             chan_flushtx        sends any characters which have been stored
  306.                         but not yet passed to the NetROM.
  307.             ra_getch            reads a character from the NetROM, if one
  308.                         is present, using the RX message structures of the 
  309. read-address protocol.
  310.             chan_getch          reads a character from the NetROM, if one
  311.                         is present, using the RX message structures of the
  312. readwrite protocol.
  313.     ra_getmsg reads a message from dualport ram, when using
  314. the read-address protocol.
  315.     chan_getmsg reads a message from dualport ram, when using
  316. the readwrite protocol.
  317.     ra_putmsg sends a complete message delineated by the 
  318. START and END out-of-band characters.
  319.     chan_putmsg sends a complete message delineated by the
  320.      START and END bits in the dualport message structures.
  321. This differs from the ra_putch() routine, which treats
  322. each dualport message structure as a complete
  323. message.
  324.     ra_setmem requests that NetROM write a byte of 
  325. emulation memory.
  326. if ra_emoffonwrite has been called, emulation memory is
  327. turned off before the byte is written.
  328.     ra_reset requests that NetROM reset the target.
  329.             ra_resync requests that NetROM re-initialize  it's 
  330. dualport parameters.
  331.     ra_rx_intr_ack acknowledges a receive interrupt
  332.     ra_emoffonwrite see ra_setmem
  333. Note that the getmsg() routines are used to incrementally fill an
  334.     input buffer.  When used in a polling mode, they return one of four 
  335.     status values:  GM_NODATA indicates that no data has arrived since the
  336.     last poll; GM_MSGCOMPLETE indicates that new data has arrived and that the
  337.     input buffer now holds the complete message; GM_NOTDONE indicates that
  338.     data has arrived but that the message is not yet complete; GM_MSGOVERFLOW
  339.     indicates that more data has arrived, but that it has overflown the input
  340.     buffer.  In a non-polling mode, these routines will return either
  341.     GM_MSGCOMPLETE or GM_MSGOVERFLOW.
  342. *********************************************************************/
  343. /* Local Defines */
  344. #define DUMMY_READ
  345. #include "wdb/dpconfig.h"     /* This file must be ported to the new target */
  346. #include "wdb/dptarget.h"      
  347. #include "wdb/dualport.h"
  348. #include "stdio.h"
  349. /* declarations */
  350. STATIC void c_dpcons_hdlr();
  351. void chan_flushtx();
  352. void set_dp_blockio();
  353. void ra_putch();
  354. int do_emoffonwrite();
  355. /* global data */
  356. STATIC DpChannel channels[DP_MAXCHANNELS];
  357. #ifdef READONLY_TARGET
  358. STATIC int emoffonwrite_set;
  359. #endif
  360. #ifndef RAWRITES_ONLY
  361. STATIC uInt16 dp_readint();
  362. void dp_bwrite();
  363. void dp_bread();
  364. #ifndef READONLY_TARGET
  365. /* writes an int to dp ram */
  366. STATIC void
  367. dp_writeint(addr,val)
  368. uInt32 addr;
  369. uInt16 val;
  370. {
  371.     /* write in network byte order, lsb first */
  372.     WRITE_POD(&channels[0], addr + 1, (uInt32)val & 0xFF);
  373.     WRITE_POD(&channels[0], addr, (uInt32)(val >> 8) & 0xFF);
  374.     /* Check that the write was sucessful.  See change log dated 8/21/95
  375.        at the top of this file for details. */
  376.     while (val != dp_readint(addr)) {
  377.         WRITE_POD(&channels[0], addr + 1, (uInt32)val & 0xFF);
  378.         WRITE_POD(&channels[0], addr, (uInt32)(val >> 8) & 0xFF);
  379.     }
  380. }
  381. #endif
  382. /* read an int from dpram */
  383. STATIC uInt16
  384. dp_readint(addr)
  385. uInt32 addr;
  386. {
  387.     uInt16 val;
  388.     /* read the msb first, in case it contains flags */
  389.     val = READ_POD(&channels[0], addr);
  390.     val <<= 8;
  391.     val += READ_POD(&channels[0], addr + 1);
  392.     /* return, in host byte order */
  393.     return(val);
  394. }
  395. /* copy bytes to dual-port memory (optimized version - move stuff
  396.    out of the loop )*/
  397. void
  398. dp_bwrite(src, addr, size)
  399. uChar *src;
  400. uInt32 addr;
  401. int size;
  402. {
  403.     register int inc;
  404.     register volatile uChar *dst;
  405.     register int i;
  406.     DpChannel *cp = &channels[0];
  407.     inc = cp->width;
  408.     dst = (volatile uChar *)(cp->dpbase + (cp->width * addr) + cp->index);
  409.     for(i = 0; i < size; i++) {
  410. #if (HASCACHE == True)
  411.     WRITE_POD(cp, addr++, *src);
  412. #else
  413.         *dst = *src;
  414.         dst += inc;
  415. #endif
  416.         src++;
  417.     }
  418. }
  419. /* copy bytes from dual-port memory (optimized version - move stuff
  420.    out of the loop) */
  421. void
  422. dp_bread(addr, buf,  size)
  423. uInt32 addr;
  424. volatile uChar *buf;
  425. int size;
  426. {
  427.     register int inc;
  428.     register volatile uChar *src;
  429.     register int i;
  430.     DpChannel *cp = &channels[0];
  431.     inc = cp->width;
  432.     src = (volatile uChar *)(cp->dpbase + (cp->width * addr) + cp->index);
  433.     for(i = 0; i < size; i++) {
  434. #if (HASCACHE == True)
  435. uChar tmp = READ_POD(cp, addr++);
  436.         *buf = tmp;
  437. #else
  438.         *buf = *src;
  439.         src += inc;
  440. #endif
  441.         buf ++;
  442.     }
  443. }
  444. #endif /* RAWRITES_ONLY */
  445. #ifdef READONLY_TARGET
  446. #ifndef RAWRITES_ONLY
  447. #ifdef USE_MSGS
  448. /* this routine reads message from dualport ram.  It returns different
  449.  * statuses, depending on whether or not message data is present, the message
  450.  * is complete, the message is not complete but data was present, or
  451.  * the message overflows the buffer.  The number of bytes read into the 
  452.  * message buffer is changed by side effect. 
  453.  * 
  454.  * This routine doesn't use the buffer pointers in the channel structure. 
  455.  * Note that GM_NODATA will only be returned if we are not in a blocking I/O
  456.  * mode. */
  457. int
  458. ra_getmsg(buf, len, bytesread)
  459. uChar *buf;
  460. int len, *bytesread;
  461. {
  462.     int done = 0;
  463.     int nbytes = 0;
  464.     register DpChannel *cp = &channels[0];
  465.     register uInt16 flags, size;
  466.     register uInt16 msg_size;
  467.     volatile uChar dummy;
  468.     /* look for the whole message */
  469.     while(done == 0) {
  470. /* check whether a buffer has become valid */
  471. while(cp->rx == (-1)) {
  472.     /* poll for new buffers */
  473.     c_dpcons_hdlr(0, RA_MSGBASE);
  474.     /* did we get a message? */
  475.     if(cp->rx == (-1)) {
  476. #ifdef VETHER
  477. if((cp->chanflags & CF_NOWAITIO) || (nbytes == 0)) {
  478. #else
  479. if(cp->chanflags & CF_NOWAITIO) {
  480. #endif
  481.     *bytesread = nbytes;
  482.     return(nbytes == 0 ? GM_NODATA : GM_NOTDONE);
  483. }
  484. YIELD_CPU();
  485.     }
  486. }
  487. /* synchronize ACK values */
  488. cp->rxackval = READ_POD(cp, RA_ACK);
  489. /* get the status and length of the message */
  490. flags = dp_readint(cp->rx + DPM_FLAGS);
  491. size = dp_readint(cp->rx + DPM_SIZE);
  492. /* Msg length may be in top 10 bits of size field of 1st msg */
  493. #ifdef VETHER
  494. if (nbytes == 0) {
  495.     msg_size = (size >> 6) | (flags & DPMSG_1K_BIT);
  496.         }
  497. #endif
  498. size = size & 0x3f;
  499. /* copy data into the buffer */
  500. if(size > len) {
  501.     *bytesread = nbytes;
  502.     /*printf("ra_getmsg: msglen=%d, buf=%d, read=%d ", size,len,nbytes);*/
  503.     return(GM_MSGOVERFLOW);
  504. }
  505. /* copy the message into the buffer */
  506. dp_bread(cp->rx + DPM_DATA, buf, (int) size);
  507. /* update our buffer pointers */
  508. buf += size;
  509. nbytes += size;
  510. len -= size;
  511. /* return the buffer */
  512. dummy = READ_POD(cp, READADDR_CTLCHAR(cp, RA_PACK_INDEX));
  513. /* wait for our packet ack to be acked in its turn; read the ack
  514.  * from NetROM twice to make sure it's valid */
  515. cp->rxackval++;
  516. while(READ_POD(cp, RA_ACK) != cp->rxackval && 
  517.       READ_POD(cp, RA_ACK) != cp->rxackval) {
  518. #ifdef DUMMY_READ
  519.     dummy = READ_POD(cp, RA_ACK+8 );
  520. #endif
  521.     ; /* do nothing */
  522. }
  523. /* advance the read pointer */
  524. if(flags & DPMSG_WRAP) {
  525.     cp->rx = cp->rxbase;
  526. } else {
  527.     cp->rx += DPM_MSGSIZE;
  528. }
  529. /* see if there are more messages waiting */
  530. if(cp->rx == cp->rxlim) {
  531.     cp->rx = (-1);
  532. }
  533. /* was this the end of the message? */
  534. if((flags & DPMSG_END) != 0) done = 1;
  535.     }
  536. #ifdef VETHER
  537.     /* Error check if msg len was in 1st buffer */
  538.     /* If we have a console for printf to use, do this check
  539.     if (msg_size) {
  540. if (msg_size != nbytes)
  541.     printf("ra_getmsg: 1st buf len=%d, actual=%dn",msg_size,nbytes);
  542.     } */
  543. #endif
  544.     *bytesread = nbytes;
  545.     return(GM_MSGCOMPLETE);
  546. }
  547. #endif /* USE_MSGS */
  548. int
  549. ra_getch()
  550. /* This routine attempts to read a character from the receive msg buffers of 
  551.  * the readaddress channel.  */
  552. {
  553.    DpChannel *cp = &channels[0];
  554.    BufIo *bp = &cp->rxbuf;
  555.    int ch;
  556.    volatile uChar dummy;
  557.     /* see if there is a character in this buffer */
  558.     if(bp->index < 0) {
  559.         /* wait for the buffer to become valid */
  560.         while(cp->rx == (-1)) {
  561.             /* poll for new buffers */
  562.             c_dpcons_hdlr(0, RA_MSGBASE);
  563.     /* did we get a message? */
  564.     if(cp->rx == (-1)) {
  565. if(cp->chanflags & CF_NOWAITIO) return(-1);
  566. YIELD_CPU();
  567.     }
  568.         }
  569. /* synchronize ACK values */
  570. cp->rxackval = READ_POD(cp, RA_ACK);
  571.         /* make sure that the message is ready by reading the flags byte 
  572.  * of the next receive msg. */
  573.         bp->flags = dp_readint(cp->rx + DPM_FLAGS);
  574. /* Re-read the flags because the NetROM may have been
  575.  * modifying them while we read them. */
  576.         if(bp->flags != dp_readint(cp->rx + DPM_FLAGS)) {
  577.             /* read failed on the verify, NetROM must be writing */
  578.             bp->flags = dp_readint(cp->rx + DPM_FLAGS);
  579.         }
  580.         if((bp->flags & DPMSG_READY) == 0) {
  581.             return(-1);
  582.         }
  583.         /* set up the i/o buffer for the message */
  584.         bp->bufsize = dp_readint(cp->rx + DPM_SIZE);
  585.         if(bp->bufsize > DP_DATA_SIZE) {
  586.             bp->bufsize = DP_DATA_SIZE;
  587.         }
  588.         dp_bread(cp->rx + DPM_DATA, bp->buf, (int) bp->bufsize);
  589.         bp->index = 0;
  590. /* return the buffer */
  591. dummy = READ_POD(cp, READADDR_CTLCHAR(cp, RA_PACK_INDEX));
  592. /* wait for our packet ack to be acked in its turn; read the ack
  593.  * from NetROM twice to make sure it's valid */
  594. cp->rxackval++;
  595. while(READ_POD(cp, RA_ACK) != cp->rxackval && 
  596. READ_POD(cp, RA_ACK) != cp->rxackval) {
  597. /* read different address to avoid contention on some targets*/
  598. #ifdef DUMMY_READ
  599.              dummy = READ_POD(cp, RA_ACK+8 );
  600. #endif
  601. }
  602.         /* advance the read pointer */
  603.         if(bp->flags & DPMSG_WRAP) {
  604.             cp->rx = cp->rxbase;
  605.         } else {
  606.             cp->rx += DPM_MSGSIZE;
  607.         }
  608.         /* see if there are more messages waiting */
  609.         if(cp->rx == cp->rxlim) {
  610.             cp->rx = (-1);
  611.         }
  612.     }
  613.     /* extract the character */
  614.     ch = (unsigned int) bp->buf[bp->index++];
  615.     /* check whether we finished the buffer */
  616.     if(bp->index == bp->bufsize) {
  617.         /* invalidate the buffer */
  618.         bp->index = (-1);
  619.     }
  620.     return(ch);
  621. }
  622. #endif /* ! RAWRITES_ONLY */
  623. static void
  624. ra_sendchar(ch)
  625. uChar ch;
  626. {
  627.     register DpChannel *cp = &channels[0];
  628.     register volatile uChar val, dummy;
  629.     register uChar expval;
  630.     /* reading a character sends an interrupt to NetROM */
  631.     dummy = READ_POD(cp, READADDR_DATACHAR(cp, ch));
  632.     /* wait for it to be acked */
  633.     expval = ++cp->rxackval;
  634.     while(1) {
  635.     val = READ_POD(cp, RA_ACK);
  636. #ifdef DUMMY_READ
  637.     dummy = READ_POD(cp, RA_ACK+8); 
  638. #endif
  639.     if(val == expval && val == READ_POD(cp, RA_ACK)) {
  640. /* got an ack for our last character */
  641. break;
  642.     }
  643.     }
  644. }
  645. void
  646. ra_putch(ch)
  647. uChar ch;
  648. /* 
  649. This routine sends a character to NetROM over the ReadAddress
  650. channel.
  651. */
  652. {
  653.     register volatile uChar val;
  654.     register DpChannel *cp = &channels[0];
  655.     /* wait for the NetROM to be ready */
  656.     while(1) {
  657.         val = READ_POD(cp, RA_RI);
  658.         if(val == 1 && val == READ_POD(cp, RA_RI)) {
  659.             /* NetROM is receiving */
  660.     cp->rxackval = READ_POD(cp, RA_ACK); /* AMP */
  661.             break;
  662.         }
  663.     }
  664.     /* make sure we can send the character */
  665.     while(ch >= cp->oobthresh) {
  666. /* send the escape character */
  667. ra_sendchar(cp->oobthresh + RA_ESC_INDEX);
  668. /* adjust the character we're sending */
  669. ch -= cp->oobthresh;
  670.     }
  671.     /* send the real character */
  672.     ra_sendchar(ch);
  673. }
  674. #ifndef RAWRITES_ONLY
  675. #ifdef USE_MSGS
  676. /* This routine sends a complete message to NetROM over the ReadAddress
  677.  * channel.  */
  678. void
  679. ra_putmsg(buf, len)
  680. uChar *buf;
  681. int len;
  682. {
  683.     register volatile uChar val;
  684.     register DpChannel *cp = &channels[0];
  685.     /* wait for the NetROM to be ready */
  686.     while(1) {
  687.         val = READ_POD(cp, RA_RI);
  688.         if(val == 1 && val == READ_POD(cp, RA_RI)) {
  689.             /* NetROM is receiving */
  690.     cp->rxackval = READ_POD(cp, RA_ACK); /* AMP */
  691.             break;
  692.         }
  693.     }
  694.     /* send the start message delimiter */
  695.     ra_sendchar(cp->oobthresh + RA_STARTMSG_INDEX);
  696.     /* send the message */
  697.     while(len != 0) {
  698. ra_putch(*buf);
  699. buf++;
  700. len--;
  701.     }
  702.     /* send the end message delimiter */
  703.     ra_sendchar(cp->oobthresh + RA_ENDMSG_INDEX);
  704. }
  705. #endif /* USE_MSGS */
  706. #endif /* ! RAWRITES_ONLY */
  707. /* this routine runs from ram to avoid conflicts with NetROM as it sets
  708.  * memory */
  709. void
  710. ra_setmem_sendval(ch)
  711. uChar ch;
  712. {
  713.     register volatile uChar dummy, expval, val;
  714.     register DpChannel *cp = &channels[0];
  715.     /* make sure we can send the character */
  716.     while(ch >= cp->oobthresh) {
  717. /* reading a character sends an interrupt to NetROM */
  718. dummy = READ_POD(cp, READADDR_CTLCHAR(cp, RA_ESC_INDEX));
  719. /* wait for it to be acked */
  720. expval = ++cp->rxackval;
  721. while(1) {
  722.     val = READ_POD(cp, RA_ACK);
  723.     if(val == expval && val == READ_POD(cp, RA_ACK)) {
  724. /* got an ack for our last character */
  725. break;
  726.     }
  727. }
  728. /* adjust the character we're sending */
  729. ch -= cp->oobthresh;
  730.     }
  731.     /* reading a character sends an interrupt to NetROM */
  732.     dummy = READ_POD(cp, READADDR_DATACHAR(cp, ch));
  733.     /* wait for it to be acked */
  734.     expval = ++cp->rxackval;
  735.     while(1) {
  736.         val = READ_POD(cp, RA_ACK);
  737.         if(val == expval && val == READ_POD(cp, RA_ACK)) {
  738.             /* got an ack for our last character */
  739.             break;
  740.         }
  741.     }
  742. }
  743. /* sends a request to NetROM to write a byte of memory */
  744. void
  745. ra_setmem(ch, addr, buf)
  746. uChar ch;
  747. uInt32 addr;
  748. uChar *buf; /* should be RA_SETMEM_RTN_SIZE bytes, 32 bit aligned */
  749. {
  750.     register volatile uChar dummy, expval, val;
  751.     register DpChannel *cp = &channels[0];
  752.     uChar *srcp;
  753.     int tmp;
  754.     void (*sendvalp)();
  755.     if(emoffonwrite_set == 1) { 
  756. do_emoffonwrite(); 
  757. emoffonwrite_set = 0;
  758.     }
  759.     /* wait for the NetROM to be ready */
  760.     while(1) {
  761.         val = READ_POD(cp, RA_RI);
  762.         if(val == 1 && val == READ_POD(cp, RA_RI)) {
  763.             /* NetROM is receiving */
  764.     cp->rxackval = READ_POD(cp, RA_ACK); /* AMP */
  765.             break;
  766.         }
  767.     }
  768.     /* send the set memory character */
  769.     dummy = READ_POD(cp, READADDR_CTLCHAR(cp, RA_SET_INDEX));
  770.     /* wait for it to be acked */
  771.     expval = ++cp->rxackval;
  772.     while(1) {
  773.         val = READ_POD(cp, RA_ACK);
  774.         if(val == expval && val == READ_POD(cp, RA_ACK)) {
  775.             /* got an ack for our last character */
  776.             break;
  777.         }
  778.     }
  779.     /* send the offset */
  780.     ra_putch((uChar) ((addr >> 24) & 0xFF));
  781.     ra_putch((uChar) ((addr >> 16) & 0xFF));
  782.     ra_putch((uChar) ((addr >> 8) & 0xFF));
  783.     ra_putch((uChar) (addr & 0xFF));
  784.     /* copy our sendval routine to ram */
  785.     tmp = (uInt32) buf & 0x03; /* force 32-bit alignment */
  786.     if(tmp != 0)  buf += (4 - tmp);
  787.     srcp = (uChar *) ra_setmem_sendval;
  788.     sendvalp = (void (*)()) buf;
  789.     for(tmp = 0; tmp < RA_SETMEM_RTN_SIZE; tmp++) {
  790. *buf = *srcp;
  791. buf++;
  792. srcp++;
  793.     }
  794.     /* call the sendval routine */
  795.     (*sendvalp)(ch);
  796. }
  797. /* sends a request to NetROM to reset the target
  798.       returns 0 if NetROM not ready
  799. */
  800. int
  801. ra_reset()
  802. {
  803.     register volatile uChar dummy, expval, val;
  804.     register DpChannel *cp = &channels[0];
  805.     /* check for the NetROM to be ready for interrupts */
  806.         val = READ_POD(cp, RA_RI);
  807.         if(val == !1 || val != READ_POD(cp, RA_RI)) {
  808.             /* NetROM is not receiving */
  809. return(0);
  810. }
  811. cp->rxackval = READ_POD(cp, RA_ACK);        /* AMP */
  812.     /* send  the 1st sequence character */
  813.     dummy = READ_POD(cp, READADDR_CTLCHAR(cp, RA_RESET));
  814.     /* wait for it to be acked */
  815.     expval = ++cp->rxackval;
  816.     while(1) {
  817.         val = READ_POD(cp, RA_ACK);
  818.         if(val == expval && val == READ_POD(cp, RA_ACK)) {
  819.             /* got an ack for our last character */
  820.             break;
  821.         }
  822.     }
  823.     /* send the 2nd sequence char  */
  824.     ra_putch((uChar) (0x01));
  825.     /* send  the 3rd sequence character */
  826.     dummy = READ_POD(cp, READADDR_CTLCHAR(cp, RA_RESET));
  827.     /* wait for it to be acked */
  828.     expval = ++cp->rxackval;
  829.     while(1) {
  830.         val = READ_POD(cp, RA_ACK);
  831.         if(val == expval && val == READ_POD(cp, RA_ACK)) {
  832.             /* got an ack for our last character */
  833.             break;
  834.         }
  835.     }
  836.     /* send the 4th sequence char  */
  837.     dummy = READ_POD(cp, READADDR_CTLCHAR(cp, RA_RESET));
  838.     ra_putch((uChar) (0x02));
  839.     /* send  the last sequence character */
  840.     dummy = READ_POD(cp, READADDR_CTLCHAR(cp, RA_RESET));
  841.     /*  don't wait for it to be acked */
  842.     return(1);
  843. }
  844. /* sends a request to NetROM to re-initalize (resync) the dualport parameters
  845.       returns 0 if NetROM not ready, returns 1 when done
  846.  */
  847. int
  848. ra_resync()
  849. {
  850.     register volatile uChar dummy, expval, val;
  851.     register DpChannel *cp = &channels[0];
  852.     /* check for the NetROM to be ready for interrupts */
  853.         val = READ_POD(cp, RA_RI);
  854.         if(val == !1 || val != READ_POD(cp, RA_RI)) {
  855.             /* NetROM is not receiving */
  856. return(0);
  857. }
  858. cp->rxackval = READ_POD(cp, RA_ACK);        /* AMP */
  859.     /* send  the 1st sequence character */
  860.     dummy = READ_POD(cp, READADDR_CTLCHAR(cp, RA_RESYNC));
  861.     /* wait for it to be acked */
  862.     expval = ++cp->rxackval;
  863.     while(1) {
  864.         val = READ_POD(cp, RA_ACK);
  865. dummy = READ_POD(cp, RA_ACK+8); 
  866.         if(val == expval && val == READ_POD(cp, RA_ACK)) {
  867.             /* got an ack for our last character */
  868.             break;
  869.         }
  870.     }
  871.     /* send the 2nd sequence char  */
  872.     ra_putch((uChar) (0x01));
  873.     /* send  the 3rd sequence character */
  874.     dummy = READ_POD(cp, READADDR_CTLCHAR(cp, RA_RESYNC));
  875.     /* wait for it to be acked */
  876.     expval = ++cp->rxackval;
  877.     while(1) {
  878.         val = READ_POD(cp, RA_ACK);
  879. dummy = READ_POD(cp, RA_ACK+8);
  880.         if(val == expval && val == READ_POD(cp, RA_ACK)) {
  881.             /* got an ack for our last character */
  882.             break;
  883.         }
  884.     }
  885.     /* send the 4th sequence char  */
  886.     ra_putch((uChar) (0x02));
  887.     /* send  the last sequence character */
  888.     dummy = READ_POD(cp, READADDR_CTLCHAR(cp, RA_RESYNC));
  889.     /* wait for it to be acked */
  890.     expval = ++cp->rxackval;
  891.     while(1) {
  892.         val = READ_POD(cp, RA_ACK);
  893. dummy = READ_POD(cp, RA_ACK+8); 
  894.         if(val == expval && val == READ_POD(cp, RA_ACK)) {
  895.             /* got an ack for our last character */
  896.             break;
  897.         }
  898.     }
  899.     /* Wait for NetROM to turn RA_RI back on before completing,
  900.        so that we won't try anything else before NetROM has resynced. 
  901.        Requires NetROM firmware version 1.3.1 or later. */
  902.     while(1) {
  903.         val = READ_POD(cp, RA_RI);
  904.         if(val == 1 && val == READ_POD(cp, RA_RI)) {
  905.             break;
  906.         }
  907.     }
  908.     return(1);
  909. }
  910. /* acknowledges a receive interrupt 
  911.       returns 0 if NetROM not ready, returns 1 when done
  912.  */
  913. int
  914. ra_rx_intr_ack()
  915. {
  916.     register volatile uChar dummy, expval, val;
  917.     register DpChannel *cp = &channels[0];
  918.     /* check for the NetROM to be ready for interrupts */
  919.         val = READ_POD(cp, RA_RI);
  920.         if(val == !1 || val != READ_POD(cp, RA_RI)) {
  921.             /* NetROM is not receiving */
  922. return(0);
  923. }
  924. cp->rxackval = READ_POD(cp, RA_ACK);        /* AMP */
  925.     /* send  the 1st sequence character */
  926.     dummy = READ_POD(cp, READADDR_CTLCHAR(cp, RA_MISC));
  927.     /* wait for it to be acked */
  928.     expval = ++cp->rxackval;
  929.     while(1) {
  930.         val = READ_POD(cp, RA_ACK);
  931. #ifdef DUMMY_READ
  932. dummy = READ_POD(cp, RA_ACK +8);
  933. #endif
  934.         if(val == expval && val == READ_POD(cp, RA_ACK)) {
  935.             /* got an ack for our last character */
  936.             break;
  937.         }
  938.     }
  939.     /* send the 2nd sequence char  */
  940.     ra_putch((uChar) (RX_INTR_ACK));
  941.     return(1);
  942. }
  943. /* tells netrom to turn off emulation before writing to memory 
  944.       returns 0 if NetROM not ready, returns 1 when done
  945.  */
  946. void
  947. ra_emoffonwrite()
  948. {
  949. emoffonwrite_set=1; 
  950. /* set global so ra_setmem can first call do_emoffonwrite just in case 
  951.          debug connection was not connected at the time
  952. of this call */
  953. }
  954. int
  955. do_emoffonwrite()
  956. {
  957.     register volatile uChar dummy, expval, val;
  958.     register DpChannel *cp = &channels[0];
  959.     /* check for the NetROM to be ready for interrupts */
  960.         val = READ_POD(cp, RA_RI);
  961.         if(val == !1 || val != READ_POD(cp, RA_RI)) {
  962.             /* NetROM is not receiving */
  963. return(0);
  964. }
  965. cp->rxackval = READ_POD(cp, RA_ACK);        /* AMP */
  966.     /* send  the 1st sequence character */
  967.     dummy = READ_POD(cp, READADDR_CTLCHAR(cp, RA_MISC));
  968.     /* wait for it to be acked */
  969.     expval = ++cp->rxackval;
  970.     while(1) {
  971.         val = READ_POD(cp, RA_ACK);
  972. #ifdef DUMMY_READ
  973. dummy = READ_POD(cp, RA_ACK+8);
  974. #endif
  975.         if(val == expval && val == READ_POD(cp, RA_ACK)) {
  976.             /* got an ack for our last character */
  977.             break;
  978.         }
  979.     }
  980.     /* send the 2nd sequence char  */
  981.     ra_putch((uChar) (EMOFFONWRITE));
  982.     return(1);
  983. }
  984. #endif /* READONLY_TARGET */
  985. #ifdef READWRITE_TARGET
  986. #ifdef USE_MSGS
  987. /* this routine reads message from dualport ram.  It returns different
  988.  * statuses, depending on whether or not message data is present, the message
  989.  * is complete, the message is not complete but data was present, or
  990.  * the message overflows the buffer.  The number of bytes read into the 
  991.  * message buffer is changed by side effect. 
  992.  * 
  993.  * This routine doesn't use the buffer pointers in the channel structure. 
  994.  * Note that GM_NODATA will only be returned if we are not in a blocking I/O
  995.  * mode. */
  996. int
  997. chan_getmsg(chan, buf, len, bytesread)
  998. int chan;
  999. uChar *buf;
  1000. int len, *bytesread;
  1001. {
  1002.     register DpChannel *cp = &channels[0];
  1003.     int done = 0;
  1004.     int nbytes = 0;
  1005.     register uInt16 flags, size;
  1006.     int msg_len = 0;
  1007.     /* look for the whole message */
  1008.     while(done == 0) {
  1009.         /* wait for the buffer to become valid */
  1010.         while(cp->rx == (-1)) {
  1011.             /* poll for new buffers */
  1012.             c_dpcons_hdlr(chan, RW_MSGBASE);
  1013.     /* did we get a message? */
  1014.     if(cp->rx == (-1)) {
  1015. #ifdef VETHER
  1016. if((cp->chanflags & CF_NOWAITIO) || (nbytes == 0)) {
  1017. #else
  1018. if(cp->chanflags & CF_NOWAITIO) {
  1019. #endif
  1020.     *bytesread = nbytes;
  1021.     return(nbytes == 0 ? GM_NODATA : GM_NOTDONE);
  1022. }
  1023. YIELD_CPU();
  1024.     }
  1025.         }
  1026. /* read the status and size of the new message block */
  1027.         flags = dp_readint(cp->rx + DPM_FLAGS);
  1028.         size = dp_readint(cp->rx + DPM_SIZE);
  1029. #ifdef VETHER
  1030. /* get whole msg len from first pkt of msg */
  1031. if (nbytes == 0) {
  1032.     /* if ((flags & DPMSG_START) == 0)
  1033.  printf("no START: %04x ", flags & 0xffff); */
  1034.     msg_len = (size >> 6) | (flags & DPMSG_1K_BIT);
  1035.     size = size & 0x3f;
  1036. }
  1037. #endif
  1038. /* copy data into the buffer */
  1039. if(size > len) {
  1040.     *bytesread = nbytes;
  1041.     return(GM_MSGOVERFLOW);
  1042. }
  1043.         dp_bread(cp->rx + DPM_DATA, buf, (int) size);
  1044.         /* return the buffer */
  1045.         dp_writeint(cp->rx + DPM_FLAGS, flags & ~DPMSG_READY);
  1046. /* update our buffer pointers */
  1047. buf += size;
  1048. nbytes += size;
  1049. len -= size;
  1050.         /* advance the read pointer */
  1051.         if(flags & DPMSG_WRAP) {
  1052.             cp->rx = cp->rxbase;
  1053.         } else {
  1054.             cp->rx += DPM_MSGSIZE;
  1055.         }
  1056.         /* see if there are more messages waiting */
  1057.         if(cp->rx == cp->rxlim) {
  1058.             cp->rx = (-1);
  1059.         }
  1060. /* was this the end of the message? */
  1061. if((flags & DPMSG_END) != 0) done = 1;
  1062.     }
  1063.     *bytesread = nbytes;
  1064. #ifdef VETHER
  1065.     if (nbytes != msg_len) {
  1066. /* printf("chan_getmsg: 1st pkt len=%d, got %dn", msg_len, nbytes); */
  1067. return(GM_NOTDONE);
  1068.     } else 
  1069. #endif
  1070.      return(GM_MSGCOMPLETE);
  1071. }
  1072. int
  1073. chan_getch(chan)
  1074. int chan;
  1075. /* This routine attempts to read a character from the receive msg buffers 
  1076.  * of the readwrite channel.  */
  1077. {
  1078.     DpChannel *cp = &channels[chan];
  1079.     BufIo *bp = &cp->rxbuf;
  1080.     int ch;
  1081.     /* see if there is a character in this buffer */
  1082.     if(bp->index < 0) {
  1083.         /* wait for the buffer to become valid */
  1084.         while(cp->rx == (-1)) {
  1085.             /* poll for new buffers */
  1086.             c_dpcons_hdlr(chan, RW_MSGBASE);
  1087.     /* did we get a message? */
  1088.     if(cp->rx == (-1)) {
  1089. if(cp->chanflags & CF_NOWAITIO) return(-1);
  1090. YIELD_CPU();
  1091.     }
  1092.         }
  1093.         /* make sure that the message is ready by reading the flags byte 
  1094.  * of the next receive msg.  */
  1095.         bp->flags = dp_readint(cp->rx + DPM_FLAGS);
  1096. /* Re-read the flags because the NetROM may have been modifying 
  1097.  * them while we read them. */
  1098.         if(bp->flags != dp_readint(cp->rx + DPM_FLAGS)) {
  1099.             /* read failed on the verify, NetROM must be writing */
  1100.             bp->flags = dp_readint(cp->rx + DPM_FLAGS);
  1101.         }
  1102.         if((bp->flags & DPMSG_READY) == 0) {
  1103.             return(-1);
  1104.         }
  1105.         /* set up the i/o buffer for the message */
  1106.         bp->bufsize = dp_readint(cp->rx + DPM_SIZE);
  1107.         if(bp->bufsize > DP_DATA_SIZE) {
  1108.             bp->bufsize = DP_DATA_SIZE;
  1109.         }
  1110.         dp_bread(cp->rx + DPM_DATA, bp->buf, (int) bp->bufsize);
  1111.         bp->index = 0;
  1112.         /* return the buffer */
  1113.         dp_writeint(cp->rx + DPM_FLAGS, (uInt16)bp->flags & ~DPMSG_READY);
  1114.         /* advance the read pointer */
  1115.         if(bp->flags & DPMSG_WRAP) {
  1116.             cp->rx = cp->rxbase;
  1117.         } else {
  1118.             cp->rx += DPM_MSGSIZE;
  1119.         }
  1120.         /* see if there are more messages waiting */
  1121.         if(cp->rx == cp->rxlim) {
  1122.             cp->rx = (-1);
  1123.         }
  1124.     }
  1125.     /* extract the character */
  1126.     ch = (unsigned int) bp->buf[bp->index++];
  1127.     /* check whether we finished the buffer */
  1128.     if(bp->index == bp->bufsize) {
  1129.         /* invalidate the buffer */
  1130.         bp->index = (-1);
  1131.     }
  1132.     return(ch);
  1133. }
  1134. /* send a message to netrom */
  1135. void
  1136. chan_putmsg(chan, buf, len)
  1137. int chan;
  1138. uChar *buf;
  1139. register int len;
  1140. {
  1141.     register DpChannel *cp = &channels[chan];
  1142.     register int num_sent = 0;
  1143.     int size, num_left = len, ovf_size;
  1144.     volatile uChar dummy;
  1145.     register uInt16 flags;
  1146.     while(num_sent < len) {
  1147.         /* wait for the buffer */
  1148.         while(1) {
  1149.             flags = dp_readint(cp->tx + DPM_FLAGS);
  1150.             if(flags != dp_readint(cp->tx + DPM_FLAGS)) {
  1151.                 /* read failed on the verify, NetROM must be writing */
  1152.                 continue;
  1153.             }
  1154.             if((flags & DPMSG_READY) == 0) 
  1155.                 break;
  1156. #ifdef DUMMY_READ
  1157.     dummy = READ_POD(cp, RA_ACK+8 );
  1158. #endif
  1159.             YIELD_CPU(); 
  1160.         }
  1161. /* get the number of bytes to send in DP struct and overflow */
  1162. if(num_left >= DP_DATA_SIZE) {
  1163.     size = DP_DATA_SIZE;
  1164.     if (num_left >= MAX_MSG_SIZE)
  1165.                 ovf_size = MAX_OVF_MSG_SIZE;
  1166.     else
  1167.                 ovf_size = num_left - DP_DATA_SIZE;
  1168. } else {
  1169.     size = num_left;
  1170.             ovf_size = 0;
  1171. }
  1172. /* fill the currently available DP buffer */
  1173. /* Put full msg size in upper bits of first size field */
  1174. if (num_sent == 0) { 
  1175.     dp_writeint(cp->tx + DPM_SIZE, (len << 6) | size);
  1176. } else
  1177.     dp_writeint(cp->tx + DPM_SIZE, size); 
  1178. dp_bwrite(buf, cp->tx + DPM_DATA, size);
  1179. /* get the flags to write */
  1180. flags = (flags & DPMSG_WRAP) | DPMSG_READY;
  1181. if(num_sent == 0) {
  1182.             flags |= DPMSG_START;
  1183.     /* or in 1K bit of msg len */
  1184.     flags =  flags | (len & DPMSG_1K_BIT); 
  1185. }
  1186. num_sent += size;
  1187. num_left -= size;
  1188. if(num_sent >= len) 
  1189.             flags |= DPMSG_END;
  1190. dp_writeint(cp->tx + DPM_FLAGS, flags);
  1191. dp_writeint(cp->tx + DPM_FLAGS, flags); /* try writing it twice */
  1192. /* notify NetROM that the buffer is ready */
  1193. dummy = READ_POD(cp, READADDR_CTLCHAR(cp , RW_MRI));
  1194. /* adjust pointers */
  1195. buf += size;
  1196. /* advance the msg pointer */
  1197. if(flags & DPMSG_WRAP) {
  1198.     cp->tx    = cp->txbase;
  1199.     cp->txovf = cp->txovfbase;
  1200. } else {
  1201.     cp->tx    += DPM_MSGSIZE;
  1202.     cp->txovf += MAX_OVF_MSG_SIZE;
  1203. }
  1204.     }
  1205. }
  1206. /* flush the current character-oriented tx channel */
  1207. void
  1208. chan_flushtx(chan)
  1209. int chan;
  1210. {
  1211.     DpChannel *cp = &channels[chan];
  1212.     BufIo *bp = &cp->txbuf;
  1213.     volatile uChar dummy;
  1214.     /* if we don't own the message or there's nothing in it, just return */
  1215.     bp->flags = dp_readint(cp->tx + DPM_FLAGS);
  1216.     if((bp->flags & DPMSG_READY) != 0 || bp->index == 0) {
  1217.         return;
  1218.     }
  1219.     /* send the buffer */
  1220.     dp_writeint(cp->tx + DPM_SIZE, (uInt16)bp->bufsize);
  1221.     dp_bwrite(bp->buf, cp->tx + DPM_DATA, (int) bp->bufsize);
  1222.     bp->flags &= DPMSG_WRAP;
  1223.     dp_writeint(cp->tx + DPM_FLAGS,
  1224.         (uInt16)bp->flags | (DPMSG_READY|DPMSG_START|DPMSG_END));
  1225.     /* notify NetROM that the buffer is ready */
  1226.     dummy = READ_POD(cp, READADDR_CTLCHAR(cp, RW_MRI));
  1227.     /* advance the msg pointer */
  1228.     if(bp->flags & DPMSG_WRAP) {
  1229.         cp->tx = cp->txbase;
  1230.     } else {
  1231.         cp->tx += DPM_MSGSIZE;
  1232.     }
  1233.     /* clear the buffer structure */
  1234.     bp->index = 0;
  1235.     bp->bufsize = 0;
  1236. }
  1237. int
  1238. chan_putch(chan, ch)
  1239. int chan;
  1240. uChar ch;
  1241. /*
  1242. Write a character into the transmit area of the readwrite
  1243. channel.
  1244. */
  1245. {
  1246.     DpChannel *cp = &channels[chan];
  1247.     BufIo *bp = &cp->txbuf;
  1248.     /* if the current tx channel is owned by the target, wait for it */
  1249.     bp->flags = dp_readint(cp->tx + DPM_FLAGS);
  1250.     if(bp->flags & DPMSG_READY) {
  1251.         /* wait for the buffer */
  1252.         while(1) {
  1253.             bp->flags = dp_readint(cp->tx + DPM_FLAGS);
  1254.             if(bp->flags != dp_readint(cp->tx + DPM_FLAGS)) {
  1255.                 /* read failed on the verify, NetROM must be writing */
  1256.                 continue;
  1257.             }
  1258.             if((bp->flags & DPMSG_READY) == 0) break;
  1259.             if(cp->chanflags & CF_NOWAITIO) return(-1);
  1260.             YIELD_CPU();
  1261.         }
  1262.         /* initialize the buffer structure */
  1263.         bp->index = 0;
  1264.         bp->bufsize = 0;
  1265.     }
  1266.     /* write the character into the buffer */
  1267.     bp->buf[bp->index++] = ch;
  1268.     bp->bufsize++;
  1269.     /* if the buffer is full, send it */
  1270.     if(bp->index == DP_DATA_SIZE) {
  1271.         chan_flushtx(chan);
  1272.     }
  1273.     return(1);
  1274. }
  1275. #endif /* USE_MSGS */
  1276. #endif /* READWRITE_TARGET */
  1277. #ifndef RAWRITES_ONLY
  1278. /* check if a character is waiting at the channel */
  1279. int
  1280. chan_kbhit(chan)
  1281. int chan;
  1282. {
  1283.     DpChannel *cp = &channels[chan];
  1284.     BufIo *bp = &cp->rxbuf;
  1285.     int retval;
  1286.     /* see if there is a character in this buffer */
  1287.     if(bp->index < 0) {
  1288.         /* poll for new buffers */
  1289. if(cp->chanflags & CF_TXVALID)
  1290.          c_dpcons_hdlr(chan,RW_MSGBASE);
  1291. else
  1292.          c_dpcons_hdlr(chan,RA_MSGBASE);
  1293.         /* no, check for a new buffer arriving */
  1294.         if(cp->rx != (-1)) {
  1295.             retval = 1;
  1296.         } else {
  1297.             retval = 0;
  1298.         }
  1299.     } else {
  1300.         retval = 1;
  1301.     }
  1302.     return(retval);
  1303. }
  1304. #endif /* ! RAWRITES_ONLY */
  1305. /* returns 1 if the "active" byte for a particular channel's transmit
  1306.  * and/or receive paths are set, returns 0 otherwise */
  1307. int
  1308. dp_chanready(chan)
  1309. int chan;
  1310. {
  1311.     DpChannel *cp = &channels[chan];
  1312.     uChar val;
  1313.     if(cp->chanflags & CF_TXVALID) {
  1314.         /* check that the rx channel is active */
  1315.         val = READ_POD(cp, RW_RX);
  1316.         if(val != READ_POD(cp, RW_RX)) {
  1317.             return(0);
  1318.         } else if(val != 1) {
  1319.             return(0);
  1320.         }
  1321.         /* check that the tx channel is active */
  1322.         val = READ_POD(cp, RW_TX);
  1323.         if(val != READ_POD(cp, RW_TX)){
  1324.             return(0);
  1325.         } else if(val != 1) {
  1326.             return(0);
  1327.         }
  1328.     } else {
  1329.         /* check that the NetROM is ready for interrupts */
  1330.         val = READ_POD(cp, RA_RI);
  1331.         if(val != 1 || val != READ_POD(cp, RA_RI)) {
  1332.             /* NetROM is not receiving */
  1333.             return(0);
  1334.         }
  1335.     }
  1336.     /* NetROM is ready */
  1337.     return(1);
  1338. }
  1339. #ifndef RAWRITES_ONLY
  1340. /* if the CF_NOWAITIO bit is set in a channel's flags, the channel's get
  1341.  * and put character methods, will return immediately if there are no
  1342.  * available message structures in dualport ram.  This routine sets or
  1343.  * clears that bit. */
  1344. void
  1345. set_dp_blockio(chan, val)
  1346. int chan, val;
  1347. {
  1348.     DpChannel *cp = &channels[chan];
  1349.     if(val == 0) {
  1350.         cp->chanflags |= CF_NOWAITIO;
  1351.     } else {
  1352.         cp->chanflags &= ~CF_NOWAITIO;
  1353.     }
  1354. }
  1355. /* This routine handles any messages received from NetROM. */
  1356. STATIC void 
  1357. c_dpcons_hdlr(chan,base)
  1358. int chan;
  1359. uInt32 base;
  1360. {
  1361.     register DpChannel *cp;
  1362.     register uInt16 flags;
  1363.     /* volatile uChar dummy; */
  1364.     /* get a pointer to the channel */
  1365.     cp = &channels[0];
  1366.     /* a received message indicator */
  1367.     while(cp->rx != cp->rxlim) {
  1368.         flags = dp_readint(cp->rxlim + DPM_FLAGS);
  1369.         if(flags != dp_readint(cp->rxlim + DPM_FLAGS)) {
  1370.                 /* NetROM must be writing, try again */
  1371.                 continue;
  1372.         }
  1373.         if(flags & DPMSG_READY) {
  1374.             /* a new message is ready */
  1375.             if(cp->rx == (-1)) {
  1376.                 /* record that the message is ready to be read */
  1377.                 cp->rx = cp->rxlim;
  1378.             }
  1379.             /* advance the read limit pointer */
  1380.             if(flags & DPMSG_WRAP) {
  1381.                 cp->rxlim = cp->rxbase;
  1382.             } else {
  1383.                 cp->rxlim += DPM_MSGSIZE;
  1384.             }
  1385.     /* process one message at a time if using readaddr protocol */
  1386.     if((cp->chanflags & CF_TXVALID) == 0) {
  1387. break;
  1388.     }
  1389.         } else {
  1390.             /* no more messages */
  1391.             break;
  1392.         }
  1393.     }
  1394. }
  1395. #endif /* ! RAWRITES_ONLY */
  1396. /* configure the dual-port ram to be used in a read-only or a read-write
  1397.  * fashion. */
  1398. int
  1399. config_dpram(base, width, index, flags, numaccesses)
  1400. uInt32 base;
  1401. int width, index, flags, numaccesses;
  1402. {
  1403.     DpChannel *cp = &channels[0];
  1404.     /* set the address of dualport ram in pod 0 */
  1405.     cp->dpbase = base;
  1406.     cp->width = width;
  1407.     cp->index = index;
  1408.     /* initialize the buffer system */
  1409.     cp->txbuf.bufsize = 0;
  1410.     cp->txbuf.index = 0;
  1411.     cp->rxbuf.bufsize = 0;
  1412.     cp->rxbuf.index = (-1);
  1413.     cp->numaccess = numaccesses;
  1414.     /* initialize the ack counter */
  1415.     cp->rxackval = 0;
  1416.     /* use the flags to set up */
  1417.     switch(flags) {
  1418. #ifdef READONLY_TARGET
  1419.     case DPF_READONLY_TGT:
  1420.         /* we can only read dualport */
  1421.         cp->chanflags = CF_RXVALID | CF_NOWAITIO;
  1422.         /* start the receive area after the read-address area, and the
  1423.          * status/control area */
  1424.         cp->rxbase = cp->rxlim = RA_MSGBASE;
  1425.         cp->rx = (-1);
  1426. /* to avoid runtime divides, make this a case stmt */
  1427. switch(cp->numaccess) {
  1428.   case 4:
  1429.     cp->oobthresh = (READADDR_SIZE / 4) - RA_MAX_INDEX;
  1430.     break;
  1431.   case 2:
  1432.     cp->oobthresh = (READADDR_SIZE / 2) - RA_MAX_INDEX;
  1433.     break;
  1434.   case 1:
  1435.   default:
  1436.     cp->oobthresh = (READADDR_SIZE / 1) - RA_MAX_INDEX;
  1437.     break;
  1438. }
  1439. /* Original code with the divide
  1440. cp->oobthresh = (READADDR_SIZE / cp->numaccess) - RA_MAX_INDEX; */
  1441.         /* all done */
  1442.         break;
  1443. #endif /* READONLY_TARGET */
  1444. #ifdef READWRITE_TARGET
  1445.     case DPF_ONECHANNEL:
  1446.         /* we can both read and write dualport */
  1447.         cp->chanflags = CF_TXVALID | CF_RXVALID | CF_NOWAITIO;
  1448.         /* start the receive area after the status/control area */
  1449.         cp->rxbase = cp->rxlim = RW_MSGBASE;
  1450.         cp->rx = (-1);
  1451.         /* start the transmit area after the receive area */
  1452.         cp->txbase = cp->tx = (RW_REC_MSGS + 1) * DPM_MSGSIZE;
  1453. cp->oobthresh = 0;
  1454.         /* all done */
  1455.         break;
  1456. #endif /* READWRITE_TARGET */
  1457.     
  1458.     default:
  1459.         return(-1);
  1460.         break;
  1461.     }
  1462.     return(0);
  1463. }