Asynchronous Printing

Some CODs may be implemented in such a way that it is possible to start printing when the function prn_print() is called, but for the printing not to have completed when this function returns. Support for this type of output is provided as follows.

The size of the pdesc[] array supplied by your user exit code should be greater than one. The number of elements in this array equals the maximum number possible of asynchronous print items. Whenever a line of text arrives to be printed, the OSDI code will select an entry from this array which does not have the busy flag set, fill it in and pass its index to prn_print().

If prn_print() returns 1 it is assumed that the line has been printed, and the OSDI will automatically reset the busy flag so that the pdesc[] entry can be re-used. If prn_print() returns 0 it is assumed that printing has started but not yet completed. The busy flag remains set and the pdesc[] entry is added to a linked list of pending print commands. All you have to do is ensure that 0 or 1 are returned appropriately. The OSDI will manage the buffer pointers and flags in the pdesc array for you.

The function prn_complete() is supplied in the OSDI. Your code must call this function when a print event has completed. Its argument is the index into the pdesc array for which printing is complete. You should periodically check whether any outstanding members of the pdesc array have completed their printing. It is sensible to do this within the code of inp_task(), as this routine is repeatedly called by the OSDI.

How you achieve this depends on the nature of your asynchronous output.

It is useful to arrange that the completion of printing wakes up the inp_task() function; for example, under FlexOS the asynchronous printing function could return an event mask for which inp_idle() will wait. inp_idle() actually waits on any event under FlexOS before returning. You can therefore set up an event mask when printing starts. This will be checked by inp_idle() thereby ensuring that inp_task() is called when the printing completes.

The code of inp_task() should search through the linked list of pending print commands. When it discovers one which has completed, it should call the function prn_complete(), passing as an argument the index of the pdesc[] entry which has finished. The prn_complete() function will reset the busy flag and remove the

pdesc[] entry from the linked list for you.

The start of the linked list of pdesc[] entries is the global variable busy_pdesc. This is the index in the pdesc[] array of the first entry in the list, or -1 if the list is empty. The field next in a pdesc[] array member contains the index of the next entry in the list, or -1 if it is the end of the list. Using indexes rather than pointers has the advantage that you may use the same indexes to index into any other array of control variables which the application code needs to maintain: see the sample code on the release disk for an example of how this can be done.

New entries to the linked list are always added at the end, so the order of the list is the same as the order in which the entries were submitted for printing. A new entry is always added to the list before the call to prn_print() (and is removed immediately afterwards if this function returns 1) so it is possible for prn_print() to re-arrange the order of the list so that the new entry appears in a different place. This might be useful if it is desired to vary the order of printing, for example in order to optimise printer head movement. Other than this, the linked list and the busy flags should not be touched by your code.

If the application wishes to print and all the pdesc[] entries are busy, the application will wait until one becomes available. You do not need to handle this contingency in your own code.

If the text to be printed is no longer required to be kept in memory after the prn_print() function has returned, then all the entries in the pdesc[] array can share a common data area for their 'text' pointers. More usually it will be necessary for the text to be kept untouched until the printing has finished, in which case each pdesc[] member must be provided with its own text buffer.

There will usually be a requirement for the application to wait at a certain point until all the asynchronous printing has completed. This can be achieved by having a (synchronous) COD which simply waits (typically in prn_select() or prn_parameter()) until the linked list of pending print commands has become empty. This waiting code must of course poll the status of the pending commands and call prn_complete() whenever one finishes; it should call inp_idle() in order to wait for an event.