Buffer Manager

The buffer manager provides a global buffer managing system, it provides a set of calls for setting up a buffer, inserting and removing data from a buffer and finally removing a buffer. It is also possible to setup an area of memory to be used as a buffer.

The buffer manager extends the INSV, REMV and CNPV to provide access to these buffers and also allow block transfers.

The buffer manager is used by DeviceFS to provide buffers for the various devices that can be accessed. A device may be linked to a buffer supply routines to be called when data enters the buffer and also a routine to be called when a buffer is removed (or a new device is attached).

When registering or creating a buffer it is possible to force a specific buffer handle, if this feature is not used then the manager will assign a unique handle to it. It should be noted that buffer handles are no longer stored as eight bit quanities.

Block transfers are signalled by setting bit 31 of the buffer handle, anything which can be performed on a byte by byte basis can also be performed on a block, eg. examine the buffer contents.

SWI interface

Buffer_Create

in: r0 = flags for the buffer

                bit  0 =0 => buffer is dormant and should be woken up when
                              data enters it
                bit  1 =1 => buffer generates "output buffer empty" events
                bit  2 =1 => buffer generates "input buffer full" events
                bit  3 =1 => buffer generates upcalls when free space
                              threshold crossed (from above or below)
                bits 4-31    reserved for future expansion, should be set
                              to zero on creation
        r1  = size of buffer to be created
        r2  = buffer handle to assign to buffer, -1 for does not matter

out: V =0 => r0 = buffer handle

        V =1 => r0 -> error block

This routine claims an area of memory from the RMA and links it into the buffer list, if r2 =-1 then the buffer manager will attempt to find a unique handle, if r2 <>-1 then the buffer manager will check that the handle specified is unique and then if it is assign it to that buffer.

The flags word is used to indicate what should happen when data is being inserted and removed from the buffer.

Bit 0 is used to indicate if the device attached to the buffer has been woken up, when =0 then the device is dormant and needs to be woken. When a device is attached and data is put into the buffer this bit is checked, if it is =0 then the wake up code for the device will be called allowing any device to wake up any hardware it may be driving and to start processing data within the buffer.

Bit 1 is used to indicate if "output buffer empty" events should be issued for this buffer.

Bit 2 is used to indicate if "input buffer full" events should be issued for this buffer.

Bit 3 is used to indicate if buffer threshold UpCalls should be issued for this buffer.

On exit r0 contains the buffer handle being used or a pointer to an error block.

Buffer_Remove

in: r0 = handle of buffer to be removed

out: V =1 => r0 -> error block, else preserved

This call should only be made on buffers created using Buffer_Create.

It attempts to de-register the buffer from the active list and assuming that worked ok it will attempt to free the memory relating to that buffer.

Buffer_Register

in: r0 = flags for buffer (see above)

        r1 -> start of memory for buffer
        r2 -> end of buffer (+1)
        r3  = handle to be assigned to buffer (-1 if to be generated)

out: V =0 => r0 = handle for buffer

        V =1 => r0 -> error block

This call registers an area of memory as a buffer, the routine accepts similar parameters to the Buffer_Create SWI, but instead of the call claiming tha area of memory for you, you must actually specify the buffer's start and end addresses.

It is not advisable to put buffers in application workspace, this area of memory can be switched out when someone else tries to access it. It is however possible for your task if it is going to be the only one using this buffer, and it will only be accessed whilst the task is currently paged in to register a buffer within its workspace.

For further details about the flags word and the specified buffer handle see the Buffer_Create call.

Buffer_Deregister

in: r0 = handle of buffer to be deregistered.

out: V =0 => all preserved.

        V =1 => r0 -> error block.

This call will simply unlink a buffer from the active list, the data within the buffer will be purged and any access to this buffer via INSV, REMV and CNPV will be ignored.

Do not use this call if you have created the buffer using Buffer_Create, instead use Buffer_Remove which releases any memory that may have been claimed.

Buffer_ModifyFlags

in: r0 = handle of buffer to be modified

        r1  = EOR mask
        r2  = AND mask

out: r1 = old value

        r2  = new value

This call allows you to modify the flags word stored with each buffer, the SWI allows two registers to be ANDed and then EORed with the current flags word, on exit the old and new values of this word are returned to the caller.

r1, r2 are applied as follows:

        new = (old AND r2) EOR r1

The caller should not modify reserved flag bits when issuing this call, ie bits 4 to 31 should be set in r2 and clear in r1.

Buffer_LinkDevice

in: r0 = buffer handle,

        r1 -> code to wake up device when needed      (0 => none)
        r2 -> code to call when device to be detached (0 => cannot be
detached)
        r3  = private word to be passed in
        r4 -> workspace for above routines

out: V =1 => r0 -> error block, else all preserved.

This call links a set of routines to the specified device, the caller supplies two routines, one to be called when data enters the buffer and another to be called when someone else attempts to link to the buffer.

r1 contains a pointer to the routine to be called when data enters the buffer and it is currently marked dormant, the routine can be entered in any mode and with FIQs or IRQs enabled / disabled, the mode should be preserved as should the interrupt state.

The registers to the wake up code are setup as follows:

in: r0 = buffer handle

        r8   = private word          (specified in r3 in SWI Buffer_LinkDevice)
        r12 -> workspace for routine (specified in r4 in SWI Buffer_LinkDevice)

out: all should be preserved, including PSR.

The buffer manager automatically marks the buffer as active (non-dormant) before calling the wake up code.

If the caller to Buffer_LinkDevice specifies a routine pointer equal to zero then no wake up call is made.

The second routine supplied is a routine to be called whenever the owner of the buffer is about to change; if this value is zero then the device is indicating that the owner can never be changed and changing it will result in an error.

The routine if supplied gets called as follows:

in: r0 = buffer handle

        r8   = private word
        r12 -> workspace for the calls

out: V =1 => r0 -> error block

        V =0 => all preserved

On return from this routine the routine can return an error, any errors returned halt the detach process. The detach routines are called when someone attempts to kill the buffer manager module, this results in an error and the buffer manager refuses to die.

When attaching to a buffer it is possible that the SWI will fail, this is likely to be because the current owner is refusing to detach itself.

Buffer_UnlinkDevice

in: r0 = buffer handle

out: V =0 => all preserved and device detached.

        V =1 => r0 -> error block.

This routine will unlink a device from a buffer, no warning if given of the detach and the data that is currently stored within the buffer is purged.

This call should only be used by the actual device that called Buffer_LinkDevice, anyone else calling this SWI could confuse the system.

Buffer_GetInfo

in: r0 = buffer handle

out: V =1 => r0 -> error block

        V =0 => r0  = flags relating to buffer
                r1 -> start of buffer in memory
                r2 -> end of buffer in memory (+1)
                r3  = insert index for buffer
                r4  = remove index for buffer
                r5  = remaining free space in buffer
                r6  = number of characters in buffer

This call returns data about the buffer, its position in memory, flags, insert and remove offsets and the amount of free space.

Buffer_Threshold

in: r0 = buffer handle

        r1  = threshold / 0 none / -1 to read

out: r1 = previous value

This call is used to set/read the warning threshold of the buffer. This is used to trigger UpCalls if bit 3 of the buffer flags is set.

The UpCalls are issued when the amount of free space in the buffer crosses the threshold value (see the UpCalls section below)

Vector calls

The SWIs for the buffer manager module allow you to modify and tinker with the actual buffer itself, they do not however supply a way of inserting and removing data from these buffers.

Extensions have been made to the three vectors; InsV, RemV and CnpV to handle the inserting and removing of data from the buffers, these calls have also been extended to allow block inserts.

For compatibility marking a block operation is done by setting bit 31 of the buffer handle. This changes the specification for calling these vectors as follows:

InsV

in: r0 = byte to be inserted

        r1  = buffer handle (bit 31 is clear)

out: r0, r1 preserved

        r2 corrupt

or:-

in: r1 = buffer handle (bit 31 is set)

        r2 -> first byte of data to be inserted
        r3  = number of bytes to insert

out: r0, r1 preserved

        r2 -> remaining data to be inserted
        r3  = number of bytes still to be inserted

On both calls C is used to indicate if the insertion failed, if C=1 then it was not possible to insert all the specified data, or the specified byte.

RemV

in: r1 = buffer handle (bit 31 clear)

out: r0 = next byte to be removed (for examine only)

        r1  = preserved
        r2  = byte removed (for remove only)

or:-

in: r1 = buffer handle (bit 31 set)

        r2 -> buffer to be filled
        r3  = number of bytes to place into buffer

out: r0, r1 preserved

        r2 -> updated buffer position
        r3  = number of bytes still to be removed

On both of the above calls V =1 on entry indicates that the data should be copied out (examine) and V =0 indicates that the data should actually be removed.

On exit C is used to indicate if the calls actually worked and if a byte or the requested block of data could be obtained.

CnpV

Unchanged, except it copes with buffer manager buffers.

Events

With the changes required to InsV, RemV and CnpV calls to cope with the new buffers and block transfers some of the events have been extended to cope with indicating that a block transfer occurred.

For further details of the events and when they are generated consult the PRM, as this remains unchanged.

Event_OutputEmpty

in: r0 = Event_OutputEmpty (0)

        r1  = buffer handle

out: all preserved.

This is issued when the last character is removed from a buffer which has output empty events enabled (see description of buffer flags).

Event_InputFull

in: r0 = Event_InputFull (1)

        r1  = buffer handle (bit 31 clear)
        r2  = character not inserted
or:-
r0 = Event_InputFull (1)
r1 = buffer handle (bit 31 set)
r2 -> data not inserted
        r3  = number of bytes not inserted

out: all preserved.

This event is generated when a character or block is inserted into a buffer which has input full events enabled (see description of buffer flags), and the insertion failed.

Service calls

Service_BufferStarting (&6F)


in: r1 = Service_BufferStarting (&6F)

out: all preserved.

This call is passed around after the module has been initialised or reset. It allows module which wish to register buffers with the buffer manager to do so.

When the service is received all SWIs are valid.

UpCalls

UpCall_BufferFilling (8)

in: r0 = 8
r1 = Buffer handle
        r2  = 0

out: -

This is issued when data is inserted into the buffer and the free space becomes less than the specified threshold.

UpCall_BufferEmptying (9)

in: r0 = 9
r1 = Buffer handle
        r2  = -1

out: -

This is issued when data is removed from the buffer and the free space becomes greater than or equal to the current threshold.