RISCOS.com

www.riscos.com Technical Support:
Programmer's Reference Manual

 

Econet


Introduction

The Econet module provides the software needed to use Acorn's own Econet networking system. The software allows you to send and receive data over the network.

It is used by RISC OS modules such as NetFS and NetPrint, which provide network filing and printing facilities respectively. It is also used by various other Acorn products that use Econet, such as FileStores, Econet bridges, and so on.

Note that to use the Econet you must have an Econet expansion module fitted to your RISC OS computer. If you do not already have one, they are available from your Acorn supplier.

Overview

Econet is Acorn's own networking system, and the Econet module provides the necessary software to use it.

The main purpose of any networking system is to transfer data from one machine to another. Econet breaks up the data it sends into small parts which are sent using a well defined protocol.

Econet does not use buffers in the same way as most other input and output facilities that RISC OS provides. Instead the data is moved directly between the Econet hardware and memory. This means that each time data is transmitted or received, there has to be a block of memory available for the Econet software to use immediately, either to read data from or place data in.

These blocks of memory are administered by the Econet software, which uses control blocks to do so. Many of the SWIs interact with these control blocks, so you can set them up, read the status of an Econet transmission or reception, and release the control blocks memory when you have finished using them.

In the same way as files under the filing system use file handles, these control blocks also use handles. Just like file handles, your software must keep a record of them while you need to use them.

The Econet also provides a range of immediate operations, which allow you to exercise some control over the hardware of remote machines, assuming you get their co-operation. Some of these will work across the entire range of Acorn computers, whereas others are more hardware-dependent and so may only be possible on RISC OS machines.

Technical Details

Packets and frames

A single transmission of data on an Econet is called a packet. Packets travel across the network from the transmitting station to the receiving station. The most common form of packet is called a 'four way handshake'. A 'four way handshake' consists of four frames. Each of these four frames starts with the following four bytes:

  • the station number of the destination station
  • the net number of the destination station
  • the station number of the source station
  • the net number of the source station.

These four bytes are sent in this order to facilitate decoding by the software in the receiving station.

The first frame is sent by the transmitting station; it contains the usual first four bytes, the port byte (described later), and the flag byte (also described later). This first frame is called the scout. The receiving station then replies with the scout acknowledge, which consists of just the usual first four bytes. The third frame is the data frame; this frame has the usual first four bytes, followed by all the data to be transferred. Lastly there is a final acknowledge frame which is identical to the scout acknowledge frame.

This exchange of frames can be seen with the NetMonitor and is displayed something like this.

FE0012008099 1200FE00 FE00120048454C500D 1200FE00

  • the transmitting station is &12 (18 in decimal)
  • the receiving station is &FE (254 in decimal)
  • both stations are on net zero
  • the flag byte is &80
  • the port byte is &99
  • the data that is transmitted is &48, &45, &4C, &50, &0D.

Receiving data and using RxCBs

Successful transmission of data requires co-operation from the receiving station. A station shows that it is ready to receive by setting up a receive control block (or RxCB). All RxCBs are kept by the Econet software and don't need to concern you. To create an RxCB all you need to do is call a single SWI (Econet_CreateReceive: see Econet_CreateReceive), telling the Econet software all the required information. The Econet software will return to you a handle which you then use to refer to this particular RxCB in any further dealings with the Econet software.

The information required by the Econet software is:

  • which station(s) to accept data from
  • which port number(s) to accept data on
  • where to put the data when it arrives.

It is important you note that when the data arrives from the transmitting station it is not buffered at all - it is taken directly from the hardware and placed in memory at the address you specify. This area of memory is referred to as a buffer (in this case a receive buffer). A consequence of this is that memory used for receiving Econet packets must be available at all times whilst the relevant RxCB is open. You must not use memory in application space if your program is to run within the Desktop environment.

The Econet software keeps a list of all the open RxCBs. When a scout frame comes in it is checked to see if it matches any of the currently open RxCBs:

  • if it doesn't then the receiving software indicates this to the transmitting software by not sending a scout acknowledge frame
  • if it does then the receiving software sends out a scout acknowledge, and then copies the data frame into the corresponding buffer
  • if the data frame overruns the buffer then the receiving software does not send the final acknowledge frame.
Status of RxCB's

All RxCBs have a status value. These values are tabulated below.

7 Status_RxReady
8 Status_Receiving
9 Status_Received

The status of a particular RxCB can be read using the Econet_ExamineReceive call; this takes the receive handle of an RxCB and returns its status.

When an RxCB has been received into, its status will change from RxReady to Received; usually, you will then call Econet_ReadReceive. This returns information about the reception; most importantly it tells you how much data was received - which can be anything from zero to the size of the buffer. It also returns the value of the flag byte.

The port, station, and net are also returned; these are useful because you can open an RxCB that allows reception on any port or from any station.

Abandoning RxCB's

It is very important that when RxCBs are no longer required, either because they have been received into, or because they have not been received into within a certain time, that they are removed from the system. You do so by calling the SWI Econet_AbandonReceive. The major function of this call is to return to the RMA the memory that the Econet software used to hold the RxCB; obviously if RxCBs are not abandoned, they will consume memory which will not automatically be recovered by the system.

Receiving data using a single SWI

The usual sequence of operations required for software to receive data is as follows: First call SWI Econet_CreateReceive, then make numerous calls to SWI Econet_ExamineReceive until either a reception occurs, a time out occurs, or the user interferes (by pressing Escape for instance). Then read the RxCB (Econet_ReadReceive) if it has been received into. Finally, abandon the RxCB (Econet_AbandonReceive).

To make this task easier the Econet software provides a single SWI (Econet_WaitForReception: see Econet_WaitForReception) which does the polling, the reading, and the abandoning for you. To call SWI Econet_WaitForReception you must pass in:

  • the receive handle
  • the amount of time you are prepared to wait
  • a flag which indicates whether you wish the call to return if the user presses the Escape key.

Econet_WaitForReception returns one of four status values:

8 Status_Receiving
9 Status_Received
10 Status_NoReply
11 Status_Escape

The call will return as soon as a reception occurs; when this happens the status is Received. If the time limit expires then the status is usually NoReply, but if reception had started just after the timeout, and so was then abandoned, the status will be Receiving. This is not a very likely case. If the escapable flag is set then pressing the Escape key causes the call to return with the Escape status.

Transmitting data and using TxCB's

Transmission is roughly similar to reception; a single SWI (Econet_StartTransmit - Econet_StartTransmit) is all that is required to get things started. This call requires the following information:

  • the destination station (and net)
  • the port number to transmit on
  • the flag byte to send
  • the address and length of the data to send.

SWI Econet_StartTransmit returns a handle. These handles are distinct from the handles used by the receive SWIs.

Various transport types may impose a limit on the amount of data you can send in a single packet. You can find out the limit for the transport you are using by calling Econet_PacketSize.

Status of TxCB's

To check the progress of your transmission you can call Econet_PollTransmit. This returns the status of the particular TxCB, which will be one of seven possible values:

0 Status_Transmitted
1 Status_LineJammed
2 Status_NetError
3 Status_NotListening
4 Status_NoClock
5 Status_TxReady
6 Status_Transmitting

Status_Transmitted means that your transmission has completed OK and that the data has been received by the destination machine. Status_TxReady means that your transmission is waiting to start, either because the Econet is busy receiving or transmitting something else, or your transmission is queued (see later for more details of this). Status_Transmitting is obvious; so too is Status_NoClock, which means that the Econet is not being clocked, or more likely your station is not plugged into the Econet. Status_LineJammed means that the Econet software was unable to gain access to the Econet; this may be because other stations were transmitting, but it is more likely that there is a fault in the Econet cabling somewhere. Status_NotListening is returned when the destination station doesn't send back a scout acknowledge frame; this is usually because the destination station doesn't have a suitable open receive block. Status_NetError will be returned if some part of the four way handshake is missing or damaged; the usual cause of this status is the sender sending more data than the receiver has buffer space for, so the receiver doesn't send back the final acknowledge frame.

Retrying transmissions

Status returns like NotListening and NetError can also be caused by transient problems with the Econet such as electrical noise, or by the receiving station using its floppy disc or being otherwise too busy to accept data. Because of this it is usual to try more than once to send a packet if these status returns occur. To make this easier for you the Econet software can automatically perform these extra attempts for you. These retries are controlled by passing two further values in to the Econet_StartTransmit SWI:

  • the number of times to try, referred to as the Count
  • the amount of time to wait between tries, referred to as the Delay.

If the Count is either zero or one then only one attempt to transmit will take place. If the Count is two or more then retries will occur, at the specified interval (given in centiseconds). To give an example as it would be written in BASIC V:

10 DIM Buf% 20
20 Port%=99: Station%=7: Net%=0
50 SYS "Econet_StartTransmit",0,Port%,Station%,Net%,Buf%,20,3,100 TO Tx%
60 END

When this partial program was RUN it would try to transmit immediately, probably before the program reached the END statement. If this transmission failed with either Status_NotListening or Status_NetError, then the Econet software would wait for one second (100 centiseconds) and try again. If this also failed then the software would wait a further second and try for a third time. The status of the final (in this case third) transmission would be the status finally stored in the TxCB; this could be read using SWI Econet_PollTransmit. To see this we could add some extra lines to the example program:

 30 TxReady%=5
 40 Transmitting%=6
 60 REPEAT
 70   SYS "Econet_PollTransmit", Tx% TO Status%
 80   PRINT Status%
 90 UNTIL NOT ((Status%=TxReady%) OR (Status%=Transmitting%))
100 END

Now the program will show us the status of the TxCB. We would be very unlikely to see the status value ever be Status_Transmitting since it will only have this value for about 90[MU]s during the two seconds it is retrying for. But it is most important that your software should be able to handle such a situation without error.

For retries to be effective you must try for at least 5 seconds. Recommended values for the Count and Delay are:

Broadcasts: Count = 5, Delay = 5
Machine peeks: Count = 40, Delay = 5
All other transmissions: Delay × (Count - 1) >= 500
Abandoning TxCB's

As with receptions it is most important that memory used for transmitting Econet packets must be available at all times whilst the relevant TxCB is open. You must not use memory in application space if your program is to run within the Desktop environment. This is because like receptions, transmissions move data directly from memory at the address you specify to the hardware. Also, as with receptions, it is important to inform the Econet software that you have finished with your transmission and that memory required for the internal TxCB may be returned to the RMA. You do this by calling Econet_AbandonTransmit with the appropriate TxHandle:

100 SYS "Econet_AbandonTransmit", Tx% TO FinalStatus%
110 PRINT "The final status was ";FinalStatus%

Transmitting data using a single SWI

To make this start, poll, and abandon sequence easier for you the Econet software provides it all as a single call (Econet_DoTransmit: see Econet_DoTransmit). This call has the same inputs as SWI Econet_StartTransmit, but instead of returning a handle it returns the final status. Using this call our program would look like this:

10 DIM Buf% 20
20 Port%=99: Station%=7: Net%=0
40 SYS"Econet_DoTransmit",0,Port%,Station%,Net%,Buf%,20,6,100 TO Status%
50 PRINT "The final status was ";Status%

Converting a status to an error

As you can see this makes things a lot easier. As an aid to presenting these status values to the user there are two SWI calls to convert status values to a textual form, the most frequently used of which is the call Econet_ConvertStatusToError. This call takes the status and returns an error with the appropriate error number and an appropriate string describing the error.

For instance we could add an extra line to our final program:

80 SYS "Econet_ConvertStatusToError", Status%

Note that the SYS command sets unused registers to zero.

Copying the error to RAM

Our program will now RUN and always have an error, in this case the error 'Network station not listening at line 80'. This error message is actually held in the RMA, in one of a number of error blocks used by the MessageTrans module, and so you cannot directly add to it. Furthermore, the error message will have a 'limited lifetime' before MessageTrans reuses the error block. Consequently, if you wish to process the error message or to preserve it, you should copy it into a buffer. To do so you can specify the location and size of such a buffer when calling Econet_ConvertStatusToError:

70 DIM Error% 50
80 SYS "Econet_ConvertStatusToError", Status%, Error%, 50

This new program will function in the same manner as the previous program except that the error block will have been copied from the Econet messages file (in the ROM) into RAM (at the address given in R1). The main reason for this is to allow the Econet software to customise the error for you.

Adding station and net numbers

If the station and net numbers are added as inputs to the call, the Econet software will add them to the output string:

80 SYS "Econet_ConvertStatusToError",Status%,Error%,50,Station%,Net%

Now the error reported will be of the form 'Network station 7 not listening at line 80'. It is important to stress that this is a general purpose conversion. It will convert Status_Transmitted just as well as Status_NotListening, so usually you would test the returned status from Econet_DoTransmit, and only convert status values other than Status_Transmitted into errors:

30 Transmitted%=0
60 IF Status%=Transmitted% THEN PRINT "OK": END

The same program fragment could be written in assembler (this example, like all others in this chapter, uses the ARM assembler rather than the assembler included with BBC BASIC V - there are subtle syntax differences):

Tx      MOV     r0, #0      ; Flag
        MOV     r1, #99     ; Port
        MOV     r2, #7      ; Station
        MOV     r3, #0      ; Net
        ADR     r4, Buffer
        MOV     r5, #20     ; Buffer length
        MOV     r6, #6      ; Count
        MOV     r7, #100    ; Delay (in centiseconds)
        SWI     Econet_DoTransmit
        BEQ     r0, #Status_Transmitted
        LDRNE   r1, ErrorBuffer
        MOVNE   r2, #50
        SWINE   Econet_ConvertStatusToError
        MOV     pc, lr

Notice here in the assembler version how the return values from Econet_DoTransmit fall naturally into the input values required for Econet_ConvertStatusToError. This code fragment is not really satisfactory since no code written as either a module or a transient command should ever call the non-X form of SWIs. If the routine Tx is treated as a subroutine then it should look more like this:

Tx      STMFD   sp!, {lr}
        MOV     r0, #0      ; Flag
        MOV     r1, #99     ; Port
        MOV     r2, #7      ; Station
        MOV     r3, #0      ; Net
        ADR     r4, Buffer
        MOV     r5, #20     ; Buffer length
        MOV     r6, #6      ; Count
        MOV     r7, #100    ; Delay (in centiseconds)
        SWI     XEconet_DoTransmit
        BVS     TxExit
        TEQ     r0, #Status_Transmitted
        ADRNE   r1, ErrorBuffer
        MOVNE   r2, #50
        SWINE   XEconet_ConvertStatusToError
TxExit  LDMFD   sp!, {pc}

This routine returns with V clear if all went well; if V is set, then on return R0 will contain the address of a standard error block.

RISC OS 2

RISC OS 2 differs from later versions in that it doesn't use the MessageTrans module, but instead has the full text of the English error messages in ROM. When converting messages with added station numbers you must convert into your own buffer. If you give no buffer, or its length is insufficient, then the station and net numbers are ignored and RISC OS 2 returns a pointer to the normal ROM copy of the message.

Converting a status to a string

The second error conversion call is Econet_ConvertStatusToString, which does exactly what its name suggests. The input requirements are very similar to the string conversion SWIs supported by RISC OS. In this case you pass the status value, a buffer address, and the length of the buffer. As with Econet_ConvertStatusToError you can also pass the station and net numbers, which will be included in the output string. To illustrate this the assembler routine shown above is changed to print the status on the screen:

Tx      STMFD   sp!, {lr}
        MOV     r0, #0                ; Flag
        MOV     r1, #99               ; Port
        MOV     r2, #7                ; Station
        MOV     r3, #0                ; Net
        ADR     r4, Buffer
        MOV     r5, #20               ; Buffer length
        MOV     r6, #6                ; Count
        MOV     r7, #100              ; Delay (in centiseconds)
        SWI     XEconet_DoTransmit
        BVS     TxExit
        TEQ     r0, #Status_Transmitted
        BEQ     TxExit                ; Everything is OK
        ADR     r1, TextBuffer
        MOV     r2, #50               ; Text buffer length
        MOV     r5, r0                ; Save the status value
        SWI     XOS_ConvertCardinal1  ; Convert the status number
        MOVVC   r0, r5                ; Recall status if no error
        SWIVC   XEconet_ConvertStatusToString
        ADRVC   r0, TextBuffer
        SWIVC   XOS_Write0            ; Print the resultant string
TxExit  LDMFD   sp!, {pc}

MessageTrans tokens

Both Econet_ConvertStatusToError and Econet_ConvertErrorToString use MessageTrans to produce the error message or string. The message tokens for each of the status values are tabulated below. Where two tokens are listed, as for Status_NotListening, the first is for the error message - or string - without a station number inserted, and the second is for the version with the station number inserted. The files supplied with RISC OS that the Econet software
uses are 'Resources:$.Resources.Econet.Messages' and 'Resources:$.Resources.Global.Messages' (used solely
for the status message for Escape).

Error Status Token(s)
0 Status_Transmitted TxOK
1 Status_LineJammed LineJam
2 Status_NetError NetErr
3 Status_NotListening NotLstn StnNLsn
4 Status_NoClock NoClk
5 Status_TxReady TxReady
6 Status_Transmitting Txing
7 Status_RxReady RxReady
8 Status_Receiving Rxing
9 Status_Received Rxd
10 Status_NoReply NoReply StnNRpy
11 Status_Escape Escape
12 Status_NotPresent NotPres StnNPrs

Flag bytes

The flag byte is sent from the transmitting station to the receiving station and can be treated as an extra seven bits of data. By convention, it is used as a simple way of distinguishing different types of packet sent to the same port, and it is worth you doing the same.

This is most useful in server type applications where it is often the case that similar data can be sent for different purposes, or some sorts of data are outside the normal scope. An example is a server that takes requests for teletext pages, but can also return the time. A different value for the flag byte allows the server to differentiate time requests from normal traffic. Another example is the printer server protocol, which uses the flag byte to indicate the packet that is the last in the print job, without having to change the data part of the packet.

Port bytes

The port byte is used in the receiving station to distinguish traffic destined for particular applications or services.

For instance the printer server protocol uses port &D1 for all its connect, data transfer, and termination traffic, whereas the file server uses port &99 for all its incoming commands. This use of separate ports for separate tasks is also exploited further by the file server protocol in that every single request for service by the user can use a different port for its reply. This prevents traffic getting confused.

The Econet software provides some support for you to use ports by providing an allocation service for port numbers. Port numbers should, if possible, be allocated for all incoming data.

Software that requires the use of fixed port numbers, like NetFS and NetPrint, can claim these fixed ports by calling Econet_ClaimPort. This call takes a port number as its only argument. When these claimed ports are no longer required (when the module dies for instance) it can be 'returned' by calling SWI Econet_ReleasePort.

Other software that would like a port number allocated to it can call Econet_AllocatePort, which will return a port number. While this port number is allocated no other calls to Econet_AllocatePort will return that number, until it is 'released' by calling Econet_DeAllocatePort with the port number as an input. The NetFS software uses this method of allocation and deallocation to get ports to use as reply ports in the file server protocol. The Econet software keeps a table in which it records the state of each port number: this can be either free, claimed or allocated.

Freeing ports

Ports that have been claimed will not be allocated, and can only be freed by calling SWI Econet_ReleasePort. Calling SWI Econet_DeAllocatePort will return an error if the port is claimed rather than allocated. Ports that have been allocated can not be claimed, and in fact an attempt to claim an allocated port will return an error. You should be careful with software that uses allocated ports to make sure that all ports are deallocated when they are no longer required, especially after an error. The claiming and releasing of ports should likewise be carefully checked.

An example of use of the port allocator

A typical example of the use of the port allocator would be a multi-player adventure game server. The server would claim one port (eg port &1F). This port number would then be the only fixed port number in the entire protocol. When a player wished to join the game she should ask for a port to be allocated in her machine and send this port, along with all the information required to enter the game, to the game server on port &1F. If the server can't be contacted or doesn't reply within the required time the port should be deallocated and an error returned. When the server receives this packet it should check the user's entry data; if this is OK it should then allocate a port for that user and return it, along with any other information required to start the game off. When the user wants to quit the game the server should deallocate its user's port, then send the last reply to the user. The user should deallocate the port when the reply arrives or if the server doesn't reply soon enough.

To illustrate this example the user entry routine is shown below; note that this routine is coded for clarity rather than size or efficiency.

Entry   STMFD   sp!, {r0-r8,lr}                 ; R0 points to the text string
        SWI     XEconet_AllocatePort
        BVS     Exit
        STRB    r0, Server_ReplyPort
        LDR     r1, Server_Station
        LDR     r2, Server_Net
        ADR     r3, Buffer
        MOV     r4, #?Buffer                    ; Length of buffer
        SWI     XEconet_CreateReceive
        BVS     DeAllocateExit
        MOV     r8, r0                          ; Preserve the RxHandle
        LDR     r1, [sp, #0]                    ; Address of text string to copy
        ADR     r4, Buffer                      ; Get buffer to copy into
        MOV     r5, #0                          ; Index into Tx Buffer
        LDRB    r0, Server_ReplyPort
        STRB    r0, [r4, r5]                    ; Send the port for the server
CopyLoop
        ADD     r5, r5, #1
        CMP     r5, #?Buffer                    ; Have we run out of buffer?
        BHS     BufferOverflow
        LDRB    r0, [r1], #1                    ; Pick up byte and move to next one
        CMP     r0, #" "                        ; Is this a control character?
        MOVLT   r0, #CR                         ; Terminate as the server expects
        STRB    r0, [r4, r5]
        BGE     CopyLoop                        ; Loop back for the next byte
        ADD     r5, r5, #1                      ; Set entry conditions for Tx
        MOV     r0, #0
        MOV     r1, #EntryPort                  ; A constant
        LDR     r2, Server_Station
        LDR     r3, Server_Net
        LDR     r6, Server_TxDelay
        LDR     r7, Server_TxCount
        SWI     XEconet_DoTransmit
        BVS     DeAllocateExit
        TEQ     r0, #Status_Transmitted
        BEQ     WaitForReply
ConvertEconetError
        ADR     r1, Buffer                      ; Convert status and exit
        MOV     r2, #?Buffer
        SWI     XEconet_ConvertStatusToError
        B       DeAllocateExit
WaitForReply
        MOV     r0, r8                          ; Receive handle
        LDR     r1, Server_RxDelay
        MOV     r2, #0                          ; Don't allow ESCape
        SWI     XEconet_WaitForReception
        BVS     DeAllocateExit
        TEQ     r0, #Status_Received
        BNE     ConvertEconetError
        LDR     r0, Buffer                      ; Get server return code
        CMP     r0, #0                          ; Has there been an error?
        ADR     r0, Buffer                      ; Get address of reply
        BNE     DeAllocateExit                  ; Yes, process error
        LDRB    r1, [r0, #4]                    ; Load server's port
        STRB    r1, Server_CommandPort
Exit
        STRVS   r0, [sp, #0]                    ; Poke error into return regs
        LDMFD   sp!, {r0-r8,pc}                 ; Return to caller
BufferOverflowError
        DCD     ErrorNumber_BufferOverflow
        DCB     Command too long for buffer", 0
        ALIGN
BufferOverflow
        ADR     r0, BufferOverflowError
DeAllocateExit
        MOV     r1, r0                          ; Preserve the original error
        LDRB    r0, Server_ReplyPort
        SWI     XEconet_DeAllocatePort
        MOV     r0, r1                          ; Ignore deallocation errors
        CMP     pc, #&80000000                  ; Set V
        B       Exit                            ; Exit through common point

Points to notice in the example are:

  • the careful use of a single exit point
  • the consistent return of errors (no matter what type)
  • the opening of the receive block before doing the transmit
  • the use of the 'X' form of SWIs.

It should be noted that the routine uses and manipulates global state as well as taking specific input and returning specific output.

Econet events

To allow Econet based programs to be kinder to other applications within the machine, it is possible for your program to be 'notified' when either a reception occurs or a transmission completes. This means that other applications can be using the time that your program would have spent polling, either inside Econet_DoTransmit or inside Econet_WaitForReception. This 'notification' is carried by an event. There are separate events for reception and for completion of transmission. These two events are:

14 Event_Econet_Rx
15 Event_Econet_Tx

On entry to the event vector:

  • R0 will contain the event number, either Event_Econet_Rx or Event_Econet_Tx
  • R1 will contain the receive or transmit handle as appropriate
  • R2 will contain the status of the completed operation
  • R3 will contain the port of the completed operation, except under RISC OS 2.

The status for receive will always be Status_Received, but for transmit it will indicate how the transmission completed:

0 Status_Transmitted
1 Status_LineJammed
2 Status_NetError
3 Status_NotListening
4 Status_NoClock
9 Status_Received

These events can be enabled and disabled in the normal way using OS_Byte calls.

Using events from the Wimp

If your program is a client of the Wimp then all your event routine need do is set the Wimp poll word non-zero when the event happens; see the chapter entitled PollWord_NonZero 13.

Event   TEQ     r0, #Event_Econet_Rx
        TEQNE   r0, #Event_Econet_Tx
        MOVNE   pc, lr                ; If not, exit as fast as possible
        STMFD   sp!, {lr}             ; Must preserve all regs for others
        ADR     r14, WimpPollWord
        STR     pc, [r14]             ; Set flag with non-zero value
        LDMFD   sp!, {pc}             ; Return, without claiming vector

Setting up background tasks

Since the interfaces required for reception and transmission can be called from within event routines, you can set up background tasks that make full use of the facilities offered by Econet. Note that it is important to check that the handle offered in the event belongs to your program, since there may well be many programs using this facility. The example given below is of a simple background server for sending out the time. Not all of the code needed is shown, just the event routine:

Start   STMFD   sp!, {r0-r4,lr}
        MOV     r0, #EventV             ; The vector we want is EventV
        ADR     r1, Event               ; Where to goto when it happens
        MOV     r2, #0                  ; Required so that we can release
        SWI     XOS_Claim
        MOVVC   r0, #14                 ; Enable event
        MOV     r1, #Event_Econet_Rx
        SWIVC   XOS_Byte
        MOVVC   r0, #14                 ; Enable event
        MOV     r1, #Event_Econet_Tx
        SWIVC   XOS_Byte
        MOVVC   r0, #CommandPort        ; First open the reception
        MOV     r1, #0                  ; From any station
        MOV     r2, #0                  ; From any net
        ADR     r3, Buffer
        MOV     r4, #?Buffer
        SWIVC   XEconet_CreateReceive
        STRVC   r0, RxHandle
        STRVS   r0, [sp]
        LDMFD   sp!, {r0-r4,pc}
Event   TEQ     r0, #Event_Econet_Rx
        BNE     LookForTx
        LDR     r0, RxHandle            ; Get our global state
        TEQ     r0, r1                  ; Is it for us?
        MOVNE   r0, #Event_Econet_Rx
        MOVNE   pc, lr                  ; If not, exit as fast as possible
        STMFD   sp!, {r3-r7}            ; Only R0, R1 and R2 are free for use
        MOV     r0, r1                  ; Receive handle
        SWI     XEconet_ReadReceive     ; R4.R3 is the reply address
        BVS     Exit
        MOV     r6, r3                  ; Save the station number for later
        MOV     r0, #Module_Claim
        MOV     r3, #8 + 5              ; Two words and five bytes required
        SWI     XOS_Module              ; Memory MUST come from RMA
        BVS     Exit
        ADD     r1, r2, #8              ; Get the address of the 5 bytes
        MOV     r0, #3                  ; Set OS_Word reason code
        STRB    r0, [r1]                ; Read as a five byte time
        MOV     r0, #14                 ; Read from the real time clock
        SWI     XOS_Word
        BVS     Exit
        MOV     r0, #0                  ; Flag byte
        MOV     r3, r4                  ; Net number
        MOV     r4, r1                  ; Get the address of the 5 bytes
        LDRB    r1, [r5]                ; The reply port the client sent
        MOV     r2, r6                  ; Station number
        MOV     r5, #5                  ; Number of bytes to send
        MOV     r6, #ReplyCount
        MOV     r7, #ReplyDelay
        SWI     XEconet_StartTransmit
        BVS     Exit
        SUB     r4, r2, #8              ; R4 now in R2
        STR     r0, [r4, #4]            ; Save TxHandle in record
        ADR     r1, TxList              ; Address of the head of the list
        LDR     r2, [r1, #0]            ; Head of the list
        STR     r2, [r4, #0]            ; Add the list to new record
        STR     r4, [r1, #0]            ; Make this record the list head#
        MOV     r0, #CommandPort        ; Now re-open the reception
        MOV     r1, #0                  ; From any station
        MOV     r2, #0                  ; From any net
        ADR     r3, Buffer
        MOV     r4, #?Buffer
        SWI     XEconet_CreateReceive
        STRVC   r0, RxHandle
Exit
        LDMFD   sp!, {r3-r7, pc}        ; Return claiming vector
LookForTx
        TEQ     r0, #Event_Econet_Tx
        MOVNE   pc, lr
        STMFD   sp!, {r3, lr}           ; Get two extra registers
        ADR     r3, TxList              ; The address of the head of list
        LDR     r14, [r3]               ; The first record in the list
        B       StartLooking
NextTx
        MOV     r3, r14                 ; Search the next list entry
        LDR     r14, [r3]               ; Get the link address
StartLooking
        CMP     r14, #0                 ; Is this the end of the list?
        MOVLE   r0, #Event_Econet_Tx    ; Restore entry conditions
        LDMLEFD sp!, {r3, pc}           ; Return, continuing to next owner
        LDR     r0, [r14, #4]           ; Get the handle for this record
        TEQ     r0, r1                  ; Is this event one of ours?
        BNE     NextTx                  ; No, try next record in list
        LDR     r2, [r14]               ; Get the remainder of the list
        STR     r2, [r3]                ; Remove this record from list
        MOV     r2, r14                 ; The record address for later
        SWI     XEconet_AbandonTransmit
        MOV     r0, #Module_Free
        SWI     XOS_Module              ; Return memory to RMA, ignore error
        LDMFD   sp!, {r3, lr, pc}       ; Return, claiming vector

This program also illustrates some of the more advanced features of Econet. In particular; it shows the ability to specify reception control blocks that can accept messages from more than one machine, or on more than one port. Receive control blocks like this are referred to as wild, as in wild card matching used in file name look up. Specifying either the station or net number (usually both) as zero means 'match any'. The same is true of the port number, although this facility is much less useful! This wild facility does not mean that more than one packet can be received, but rather that more than one particular packet will be acceptable. Once a packet has been received, the RxCB has Status_Received and is no longer open.

It is worth noting an implementation detail here. Receive control blocks are kept by the Econet software in a list, when an incoming scout has been received the list is scanned to find the first RxCB that matches it. To ensure that things go as one would expect the Econet software that implements the SWI Econet_CreateReceive always adds wild RxCBs to the tail of the list, and normal RxCBs to the middle of the list (between the normal and the wild ones). This ensures that when packets arrive they will be checked for exact matches before wild matches, and that if there is more than one acceptable RxCB then the one used will be the one that was opened first, ie first in first served.

Broadcast transmissions

As a complement to this concept of wild receive control blocks there are broadcast transmissions. A broadcast has both its destination station and net set to &FF, it can then be received by more than one machine. To achieve this it does not use the normal four way handshake, it is in fact a single packet. On the NetMonitor it would look something like this:

FFFF1200809F5052494E54200100

The broadcast address at the beginning (&FF, &FF), the source station and net (&12, &00), the control byte (&80), and the port (&9F) are the same as a normal scout frame, but then the data follows, in this case eight bytes.

Although the Econet software within RISC OS can transmit and receive broadcast messages of up to 1020 bytes (RISC OS 2) or 1024 bytes (later versions), other machines on Econet can't cope with messages of more than eight bytes without getting confused; this confusion causes them to corrupt such broadcasts. These other machines include things like FileStores and bridges, so beware! It is possible to transmit and/or receive zero to eight bytes without them being corrupted, but only broadcasts of exactly eight bytes can be received by BBC or Master computers, as well as being transported from net to net by bridges.

Transmitting a broadcast is exactly the same as transmitting a normal packet, all you need to do is set the destination station and net to &FF (not to -1).

Versions of RISC OS after 2.00 support a wider range of broadcasts, allowing local broadcasts (which are only seen on the local net) and long broadcasts (broadcasts of more than eight bytes, which new bridges will recognise and correctly propagate). To use these, set the station number to &FF, and the net number as follows:

Net Range Size
&FF Global Small (8 bytes maximum)
&FE Global Long (1020/1024 bytes maximum)
&FD Local Long (1020/1024 bytes maximum)
&FC reserved reserved

Note that local long broadcasts (ie net = &FD) are ignored by existing machines and bridges, and will always work.

Broadcasts don't return the status Status_NotListening, since there is no way for the transmitting station to determine whether or not its broadcast was received. Broadcasts are basically designed for locating resources, ie to transmit your desire to know about a particular class of thing. Anything recognising the broadcast will reply, so you know what's what and where it is. NetFS uses broadcast to find file servers by name, and NetPrint uses broadcast to find printer servers. The example broadcast packet shown above contains the ASCII text 'PRINT ' and is, not surprisingly, a request for all printer servers to respond.

Local loopback

When transmissions take place, the destination address is checked to see if it is the local machine (ie a transmission to your own machine). If this is the case then no access to the Econet network will take place, and if a suitable receive control block exists the data is transferred directly from the transmit buffer to the receive buffer. Local loopback is most important for Wimp-based server programs, as it allows them to offer their services to the local station as easily as to all other stations on the Econet.

Broadcasts are also subject to local loopback, but differ slightly in that even if local loopback takes place access to the Econet network will still occur. This is to ensure the semantics of broadcasts. This does however cause a slight problem, in that a broadcast can be initiated to the local station via local loopback and succeed, but still fail externally with - for example - Status_NoClock. This is a slight semantic deviation that you must bear in mind when writing software that may communicate with itself or other software running on your machine by using broadcasts.

The other problem that can occur with local loopback is premature reception, caused by transmission and reception using the same port (whether by accident, or as a feature of the protocol's design), and the length of the transmission being less than or equal to the length of the receive buffer. For example to communicate with an Econet Bridge to find out if a particular net exists code like this will generally work:

 10 SYS "Econet_AllocatePort" TO port%
 20 SYS "Econet_CreateReceive", port%, 0, 0, RxBuffer%, 10 TO handle%
 30 $TxBuffer%  = "Bridge"
 40 TxBuffer%?6 = port%
 50 TxBuffer%?7 = NetToTestFor%
 60 SYS "Econet_DoTransmit", &83, &9C, &FF, &FF, TxBuffer%, 8, 5, 5
 80 SYS "Econet_WaitForReception", handle%, 10, 0 TO status%
 90 IF status% = 9 THEN
100   PRINT "Net number ";STR$(NetToTestFor%);" exists."
110 ENDIF
120 SYS "Econet_DeAllocatePort",port%

However, when the port allocator returns port &9C the program will be subject to unexpected local loopback, and the broadcast will be received internally as well as transmitted externally. This will cause the program to incorrectly report a reception from the bridge, and to interpret it as a reply indicating the existence of the desired net. The most effective way to prevent this is to only create the receive control block after the transmission has completed. In the case above you could simply change line 20 to be line 70. In general it is not acceptable to transmit a request before opening the receive control block for the reply; however, some pre-existing protocols force the issue.

It is worth noting that the use of local loopback in the Wimp environment does require that the polling of receptions and transmissions be interleaved with calls to Wimp_Poll. If this is not done, although the data will be transferred, no notice will be taken because control will not be transferred to the receiving program.

Local loopback with zero length packets will cause the machine to lock up.

Immediate operations are not subject to local loopback.

Local loopback is not supported by RISC OS 2.

Immediate operations

There is a second class of network operations called immediate operations. These operations don't require the explicit co-operation of the destination machine; instead the co-operation is provided by the Econet software in that machine. Immediate operations are similar semantically to normal transmissions but, because they have no need for a port number, have a type instead of a flag; and most also require an extra input value. They have a separate pair of SWI calls to cause them to happen: Econet_StartImmediate and Econet_DoImmediate.

The call Econet_StartImmediate returns a transmit handle in exactly the same way as Econet_StartTransmit and that handle should be polled and abandoned in the same way. The call Econet_DoImmediate returns a status just as Econet_DoTransmit does.

There are nine types of immediate operations:

1 Econet_Peek Copy memory from the destination machine
2 Econet_Poke Copy memory to the destination machine
3 Econet_JSR Cause JSR/BL on the destination machine
4 Econet_UserProcedureCall Execute User remote procedure call
5 Econet_OSProcedureCall Execute OS remote procedure call
6 Econet_Halt Halt the destination machine
7 Econet_Continue Continue the destination machine
8 Econet_MachinePeek Machine peek of the destination machine
9 Econet_GetRegisters Return registers from the destination machine

The last one, Econet_GetRegisters, can only be transmitted by or received on RISC OS based machines, whereas all the others can be transmitted or received by BBC or Master series computers. The reason for this is that Econet_GetRegisters is specific to the ARM processor.

As noted earlier, Immediate operations are not subject to local loopback.

Econet_Peek and Poke

The poke operation is very similar to a transmit, in that data is moved from the transmitting station to the receiving station. The difference is that the address at which the data is received is supplied by the transmitting station. Peek is the inverse of poke; data is moved from the receiving station into the transmitting station.

Before the receiving station allows the data to be transferred (in or out), it validates the address range supplied by the transmitting station. This validation - done using the SWI XOS_ValidateAddress - takes place in an IRQ process, so having IRQs disabled will affect a machine's ability to be peeked or poked.

This validation does not take place under RISC OS 2.

Econet_JSR, UserProcedureCall and OSProcedureCall

JSR, UserProcedureCall, and OSProcedureCall are all very similar. They send a small quantity of data, referred to as the argument buffer or arguments, to the destination machine; they then force it to execute a particular section of code. When received a JSR actually does a BL to the address given in R1, whereas UserProcedureCall and OSProcedureCall cause events to occur. These events are:

8 Event_Econet_UserRPC
16 Event_Econet_OSProc

After reception the arguments are buffered so that they may be used by the code that is called, either directly by a BL or indirectly via an event. The format of the arguments buffer is as follows: word 0 is the length (in bytes) of the arguments, then the arguments follow this first word and may be null (ie the length may be zero).

Conditions on entry to event code

The conditions on entry to the event code are:

R0 = Event number (either Event_Econet_UserRPC or Event_Econet_OSProc)
R1 = Address of the argument buffer
R2 = RPC number (passed in R1 on the transmitting station)
R3 = Station that sent the RPC
R4 = Net that sent the RPC

Conditions on entry to JSR code

The conditions on entry to code that is BL'd to for a JSR are:

R1 = Address of the argument buffer
R2 = Address of the code being executed
R3 = Station that sent the JSR
R4 = Net that sent the JSR

Format of the argument buffer

The format of the argument buffer is exactly the same in all cases. If, in the case of a JSR, the call address transmitted from the remote station is -1 (&FFFFFFFF) then the execution address will be the argument buffer itself; this means that relocatable ARM code can be sent as a JSR. Registers R0 to R4 can be used as they are preserved by the Econet software, and R13 can also be used as a full descending stack.

The transmission of Econet_OSProcedureCall is intended for use solely by system software, and is only documented here for completeness. The transmission of Econet_JSR is only provided as a compatibility feature to allow interworking with BBC and Master computers.

Econet_UserProcedure calls

The Econet_UserProcedureCall is the best method for this style of communications. It does however have some restrictions. The first of these is the most important - it is executed in the destination machine as an event caused by an interrupt, and so it has all the normal restrictions applied to interrupt code. This means that code directly executed as a result of Event_Econet_UserRPC must be fast and clean, and must not call any of the normal input or output SWI routines nor call the filing system, either directly or indirectly. This is paramount if the integrity of the destination machine is to be ensured. However, you can copy away the arguments passed and signal to a foreground task (by altering a flag) that the procedure call has arrived. It is most important that you copy the arguments away, because the buffer that they are in is only valid for the duration of the event call. This means that R1 will point to the arguments whilst you are processing the event, but afterwards the argument buffer may be overwritten. If the requirements for the processing of the call are small then it is possible to do it all within the event. An example of this is a modification of the program presented earlier that returned the time. This new program sends the time in response to a User RPC, rather than a normal packet:

Start   MOV     r0, #EventV                     ; The vector we want is EventV
        ADR     r1, Event                       ; Where to goto when it happens
        MOV     r2, #0                          ; Required so that we can release
        SWI     XOS_Claim
        MOVVC   r0, #14                         ; Enable event
        STRVC   r0, ClaimedFlag                 ; Set it to a non-zero value
        MOV     r1, #Event_Econet_UserRPC
        SWIVC   XOS_Byte
        MOVVC   r0, #14                         ; Enable event
        MOV     r1, #Event_Econet_Tx
        SWIVC   XOS_Byte
        MOV     pc, lr
Event   TEQ     r0, #Event_Econet_UserRPC
        BNE     LookForTx
        TEQ     r2, #RPC_SendTime               ; Is it for us?
        MOVNE   pc, lr                          ; If not, exit as fast as possible
        LDR     r0, [r1, #0]                    ; Get size of arguments
        TEQ     r0, #1                          ; Check that it is right
        MOVNE   r0, #Event_Econet_UserRPC       ; Restore exit registers
        MOVNE   pc, lr                          ; If not, exit as fast as possible
        
        STMFD   sp!, {r5-r7}                    ; Only R1 to R4 are free for use
        ; R4.R3 is the reply address
        MOV     r6, r3                          ; Save the station number for later
        MOV     r5, r1                          ; Preserve arguments pointer
        MOV     r0, #Module_Claim
        MOV     r3, #8 + 5                      ; Two words and five bytes required
        SWI     XOS_Module                      ; Memory MUST come from RMA
        BVS     Exit
        ADD     r1, r2, #8                      ; Get the address of the 5 bytes
        MOV     r0, #3                          ; Set OS_Word reason code
        STRB    r0, [r1]                        ; Read as a five byte time
        MOV     r0, #14                         ; Read from the real time clock
        SWI     XOS_Word
        BVS     Exit
        MOV     r0, #0                          ; Flag byte
        MOV     r3, r4                          ; Net number
        MOV     r4, r1                          ; Get the address of the 5 bytes
        LDRB    r1, [r5, #4]                    ; The reply port the client sent
        MOV     r2, r6                          ; Station number
        MOV     r5, #5                          ; Number of bytes to send
        MOV     r6, #ReplyCount
        MOV     r7, #ReplyDelay
        SWI     XEconet_StartTransmit
        BVS     Exit
        
        SUB     r4, r2, #8                      ; R4 now in R2
        STR     r0, [r4, #4]                    ; Save TxHandle in record
        ADR     r1, TxList                      ; Address of the head of the list
        LDR     r2, [r1, #0]                    ; Head of the list
        STR     r2, [r4, #0]                    ; Add the list to new record
        STR     r4, [r1, #0]                    ; Make this record the list head
Exit
        LDMFD   sp!, {r5-r7, pc}                ; Return claiming vector
LookForTx
        TEQ     r0, #Event_Econet_Tx
        MOVNE   pc, lr                          ; This event has only R0 to R2
        STMFD   sp!, {r3, lr}                   ; Get two extra registers
        ADR     r3, TxList                      ; The address of the head of list
        LDR     r14, [r3]                       ; The first record in the list
        B       StartLooking
NextTx
        MOV     r3, r14                         ; Search the next list entry
        LDR     r14, [r3]                       ; Get the link address
StartLooking
        CMP     r14, #0                         ; Is this the end of the list?
        MOVLE   r0, #Event_Econet_Tx            ; Restore entry conditions
        LDMLEFD sp!, {r3, pc}                   ; Return, continuing to next owner
        LDR     r0, [r14, #4]                   ; Get the handle for this record
        TEQ     r0, r1                          ; Is this event one of ours?
        BNE     NextTx                          ; No, try next record in list
        LDR     r2, [r14]                       ; Get the remainder of the list
        STR     r2, [r3]                        ; Remove this record from list
        SWI     XEconet_AbandonTransmit
        MOV     r0, #Module_Free
        MOV     r2, r14                         ; The record address
        SWI     XOS_Module                      ; Return memory to RMA, ignore error
        LDMFD   sp!, {r3, lr, pc}               ; Return, claiming vector

You will notice how much simpler this program is when compared to the program shown earlier.

Econet_OSProcedure calls

There are five defined OS procedure calls for which only two have implementations under RISC OS. The five are:

0 Econet_OSCharacterFromNotify
1 Econet_OSInitialiseRemote
2 Econet_OSGetViewParameters
3 Econet_OSCauseFatalError
4 Econet_OSCharacterFromRemote
OSCharacterFromNotify

Econet_OSCharacterFromNotify causes the character received to be inserted into the keyboard buffer; the code that does so looks like this:

InsertCharacter                 ; R1 points at the argument buffer
        MOV     r0, #138        ; Insert into buffer OS_Byte
        LDRB    r2, [r1, #4]    ; Get character from buffer
        MOV     r1, #0          ; Buffer is keyboard
        SWI     XOS_Byte

Whilst the desktop is running the NetFiler module provides a different handler for characters from notify. It bundles them up by station, and when none have been received for a while sends them as a Wimp message, displaying them using Wimp_ReportError. For more information see the documentation of Message_Notify on Message_Notify (&40040).

OSCauseFatalError

Econet_OSCauseFatalError does exactly what its name implies. In fact it calls SWI OS_GenerateError directly from the event routine; normally this would be illegal, but since this is what the RPC is for, that is what it does. It should be observed that this can have a disastrous effect on the integrity of the machine and is not a recommended action; it is provided only for compatibility reasons.

Econet_Halt and Continue

Halt and continue are only acted upon by BBC and Master series machines; there is no implementation for receiving halt or continue on RISC OS machines or RISC iX machines.

Econet_MachinePeek

Machine peek is similar to peek, except that it is not possible to specify the address to be peeked, but rather four bytes are returned that identify the machine that is being machine peeked. Machine peek is used by some of the system software in RISC OS to quickly decide if a particular machine is present or not. The four bytes returned by machine peek are as follows:

Byte(s) Value
1 and 2 Machine type number
3 Software version number
4 Software release number
Machine type numbers

Machine type numbers are as follows:

&0000 Reserved
&0001 Acorn BBC Micro Computer (OS 1 or OS 2)
&0002 Acorn Atom
&0003 Acorn System 3 or System 4
&0004 Acorn System 5
&0005 Acorn Master 128 (OS 3)
&0006 Acorn Electron (OS 0)
&0007 Acorn Archimedes (OS 6)
&0008 Reserved for Acorn
&0009 Acorn Communicator
&000A Acorn Master 128 Econet Terminal
&000B Acorn FileStore
&000C Acorn Master 128 Compact (OS 5)
&000D Acorn Ecolink card for Personal Computers
&000E Acorn UNIX workstation
&000F to &FFF9 Reserved
&FFFA SCSI Interface
&FFFB SJ Research IBM PC Econet interface
&FFFC Nascom 2
&FFFD Research Machines 480Z
&FFFE SJ Research File Server
&FFFF Z80 CP/M
Software version and release number

The software version and release numbers are stored in two bytes. These two bytes are encoded in packed BCD (Binary Coded Decimal) and represent a number between 0 and 99. The easiest way to display packed BCD is to print it as if it was hexadecimal data:

ReportStationVersion
        MOV     r2, r0                          ; Station number in R0
        MOV     r3, r1                          ; Net number in R1
        MOV     r0, #Econet_MachinePeek
        ADR     r4, Buffer
        MOV     r5, #?Buffer
        MOV     r6, #40                         ; Count
        MOV     r7, #5                          ; Delay
        SWI     XEconet_DoImmediate
        MOVVS   pc, lr
        TEQ     r0, #Status_Transmitted
        BEQ     PrintVersion
        TEQ     r0, #Status_NotListening        ; from Machine peek
        MOVEQ   r0, #Status_NotPresent          ; return as "Not present"
        ADR     r1, Buffer
        MOV     r2, #?Buffer
        SWI     XEconet_ConvertStatusToError
        MOV     pc, lr
PrintVersion
        LDR     r3, [r2]                        ; Buffer address on exit from SWI
        MOV     r0, r3, ASR #24                 ; Get top byte
        ADR     r1, Buffer
        MOV     r2, #?Buffer
        SWI     XOS_ConvertHex2                 ; Print BCD as hex
        SWIVC   XOS_Write0                      ; Display output
        SWIVC   XOS_WriteI+"."                  ; Divide release from version number
        MOVVC   r0, r3, ASR #16                 ; Get version number in place
        ANDVC   r0, r0, #&FF                    ; Only the version number
        ADRVC   r1, Buffer
        MOVVC   r2, #?Buffer
        SWIVC   XOS_ConvertHex2                 ; Print BCD as hex
        SWIVC   XOS_Write0                      ; Display output
        MOV     pc, lr

We recommend that when using Econet_MachinePeek you use a Count of 40 and a Delay of 5.

Econet_GetRegisters

Econet_GetRegisters is similar to machine peek, in that a fixed amount of information is returned from the destination machine; in this case it is 80 bytes (20 words). The registers are returned in the following order: R0 to R14, PC plus PSR, R13_irq, R14_irq, R13_svc, and R14_svc. The FIQ registers are not returned because they are used by the Econet software, and so would always be the same, and of no interest since they would reflect the state of the part of the Econet software that transmits data. It is worthwhile aligning the receive buffer for a machine peek so that each of the 20 words is on a word boundary; this makes loading them easier.

Protection against immediate operations

Because these immediate operations can be quite intrusive it is possible to prevent their reception by manipulating an internal variable of the Econet software. There is one bit in this internal variable for each operation, and you can set or clear each bit. There is also a default value for each bit which is held in CMOS RAM. The SWI that allows you to manipulate this internal variable is Econet_SetProtection. These bits are held in a single word; the bit assignments are as follows:

Bit Immediate operation protected against
0 Peek
1 Poke
2 Remote JSR
3 User procedure call
4 OS procedure call
5 Halt
6 Continue - must be zero on RISC OS computers
7 Machine peek - must be zero on RISC OS computers
8 Get registers
9 - 30 Reserved - must be zero.
31 Write new value to the CMOS RAM

To protect against or disable the reception of a particular immediate operation, the appropriate bit should be set in the internal variable. The SWI Econet_SetProtection call replaces the OldValue with the NewValue, The NewValue is calculated like this:

NewValue = (OldValue AND R1) EOR R0
Altering the protection held in CMOS RAM

When the Econet software is started up (as a result of Ctrl-Break, or *RMReInit) then the value held in CMOS RAM will be used to initialise the internal variable. To alter the value held in CMOS RAM the entry value of R0 to SWI Econet_SetProtection should have bit 31 set, which causes the resultant value to be written not only to the internal variable, but also to the CMOS RAM. To read the current value you should use SWI Econet_SetProtection with R0=0, and R1=&FFFFFFFF.

Reading your station and net numbers

To establish what your station number is and which net you are connected to (if you have more than one), the Econet software provides a call to return these two values: Econet_ReadLocalStationAndNet. If you don't have more than one net then the net number (returned in R1) will be zero.

The local net number is in fact obtained from a bridge whenever the Econet module is initialised (eg when the machine is turned on). If this fails, say because there is no clock or the bridge is not switched on, then the local net number is reported as zero.

These values are the same as those reported by *Help Station (in fact *Help Station calls SWI Econet_ReadLocalStationAndNet to get the values).

Extracting station numbers from a string

To ensure that all Econet oriented software presents a consistent user interface there is a SWI call to read a station and/or net number from a supplied string. This call, Econet_ReadStationNumber, is used by both NetFS and NetPrint for all their command line processing. In the case of software that has a concept of a current station (and net) number the return value of -1 should mean 'use the existing value' - this is how *FS works, for example. Where there isn't a current value, as would be expected in a transient command such as *Notify, the return of -1 for the station number should be treated as an error and the return of -1 as a net number should imply the use of zero as a net number. The following is the beginning (and some of the end) of a transient command:

CommandStart
        LDRB    r0, [r1]                ; Check the first argument exists
        TEQ     r0, #0                  ; Zero means no arguments
        BEQ     SyntaxError             ; Exit with error
        SWI     XEconet_ReadStationNumber
        MOVVS   pc, lr                  ; Must be able to cope
        CMP     r2, #-1                 ; No station number given
        BEQ     NoStationNumberError
        CMP     r3, #-1                 ; No net number given
        MOVEQ   r3, #0                  ; Means use zero
        MOV     pc, lr
SyntaxError
        ADR     r0, ErrorGetRegsSyntax
        ORRS    pc, lr, #VFlag
ErrorGetRegsSyntax
        DCD     ErrorNumber_Syntax
        DCB     "Syntax: *Command <Station number>"
        DCB     0
        ALIGN
        
NoStationNumberError
        ADR     r0, ErrorUnableToDefault
        ORRS    pc, lr, #VFlag
ErrorUnableToDefault
        DCD     ErrorNumber_UnableToDefault
        DCB     "Either a station number or a full"
        DCB     " network address is required"
        DCB     0
        ALIGN

Converting station and net to a string

The kernel provides two inverse functions that convert a station and net number pair into a string. See OS_ConvertFixedNetStation and OS_ConvertNetStation for exact details.

Conventions and values

The following conventions apply to the various values that the Econet uses:

Station numbers

Station numbers are normally in the range 1 to 254. The station number zero is used in SWI Econet_CreateReceive to indicate that reception may occur from any station. The station number 255 is used in SWI Econet_StartTransmit and in SWI Econet_DoTransmit to indicate that a broadcast is to take place. Station number 255 is also used in SWI Econet_CreateReceive to indicate that reception may occur from any station; you may also use station number zero for this purpose, but its use is deprecated, and may be withdrawn in the future.

Net numbers

Net numbers are normally in the range 1 to 251. The value zero means the local Econet net; in a SWI Econet_CreateReceive it is taken to indicate that reception may occur from any net. The net numbers 255, 254 and 253 are used in SWI Econet_StartTransmit and in SWI Econet_DoTransmit to indicate that a broadcast is to take place. Net number 255 is also used in SWI Econet_CreateReceive to indicate that reception may occur from any station; the use of zero to indicate wild reception is deprecated.

Although RISC OS fully supports top-bit-set net numbers (ie 128 - 251), certain Econet devices - such as bridges - will not propagate them, leading to problems. You should beware of this.

Port numbers

Port numbers are normally in the range 1 to 254, although some values are reserved - as shown in the table below:

Port Allocation
&54 DigitalServicesTapeStore
&99 FileServerCommand
&9C Bridge
&9E PrinterServerInquiryReply
&9F PrinterServerInquiry
&A0 SJ Research *FAST protocol (file server management)
&AF SJ Research Nexus net finder reply port
&B0 FindServer
&B1 FindServerReply
&B2 TeletextServerCommand
&B3 TeletextServerPage
&D0 OldPrinterServerData
&D1 PrinterServerData
&D2 TCPIPProtocolSuite
&D3 SIDFrameSlave
&D4 Scrollarama
&D5 Phone
&D6 BroadcastControl
&D7 BroadcastData
&D8 ImpressionLicenceChecker
&D9 DigitalServicesSquirrel
&DA SIDSecondary
&DB DigitalServicesSquirrel2
&DC DataDistributionControl
&DD DataDistributionData
&DE ClassROM
&DF PrinterSpoolerCommand

Port numbers zero and 255 currently have a special meaning: they may be used as arguments to SWI Econet_CreateReceive to indicate that reception may occur regardless of the port number on the incoming packet. This use of zero to indicate wild reception is deprecated, and will be withdrawn in the future.

For an allocation of a port number you must contact Acorn.

Flag bytes

Flag byte values are in the range 0 to 127 (&7F). When passed in a word to a SWI, bits 8 - 31 inclusive must be zero. Bit 7 is ignored by RISC OS, to maintain compatibility with some older software that used this bit. To clarify, flag bytes &87 and &07 are acceptable as input to a transmission SWI (and both represent the value &07), but &107 is not acceptable. Reception SWIs all return values with bit 7 clear (ie &00 to &7F).

Transmission semantics

The transmission semantics are simple. When a transmission is started the client's control information (passed in registers) is stored in a record in a linked list within Econet workspace. At regular intervals the list is scanned, and those records that should be actually transmitted at that moment are passed to the FIQ software. When that particular transmission attempt completes the status of the record is changed accordingly. This means that if two transmissions are started at the same time, they will interleave their transmission retries.

When a transmission has completed but failed:

  • if the count is non-zero the delay is added to the predicted start time to give the next start time
  • otherwise the status is set to Status_NotListening (or Status_NetError).

This means that as far as possible the time out time will be the Delay multiplied by the (Count - 1).

Local loopback

Versions of RISC OS after RISC OS 2 have added support for local loopback. Transmissions directed at your own station number will be 'received' if there is an acceptable receive block open by directly copying the data. This applies to broadcast transmissions and wild receptions as well as to calls that explicitly address your machine.

Service Calls


Service_ReAllocatePorts
(Service Call &48)

Econet restarting

On entry

R1 = &48 (reason code)

On exit

R1 preserved to pass on (do not claim)

Use

This call is made whenever Econet restarts. It is then up to the Econet software to allocate ports, set up TxCBs and RxCBs, etc.


Service_EconetDying
(Service Call &56)

Econet is about to leave

On entry

R1 = &56 (reason code)

On exit

R1 preserved to pass on (do not claim)

Use

This call is made whenever Econet is about to leave. At this point the Econet module is already being finalised, and you may not make further calls to it. Resources such as ports, CBs etc are no longer valid, and you may dispose of any relevant local workspace.


Service_ProtocolDying
(Service Call &83)

Part of the AUN Driver Control Interface

Use

This service call is part of the AUN Driver Control Interface, used to interface a network interface's driver module to a protocol module. Third parties wishing to develop network interfaces for use with AUN may obtain further details on request from Acorn.


Service_FindNetworkDriver
(Service Call &84)

Part of the AUN Driver Control Interface

Use

This service call is part of the AUN Driver Control Interface, used to interface a network interface's driver module to a protocol module. Third parties wishing to develop network interfaces for use with AUN may obtain further details on request from Acorn.


Service_NetworkDriverStatus
(Service Call &8B)

Part of the AUN Driver Control Interface

Use

This service call is part of the AUN Driver Control Interface, used to interface a network interface's driver module to a protocol module. Third parties wishing to develop network interfaces for use with AUN may obtain further details on request from Acorn.

SWI Calls


Econet_CreateReceive
(SWI &40000)

Creates a Receive Control Block

On entry

R0 = port number
R1 = station number
R2 = net number
R3 = buffer address
R4 = buffer size in bytes

On exit

R0 = handle
R2 = 0 if R2 on entry is the local net number

Interrupts

Interrupt status is unaltered
Fast interrupts are enabled

Processor mode

Processor is in SVC mode

Re-entrancy

SWI is re-entrant

Use

This call creates a Receive Control Block (RxCB) to control the reception of an Econet packet. It returns a handle to the RxCB.

The buffer must remain available all the time that the RxCB is open, as data received over the Econet is read directly from hardware to the buffer. You must not use memory in application space if your program is to run under the Desktop. Instead, you should use memory from the RMA. To do so, claim the memory using OS_Module 6 (see OS_Module 6), and - after abandoning the receive control block - return the space to the RMA using OS_Module 7 (see OS_Module 7).

Related SWIs

Econet_ExamineReceive, Econet_WaitForReception, Econet_AbandonAndReadReceive

Related vectors

None


Econet_ExamineReceive
(SWI &40001)

Reads the status of an RxCB

On entry

R0 = handle

On exit

R0 = status

Interrupts

Interrupt status is unaltered
Fast interrupts are enabled

Processor mode

Processor is in SVC mode

Re-entrancy

SWI is re-entrant

Use

This call reads the status of an RxCB, which may be one of the following:

7 Status_RxReady
8 Status_Receiving
9 Status_Received

It returns less information than Econet_ReadReceive, so is faster and corrupts fewer registers. You should use it to poll a reception when not using Econet_WaitForReception.

Related SWIs

Econet_CreateReceive, Econet_WaitForReception, Econet_ConvertStatusToString, Econet_ConvertStatusToError

Related vectors

None


Econet_ReadReceive
(SWI &40002)

Returns information about a reception, including the size of data

On entry

R0 = handle

On exit

R0 = status
R1 = 0, or flag byte if R0 = 9 (Status_Received) on exit
R2 = port number
R3 = station number
R4 = net number
R5 = buffer address
R6 = buffer size in bytes, or amount of data received if R0 = 9 on exit (Status_Received)

Interrupts

Interrupt status is unaltered
Fast interrupts are enabled

Processor mode

Processor is in SVC mode

Re-entrancy

SWI is re-entrant

Use

This call returns information about a reception; most importantly, it tells you how much data was received, if any, and the address of the buffer in which it was placed. The buffer address is the same as that passed to Econet_CreateReceive. You can call this SWI before a reception has occurred.

The status of the RxCB may be one of the following:

7 Status_RxReady
8 Status_Receiving
9 Status_Received

The returned values in R3 and R4 (the net and station numbers) are those of the transmitting station if the status is Status_Received; otherwise they are the same values that were passed in to Econet_CreateReceive.

Related SWIs

Econet_CreateReceive, Econet_WaitForReception, Econet_AbandonAndReadReceive

Related vectors

None


Econet_AbandonReceive
(SWI &40003)

Abandons an RxCB

On entry

R0 = handle

On exit

R0 = status

Interrupts

Interrupts are disabled
Fast interrupts are enabled

Processor mode

Processor is in SVC mode

Re-entrancy

SWI is re-entrant

Use

This call abandons an RxCB, returning its memory to the RMA. The reception may have completed (R0 = 9 - Status_Received - on exit), in which case the information in the RxCB (such as the sending station number, and the amount of data sent) will be lost. The data in the receive buffer remains unaffected. If the reception is in progress when this SWI is called, then information in the RxCB is lost, as above.

Related SWIs

Econet_CreateReceive, Econet_WaitForReception, Econet_AbandonAndReadReceive

Related vectors

None


Econet_WaitForReception
(SWI &40004)

Polls an RxCB, reads its status, and abandons it

On entry

R0 = handle
R1 = delay in centiseconds
R2 = 0 to ignore Escape; else Escape ends waiting

On exit

R0 = status
R1 = 0, or flag byte if R0 = 9 (Status_Received) on exit
R2 = port number
R3 = station number
R4 = net number
R5 = buffer address
R6 = buffer size in bytes, or amount of data received if R0 = 9 on exit (Status_Received)

Interrupts

Interrupts are enabled
Fast interrupts are enabled

Processor mode

Processor is in SVC mode and in USR mode

Re-entrancy

SWI is not re-entrant

Use

This call repeatedly polls an RxCB (that you have already set up with Econet_CreateReceive) until a reception occurs, or a timeout occurs, or the user interferes (say by pressing Escape). It then reads the status of the RxCB before abandoning it.

The status of the RxCB may be one of the following:

8 Status_Receiving
9 Status_Received
10 Status_NoReply
11 Status_Escape

The returned values in R3 and R4 (the net and station numbers) are those of the transmitting station if the status is Status_Received; otherwise they are the same values that were passed in to SWI Econet_CreateReceive.

Note that because this interface enables interrupts it should not be called from within either interrupt service code or event routines.

During the loop when the polling of the RxCB and of Escape takes place, the processor is put in USR mode with IRQs enabled; this allows callbacks to occur.

Related SWIs

Econet_ExamineReceive, Econet_ReadReceive, Econet_AbandonReceive, Econet_AbandonAndReadReceive

Related vectors

None


Econet_EnumerateReceive
(SWI &40005)

Returns the handles of open RxCBs

On entry

R0 = index (1 to start with first receive block)

On exit

R0 = handle (0 if no more receive blocks)

Interrupts

Interrupt status is unaltered
Fast interrupts are enabled

Processor mode

Processor is in SVC mode

Re-entrancy

Not defined

Use

This call returns the handles of open RxCBs. On entry R0 is the number of the RxCB being asked for (1, 2, 3...). If the value of R0 is greater than the number of open RxCBs, then the value returned as the handle will be 0, which is an invalid handle.

This call should not be made from an IRQ or event routine as, although it will not fail, errors and omissions are likely to occur in the returned information.

Related SWIs

Econet_CreateReceive,
Econet_ReadReceive, Econet_AbandonReceive

Related vectors

None


Econet_StartTransmit
(SWI &40006)

Creates a Transmit Control Block and starts a transmission

On entry

R0 = flag byte
R1 = port number
R2 = station number
R3 = net number
R4 = buffer address
R5 = buffer size in bytes
R6 = count
R7 = delay in centiseconds

On exit

R0 = handle
R1 corrupted
R2 = buffer address
R3 = station number
R4 = net number

Interrupts

Interrupt status is unaltered
Fast interrupts are enabled

Processor mode

Processor is in SVC mode

Re-entrancy

SWI is re-entrant

Use

This call creates a Transmit Control Block (TxCB) to control the transmission of an Econet packet. It then starts the transmission.

The buffer must remain available all the time that the TxCB is open, as data transmitted over the Econet is read directly from the buffer to hardware. You must not use memory in application space if your program is to run under the Desktop. Instead, you should use memory from the RMA. To do so, claim the memory using OS_Module 6 (see OS_Module 6), and - after abandoning the transmit control block - return the space to the RMA using OS_Module 7 (see OS_Module 7).

The value returned in R4 (the net number) will be the same as that passed in R3 unless that number is equal to the local net number; in that case the net number will be returned as zero.

Related SWIs

Econet_PollTransmit, Econet_AbandonTransmit, Econet_DoTransmit

Related vectors

None


Econet_PollTransmit
(SWI &40007)

Reads the status of a TxCB

On entry

R0 = handle

On exit

R0 = status

Interrupts

Interrupt status is unaltered
Fast interrupts are enabled

Processor mode

Processor is in SVC mode

Re-entrancy

SWI is re-entrant

Use

This call reads the status of a TxCB, which may be one of the following:

0 Status_Transmitted
1 Status_LineJammed
2 Status_NetError
3 Status_NotListening
4 Status_NoClock
5 Status_TxReady
6 Status_Transmitting
Related SWIs

Econet_StartTransmit, Econet_AbandonTransmit

Related vectors

None


Econet_AbandonTransmit
(SWI &40008)

Abandons a TxCB

On entry

R0 = handle

On exit

R0 = status

Interrupts

Interrupt status is unaltered
Fast interrupts are enabled

Processor mode

Processor is in SVC mode

Re-entrancy

SWI is re-entrant

Use

This call abandons a TxCB, returning its memory to the RMA. The returned status is the same as for Econet_PollTransmit.

Related SWIs

Econet_StartTransmit, Econet_PollTransmit

Related vectors

None


Econet_DoTransmit
(SWI &40009)

Creates a TxCB, polls it, reads its status, and abandons it

On entry

R0 = flag byte
R1 = port number
R2 = station number
R3 = net number
R4 = buffer address
R5 = buffer size in bytes
R6 = count
R7 = delay in centiseconds

On exit

R0 = status
R1 corrupted
R2 = buffer address
R3 = station number
R4 = net number

Interrupts

Interrupts are enabled
Fast interrupts are enabled

Processor mode

Processor is in SVC mode and in USR mode

Re-entrancy

SWI is not re-entrant

Use

This call creates a TxCB and repeatedly polls it until it finishes transmission, or it exceeds the count of retries. It then reads the final status of the TxCB before abandoning it.

The status of the TxCB may be one of the following:

0 Status_Transmitted
1 Status_LineJammed
2 Status_NetError
3 Status_NotListening
4 Status_NoClock

The value returned in R4 (the net number) will be the same as that passed in R3 unless that number is equal to the local net number; in that case the net number will be returned as zero.

Note that because this interface enables interrupts it should not be called from within either interrupt service code or event routines.

During the loop when the polling of the TxCB and of Escape takes place, the processor is put in USR mode with IRQs enabled; this allows callbacks to occur.

Related SWIs

Econet_StartTransmit, Econet_PollTransmit,
and Econet_AbandonTransmit

Related vectors

None


Econet_ReadLocalStationAndNet
(SWI &4000A)

Returns a computer's station number and net number

On entry

No parameters passed in registers

On exit

R0 = station number
R1 = net number

Interrupts

Interrupts are enabled
Fast interrupts are enabled

Processor mode

Processor is in SVC mode

Re-entrancy

SWI is not re-entrant

Use

This call returns a computer's station number and Econet net number. The net number will be zero if there are no Econet bridges present on the network.

For more information, see the chapter entitled Reading your station and net numbers.

Related SWIs

None

Related vectors

None


Econet_ConvertStatusToString
(SWI &4000B)

Converts a status to a string

On entry

R0 = status
R1 = pointer to buffer
R2 = buffer size in bytes
R3 = station number
R4 = net number

On exit

R0 = buffer
R1 = updated buffer address
R2 = updated buffer size in bytes

Interrupts

Interrupt status is unaltered
Fast interrupts are enabled

Processor mode

Processor is in SVC mode

Re-entrancy

SWI is re-entrant

Use

This call converts a status to a string found in the messages file. This is then copied into RAM, including the station and net numbers, giving a string such as:

Network station 59.254 not listening

If the status given in R0 is invalid (ie not in the range 0 - 14), this will cause a data abort or an address exception. If the station/net number given in R3/R4 is invalid, no station information is given.

Under RISC OS 2 the string is not read from the messages file, but is instead read direct from the ROM.

Related SWIs

Econet_ConvertStatusToError

Related vectors

None


Econet_ConvertStatusToError
(SWI &4000C)

Converts a status to a string, and then generates an error

On entry

R0 = status
R1 = pointer to error buffer
R2 = error buffer size in bytes
R3 = station number
R4 = net number

On exit

R0 = pointer to error block
V flag is set

Interrupts

Interrupt status is unaltered
Fast interrupts are enabled

Processor mode

Processor is in SVC mode

Re-entrancy

SWI is re-entrant

Use

This call converts a status to a string found in the messages file. This is then copied into RAM, including the station and net numbers, giving a string such as:

Network station 59.254 not listening

If the station/net number given in R3/R4 is invalid, no station information is given.

Finally this call returns an error by setting the V flag, with R0 pointing to the error block.

If you use a buffer address of zero, then the string is left in a buffer in the MessageTrans workspace.

Under RISC OS 2 the string is not read from the messages file, but is instead read direct from the ROM.

Related SWIs

Econet_ConvertStatusToString

Related vectors

None


Econet_ReadProtection
(SWI &4000D)

Reads the current protection word for immediate operations

On entry

No parameters passed in registers

On exit

R0 = current protection value

Interrupts

Interrupt status is unaltered
Fast interrupts are enabled

Processor mode

Processor is in SVC mode

Re-entrancy

SWI is re-entrant

Use

This call reads the current protection word for immediate operations. Various bits in the word, when set, disable corresponding immediate operations:

Bit Immediate operation
0 Peek
1 Poke
2 Remote JSR
3 User procedure call
4 OS procedure call
5 Halt
6 Continue - always zero on RISC OS computers
7 Machine peek - always zero on RISC OS computers
8 Get registers
9 - 31 Reserved - must be zero

Note - This call is deprecated. You should preferably use the call Econet_SetProtection to read the protection word instead of this call.

Related SWIs

Econet_SetProtection

Related vectors

None


Econet_SetProtection
(SWI &4000E)

Sets or reads the protection word for immediate operations

On entry

R0 = EOR mask word
R1 = AND mask word

On exit

R0 = old value

Interrupts

Interrupts are enabled on write-through to CMOS, preserved otherwise
Fast interrupts are enabled

Processor mode

Processor is in SVC mode

Re-entrancy

SWI is not re-entrant

Use

This call sets the protection word for immediate operations as follows:

New value = (old value AND R1) EOR R0

Various bits in the word, when set, disable corresponding immediate operations:

Bit Immediate operation
0 Peek
1 Poke
2 Remote JSR
3 User procedure call
4 OS procedure call
5 Halt
6 Continue - must be zero on RISC OS computers
7 Machine peek - must be zero on RISC OS computers
8 Get registers
9 - 30 Reserved - must be zero
31 Write new value to the CMOS RAM

Normally this call sets or reads the current value of the word. A default value for this word is held in CMOS RAM.

The most useful values of R0 and R1 are:

Action R0 R1
Set current value new value (0 - &1FF) 0
Read current value 0 &FFFFFFFF
Set new default value &80000000 + new value 0

You should use this call to read the value of the protection word, rather than Econet_ReadProtection.

Using this call to read is also the preferred method for detecting the presence of the Econet drivers, since doing so can never return an unexpected error. Detecting the error 'No such SWI' allows software dependent upon Econet to report its absence. Example code is given in the Application notes.

Related SWIs

None

Related vectors

None


Econet_ReadStationNumber
(SWI &4000F)

Extracts a station and/or net number from a supplied string

On entry

R1 = address of string to read

On exit

R1 = address of terminating space or control character
R2 = station number (-1 for not found)
R3 = net number (-1 for not found)

Interrupts

Interrupts are enabled
Fast interrupts are enabled

Processor mode

Processor is in SVC mode

Re-entrancy

SWI is re-entrant

Use

This call extracts a station and/or net number from a supplied string. For an example of its use, see the chapter entitled Extracting station numbers from a string.

Related SWIs

None

Related vectors

None


Econet_PrintBanner
(SWI &40010)

Prints the string 'Acorn Econet' followed by a newline

On entry

--

On exit

--

Interrupts

Interrupts are enabled
Fast interrupts are enabled

Processor mode

Processor is in SVC mode

Re-entrancy

SWI is not re-entrant

Use

This call prints the string 'Acorn Econet' followed by a newline. The string is fetched from a message file with the token 'AcrnEco'. If the Econet network data clock is not present then this call instead prints the string 'Acorn Econet, no clock' followed by a newline. In this case, the token used is 'EcoNClk'.

This call uses OS_Write0 and OS_NewLine, and so cannot be called from within either interrupt service code or event routines.

Related SWIs

None

Related vectors

None


Econet_ReadTransportType
(SWI &40011)

Returns the underlying transport type to a given station

On entry

R0 = station number
R1 = net number
R2 = 2

On exit

R0, R1 preserved
R2 = transport type (0 => NOT KNOWN_ 1 => INTERNET_ 2 => ECONET_ 3 => Nexus)

Interrupts

Interrupt status is unaltered
Fast interrupts are enabled

Processor mode

Processor is in SVC mode

Re-entrancy

SWI is re-entrant

Use

This call is used by clients to determine the underlying transport type to a given station. They can then use this information to determine the optimum transmission strategy to use, based on prior empirical knowledge of the different transport types.

This call is unnamed - but still available by number - in both RISC OS 2 and RISC OS 3 (version 3.00).

Related SWIs

None

Related vectors

None


Econet_ReleasePort
(SWI &40012)

Releases a port number that was previously claimed

On entry

R0 = port number

On exit

--

Interrupts

Interrupt status is unaltered
Fast interrupts are enabled

Processor mode

Processor is in SVC mode

Re-entrancy

SWI is re-entrant

Use

This call releases a port number that was previously claimed by calling Econet_ClaimPort.

You must not use this call for port numbers that have been previously claimed using Econet_AllocatePort; instead, you must call Econet_DeAllocatePort.

Related SWIs

Econet_ClaimPort

Related vectors

None


Econet_AllocatePort
(SWI &40013)

Allocates a unique port number

On entry

No parameters passed in registers

On exit

R0 = port number

Interrupts

Interrupt status is unaltered
Fast interrupts are enabled

Processor mode

Processor is in SVC mode

Re-entrancy

SWI is re-entrant

Use

This call allocates a unique port number that has not already been claimed or allocated.

When you have finished using the port number, you should call Econet_DeAllocatePort to make it available for use again.

Related SWIs

Econet_DeAllocatePort

Related vectors

None


Econet_DeAllocatePort
(SWI &40014)

Deallocates a port number that was previously allocated

On entry

R0 = port number

On exit

--

Interrupts

Interrupt status is unaltered
Fast interrupts are enabled

Processor mode

Processor is in SVC mode

Re-entrancy

SWI is re-entrant

Use

This call deallocates a port number that was previously allocated by calling Econet_AllocatePort.

You must not use this call for port numbers that have been previously claimed using Econet_ClaimPort; instead, you must call Econet_ReleasePort.

Related SWIs

Econet_AllocatePort

Related vectors

None


Econet_ClaimPort
(SWI &40015)

Claims a specific port number

On entry

R0 = port number

On exit

--

Interrupts

Interrupt status is unaltered
Fast interrupts are enabled

Processor mode

Processor is in SVC mode

Re-entrancy

SWI is re-entrant

Use

This call claims a specific port number. If it has already been claimed or allocated, an error is generated.

When you have finished using the port number, you should call Econet_ReleasePort to make it available for use again.

Related SWIs

Econet_ReleasePort

Related vectors

None


Econet_StartImmediate
(SWI &40016)

Creates a TxCB and starts an immediate operation

On entry

R0 = operation type
R1 = remote address or Procedure number
R2 = station number
R3 = net number
R4 = buffer address
R5 = buffer size in bytes
R6 = count
R7 = delay in centiseconds

On exit

R0 = handle
R1 corrupted
R2 = buffer address
R3 = station number
R4 = net number

Interrupts

Interrupts are disabled
Fast interrupts are enabled

Processor mode

Processor is in SVC mode

Re-entrancy

SWI is re-entrant

Use

This call creates a TxCB and starts an immediate operation. For full details see the chapter entitled Immediate operations.

The buffer must remain available all the time that the TxCB is open, as data transmitted over the Econet is read directly from the buffer to hardware. You must not use memory in application space if your program is to run under the Desktop. Instead, you should use memory from the RMA. To do so, claim the memory using OS_Module 6 (see OS_Module 6), and - after abandoning the transmit control block - return the space to the RMA using OS_Module 7 (see OS_Module 7).

The value returned in R4 (the net number) will be the same as that passed in R3 unless that number is equal to the local net number; in that case the net number will be returned as zero.

Related SWIs

Econet_DoImmediate

Related vectors

None


Econet_DoImmediate
(SWI &40017)

Creates a TxCB for an immediate operation, polls it, reads its status, and abandons it

On entry

R0 = operation type
R1 = remote address or procedure number
R2 = station number
R3 = net number
R4 = buffer address
R5 = buffer size in bytes
R6 = count
R7 = delay in centiseconds

On exit

R0 = status
R1 corrupted
R2 = buffer address
R3 = station number
R4 = net number

Interrupts

Interrupts are enabled
Fast interrupts are enabled

Processor mode

Processor is in SVC mode and in USR mode

Re-entrancy

SWI is re-entrant

Use

This call creates a TxCB for an immediate operation, and repeatedly polls it until it finishes transmission or it exceeds the count of retries. It then reads the final status of the TxCB before abandoning it. For full details see the chapter entitled Immediate operations.

The value returned in R4 (the net number) will be the same as that passed in R3 unless that number is equal to the local net number; in that case the net number will be returned as zero.

Note that because this interface enables interrupts it should not be called from within either interrupt service code or event routines.

During the loop when the polling of the TxCB and of Escape takes place, the processor is put in USR mode with IRQs enabled; this allows callbacks to occur.

Related SWIs

Econet_StartImmediate

Related vectors

None


Econet_AbandonAndReadReceive
(SWI &40018)

Abandons a reception and returns information about it, including the size of data

On entry

R0 = handle

On exit

R0 = status
R1 = 0, or flag byte if R0 = 9 (Status_Received) on exit
R2 = port number
R3 = station number
R4 = net number
R5 = buffer address
R6 = buffer size in bytes, or amount of data received if R0 = 9 on exit (Status_Received)

Interrupts

Interrupt status is unaltered
Fast interrupts are enabled

Processor mode

Processor is in SVC mode

Re-entrancy

SWI is re-entrant

Use

This call abandons an RxCB, returning its memory to the RMA. It also returns information about the reception; most importantly, it tells you how much data was received, if any, and the address of the buffer in which it was placed. The buffer address is the same as that passed to Econet_CreateReceive. You can call this SWI before a reception has occurred.

The status of the RxCB may be one of the following:

7 Status_RxReady
9 Status_Received

The returned values in R3 and R4 (the net and station numbers) are those of the transmitting station if the status is Status_Received; otherwise they are the same values that were passed in to Econet_CreateReceive.

This call is not available in RISC OS 2, nor in RISC OS 3 (version 3.00).

Related SWIs

Econet_CreateReceive, Econet_ReadReceive, Econet_AbandonReceive

Related vectors

None


Econet_Version
(SWI &40019)

Returns the version of software for the underlying transport to a given station

On entry

R0 = station number
R1 = net number

On exit

R0, R1 preserved
R2 = version number × 100 (eg 547 for version 5.47)

Interrupts

Interrupt status is unaltered
Fast interrupts are enabled

Processor mode

Processor is in SVC mode

Re-entrancy

SWI is re-entrant

Use

This call is used by clients to determine the version of software that handles the underlying transport to a given station. If both R0 and R1 are set to zero on entry, this call instead returns the version number of the top-level software to which RISC OS passes the Econet SWIs.

This call is not available in RISC OS 2, nor in RISC OS 3 (version 3.00).

Related SWIs

None

Related vectors

None


Econet_NetworkState
(SWI &4001A)

Returns the state of the underlying transport to a given station

On entry

R0 = station number
R1 = net number

On exit

R0, R1 preserved
R2 = transport state (0 => FULLY FUNCTIONAL_ 1 => no clock signal)

Interrupts

Interrupt status is unaltered
Fast interrupts are enabled

Processor mode

Processor is in SVC mode

Re-entrancy

SWI is re-entrant

Use

This call returns the state of the underlying transport to a given station. The state returned is transport type dependent, but you may always assume that a value of zero means that the transport is fully functional.

You should only use the returned value as a hint to the exact state; in other words, it is suitable for display but not for decision making. Using this call is no substitute for proper error handling; to determine if a particular transmit will fail, you must do the transmit and be prepared for it to fail.

Related SWIs

Econet_PrintBanner

Related vectors

None


Econet_PacketSize
(SWI &4001B)

Returns the maximum packet size recommended on the underlying transport to a given station

On entry

R0 = station number
R1 = net number

On exit

R0, R1 preserved
R2 = maximum permitted packet size, in bytes

Interrupts

Interrupt status is unaltered
Fast interrupts are enabled

Processor mode

Processor is in SVC mode

Re-entrancy

SWI is re-entrant

Use

This call returns the maximum recommended packet size on the underlying transport to a given station. Larger packets will not necessarily be rejected, but their use is not recommended. The size returned is transport type dependent.

This call is intended for use by modules supplying protocols; you do not need to use it in application software. For maximum efficiency the protocol module should negotiate the packet size once. Since the recommended packet size may differ between the stations at either end of a transmission, the protocol module should interrogate both stations and take the lower value returned.

Related SWIs

None

Related vectors

None


Econet_ReadTransportName
(SWI &4001C)

Returns the name of the underlying transport to a given station

On entry

R0 = station number
R1 = net number

On exit

R0, R1 preserved
R2 = pointer to null terminated name of transport

Interrupts

Interrupt status is unaltered
Fast interrupts are enabled

Processor mode

Processor is in SVC mode

Re-entrancy

SWI is re-entrant

Use

This call returns the name of the underlying transport to a given station. You can use this to insert the transport name into (for example) a status conversion.

Related SWIs

None

Related vectors

None

* Commands

The only * Command the Econet module responds to is *Help Station, which displays the current net and station numbers of the machine. It also displays a 'No clock' message if applicable. For more details of the *Help command, see *Help.

Application notes

The following code is the preferred way of testing for the presence of the Econet drivers. It calls the SWI Econet_SetProtection with R0 and R1 set such that the call attempts to read the Econet protection word; doing so can never return an unexpected error. Detecting the error 'No such SWI' allows software dependent upon Econet to report its absence by generating an error; note the use of MessageTrans to do so:

        STMFD   sp!, {r0-r7,lr}
        MOV     r0, #0
        MVN     r1, #0
        SWI     XEconet_SetProtection
        BVC     ExitFindEconet
        LDR     r2, ErrorNumber_NoSuchSWI
        LDR     r0, [r0]
        TEQ     r0, r2
        BNE     ExitFindEconet
        ADR     r0, Error_NoEconet
        MOV     r1, #0                  ; No message file - use global
        MOV     r2, #0                  ; No buffer - use internal one
        MOV     r3, #0
        MOV     r4, #0                  ; No parameters
        MOV     r5, #0
        MOV     r6, #0
        MOV     r7, #0
        SWI     XMessageTrans_ErrorLookup
ExitFindEconet
        STRVS   r0, [sp,#0]
        LDMFD   sp!, {r0-r7,pc}
ErrorNumber_NoSuchSWI
        DCD     &000001E6
Error_NoEconet
        DCD     &00000312
        DCB     "NoEco", 0