Legacy Documentclose button

Important: The information in this document is obsolete and should not be used for new development.

Previous Book Contents Book Index Next

Inside Macintosh: Networking /
Chapter 12 - Multinode Architecture / Using Multinode Architecture


Receiving Packets Addressed to Your Multinode

Your application must provide a routine that receives packets addressed to the multinode and broadcast packets. Because the .MPP driver passes values to your multinode receive routine in registers when it calls the routine, you must code the receive routine in assembly language.

You pass the address of your receive routine to the .MPP driver when you call the AddNode routine to open a multinode. The .MPP driver internally associates your receive routine with the multinode address that it assigns, and it calls your receive routine to handle a packet addressed to the multinode or a broadcast packet.

If your application acquires more than one multinode, you can use the same receive routine for each of these multinodes. If you use the same receive routine to receive and process packets for more than one multinode, the .MPP driver will call that receive routine only once for each broadcast packet that it receives.

A multinode receive routine is similar in concept to a socket listener that receives packets addressed to a specific socket. The chapter "Datagram Delivery Protocol (DDP)" in
this book includes a sample socket listener. To create a receive routine, perform the following steps:

  1. Allocate a buffer to hold the data that you expect to receive.

    • The maximum amount of data in a DDP packet is 586 bytes. All packets addressed to multinodes use a long header, which is 13 bytes long. If your receive routine places the packet header as well as the data portion in the buffer, make the buffer large enough to hold both parts of the packet contents.
    • If you use the same receive routine to receive and process packets for more than one multinode, you should provide a separate buffer to store the data for each multinode. You can define a single buffer for each multinode to hold the contents of both the header and data portions of a packet, or you can define a pair of buffers for each multinode to separate the packet's contents.

  2. Determine the number of bytes that have already been read into the .MPP driver's internal buffer, called the RHA.

    • To do this, subtract the beginning address of the read-header area (RHA) from the value in register A3, which points past the last byte read into the RHA. To locate the offset at the beginning of the RHA, you can use the toRHA equate.

      When a frame that contains either a DDP packet that is addressed to your multinode or a broadcast packet is delivered to the node that is running your multinode applica-
      tion, the node's CPU is interrupted and the .MPP driver's interrupt handler gets control to service the interrupt. As the frame's first 3 bytes are read into a FIFO buffer, the .MPP driver's interrupt handler moves these bytes into the RHA.

  3. Use the ReadPacket and ReadRest routines to read the rest of the incoming data that constitutes the packet.

    How you handle a packet after you read it is particular to your application. For example, if your application implements NBP, you can check the packet's entity name object and type fields against entries in your names table to determine whether to process the packet and respond to the sender. If you respond, the packet you send must adhere to the structure of a standard AppleTalk packet. (See Inside AppleTalk, second edition, for the AppleTalk packet structure.) For a brief description of how ARA uses multinode, see the discussion on page 12-5.

    • You can call the ReadPacket routine as many times as you like to read the data piece by piece into one or more data buffers that you have defined, but you must always use the ReadRest routine to read the final piece of the data packet. The ReadRest routine restores the machine state (the stack pointers, status register, and so forth) and checks for error conditions.
    • Before you call the ReadPacket routine, you must place a pointer to the data buffer for which you allocated memory in the A3 register. You must also place the number of bytes you want to read in the D3 register. You must not request more bytes than remain in the data packet.
    • After you have called the ReadRest routine, you can use registers A0 through A3 and D0 through D3 for your own use, but you must preserve all other registers. You cannot depend on having access to your application's global variables.

Calling ReadPacket and ReadRest when LocalTalk is the data link
If LocalTalk is the data link that is being used, your receive routine
has less than 95 microseconds (best case) to read more data with a ReadPacket or ReadRest routine. If you need more time, you
can read another 3 bytes into the RHA, which will allow you an
additional 95 microseconds. Note that the RHA may only have 8 bytes still available.
  1. If the packet header contains a checksum, you can calculate a checksum for both the header and data portions of the packet and then verify the sum of these two values against the value in the checksum field of the packet header. If the checksum you calculate does not match the one in the header, the data has been corrupted in
    some way. (Figure 12-1 on page 12-5 shows the DDP packet header, including the checksum field.)

    The chapter "Datagram Delivery Protocol (DDP)" in this book contains a sample checksum routine to be used for a socket listener; this routine is equally applicable to a multinode receive routine.

Calling ReadPacket to Read in the Packet Contents

To call the ReadPacket routine, execute a JSR instruction to the address in the A4 register. The ReadPacket routine uses the registers as follows:
Registers on entry to the ReadPacket routine
A3Pointer to a buffer to hold the data you want to read
D3Size in of bytes to be read; must be nonzero
Registers on exit from the ReadPacket routine
A0Unchanged
A1Unchanged
A2Unchanged
A3Pointer to the first byte after the last byte read into buffer
A4Unchanged
D0Changed
D1Number of bytes left to be read
D2Unchanged
D3Equals 0 if the requested number of bytes were read, nonzero if error

After every time that you call ReadPacket, you must check the zero (z) flag in the status register for errors because the ReadPacket routine indicates an error by clearing it to 0. If the ReadPacket routine returns an error, you must terminate execution of your receive routine with an RTS instruction without calling ReadPacket again or calling ReadRest at all.

Calling ReadRest to Complete Reading in the Packet Contents

Call the ReadRest routine to read the last portion of the data packet, or call it after
you have read all the data with ReadPacket routines and before you do any other processing or terminate execution. After you call ReadRest, you must check the zero (z) flag in the status register for errors.

After you call the ReadRest routine, you must terminate execution of your receive routine with an RTS instruction whether or not the ReadRest routine returns an error.

When you call the ReadRest routine, you must provide in the A3 register a pointer to
a data buffer and you must indicate in the D3 register the size of the data buffer. If
you have already read all of the data using the ReadPacket routine, specify a buffer
of size 0.

WARNING
If you do not call the ReadRest routine after the last time you call the ReadPacket routine successfully, the system will crash.
To call the ReadRest routine, execute a JSR instruction to an address 2 bytes past the address in the A4 register:

JSR 2(A4)
The ReadRest routine uses the registers as follows:
Registers on entry to the ReadRest routine
A3Pointer to a buffer to hold the data you want to read
D3Size of the buffer (word length); may be 0
Registers on exit from the ReadRest routine
A0Unchanged
A1Unchanged
A2Unchanged
A3Pointer to first byte after the last byte read into buffer
D0Changed
D1Changed: number of bytes left to be read
D2Unchanged
D3Equals 0 if the requested number of bytes were read, is less than 0 if the
packet data was too large to fit in the buffer and the data was truncated, and
is greater than 0 to indicate the number of bytes that were not read

For more information on how your receive routine can use the registers, see the discussion of the socket listener routine in the chapter "Datagram Delivery Protocol (DDP)" in this book.


Previous Book Contents Book Index Next

© Apple Computer, Inc.
7 JUL 1996