[comp.sys.apollo] locking object info physical memory

krowitz@RICHTER.MIT.EDU.UUCP (05/13/88)

I'm writing a device driver for a printer that has a high data
rate and no internal buffer. In order to send the data to the
printer at a high-enough rate, I format the entire page in a
buffer (a Pascal array) before starting the data transfer. The
problem I'm having is that the buffer is large (up to 2 MB) and
the virtual memory system pages the buffer out to the disk as I
fill it with the data -- when I begin the data tranfer I most of
the buffer is out on the disk, and the page faulting needed to
bring it back into physical memory interrupt the transfer of the
data to the printer which, in turn, leaves horizontal streaks
across the page at the places where the data transfer got interrupted.

Here's my question: is there some way of locking an array, or some
arbitrary piece of address space, into *physical* memory? The
MS_$ calls and RWS_$ calls talk about mapping things into the
*virtual* address space and talk about "locks", but these seems
to be locks on the access to the object. No mention is made of
physical vs. virtual memory. Does anyone have an info which
could help me on this?


 -- David Krowitz

krowitz@richter.mit.edu   (18.83.0.109)
krowitz%richter@eddie.mit.edu
krowitz%richter@athena.mit.edu
krowitz%richter.mit.edu@mitvma.bitnet
(in order of decreasing preference)

ced@apollo.uucp (Carl Davidson) (05/15/88)

From article <8805122134.AA04356@richter.mit.edu>, by krowitz@RICHTER.MIT.EDU (David Krowitz):
> I'm writing a device driver for a printer ...
> ... [text deleted]
> Here's my question: is there some way of locking an array, or some
> arbitrary piece of address space, into *physical* memory? ...
> ... [more text deleted]

Yes, but it's not pretty. You can use the "pbu[2]_$wire" calls (there are actually tow calls,
pbu_$wire and pbu2_$wire).

These calls are declared like this (in the Pascal insert files):

PROCEDURE pbu2_$wire (                      { wire an I/O buffer }
            IN  unit : pbu_$unit_t;         { unit number }
            IN  buffer : UNIV pbu_$buffer_t;{ buffer to be wired }
            IN  length : linteger;          { length of buffer (in bytes) }
            OUT status : status_$t          { returned status }
            ) ; EXTERN;

		(In pbu_$wire, the length parameter is 2 bytes instead of 4)

To be able to use these calls, your process must have acquired a pbu device (i.e., a device in the
peripheral bus).  If you don't, the error "unit in use" will be returned.  In cases like yours (it 
sounds like you are really writing a printer driver, not a device driver), you have to go out of 
your way to do this.

What you must do is write a dummy GPIO device driver consisting of a do-nothing initialization routine
nd a do-nothing cleanup routine.  Then specify an unused pbu unit number in the DDF (device descriptor
file) for your dummy device.  Finally, in your print driver, use "pbu_$acquire" to initialize the dummy
device driver prior to trying to wire any buffers with pbu2_$acquire.  Also be sure to call
pbu_$release prior to terminating the print driver.  See the Apollo manual "Writing Device Drivers with
GPI/O Calls", Order NO. 959, for details on the above steps.


If you are actually writing a GPIO device driver, then you will already have a GPIO unit number
allocated.  Then all you have to do is call the appropriate call. I recommend that you always use
"pbu2_$wire", for simplicity's sake (it lets you wire larger buffers).

Hope this helps!
-- 
--Carl Davidson                                 "Science is what you do
  Apollo Computer Inc.                           after  you  guess well."
  Chelmsford, MA 01824                 
  {decvax,mit-eddie,umix}!apollo!ced