Registering the task-time level of a block device
Use the
bdistributed(D3oddi)
function to register the task-time level of a block driver
as multithreaded.
The initialization routine must also determine
whether the hardware configuration allows
all processors to access the I/O bus and,
if not, allocate an interprocessor interrupt
that will be used to access the correct
start( )
routine in the driver's
strategy( )
routine (see
``Modifying the strategy routine'').
See the
idistributed(D3oddi)
manual page for examples of how to register
the driver as level-two multithreaded.
Multithreaded init routine for block driver
1 int xxhandle = -1;
2 xxinit()
3 {
4 ...
5 if (all_io(MP_ATBUS))
6 bdistributed(xxstrategy, DIST_BDEV_STRATEGY);
7 else if (xxhandle == -1) {
8 xxhandle = intralloc(&lock_xxtab, xxstart);
9 if (xxhandle == -1)
10 cmn_err(CE_WARN, "xxinit: Multiprocessor access denied");
11 else
12 bdistributed(xxstrategy, DIST_BDEV_STRATEGY);
13 }
14 ...
15 }
line 1-
The xxhandle variable describes the stored address of the
start( )
routine that will be used by
startio(D3oddi).
startio is called to run the
start( )
routine
from the default processor
when the current processor cannot access the I/O bus.
line 5-
calls
all_io(D3oddi)
to determine if all the processors can
access the AT bus.
all_io( )
takes one argument that specifies the bus type;
these are defined in the <sys/ci/cidriver.h> header file.
The recommended policy is for the driver to pass the most common
bus type to
all_io( ).
For example, if a controller works
on both the AT-bus and the EISA bus, the driver
should pass MP_ATBUS rather than MP_EISABUS.
all_io( )
returns TRUE if all processors on the system can
perform I/O (to or from a device) on the specified bus.
TRUE will also be returned on uniprocessor systems.
The driver does not have to know on which type of platform it is running;
the kernel support routines handle all of the operations at that level.
line 6-
If
all_io(D3oddi)
returns TRUE,
bdistributed(D3oddi)
is called to notify the kernel
that the driver can be accessed by more than one processor.
The first argument to
bdistributed( )
specifies the name of the driver's
strategy( )
routine in the block device switch table,
bdevsw[].
The second argument specifies flags for I/O operations.
This value must include DIST_BDEV_STRATEGY;
other values defined in the
<sys/conf.h> header file
may be ORed with it.
The flags are stored
in an array associated with bdevsw[].
If the driver is a SCSI host adapter,
it must also call the
scsi_distributed(D3osdi)
function:
{
...
if (all_io(MP_ATBUS)) {
bdistributed(xxstrategy, DIST_BDEV_STRATEGY);
scsi_distributed(ad_entry);
...
}
}
SCSI drivers are discussed in SCSI Driver Interface.
lines 7-8-
If the system is one in which not all of the processors have
I/O access,
all_io(D3oddi)
will return FALSE.
In this case, the driver calls
intralloc(D3oddi)
to allocate an interprocessor interrupt so that when
startio(D3oddi)
is called, the correct routine is called.
line 9-
The xxhandle
variable (declared in line 1) provides a handle on a structure
describing the address and lock of the
start( )
routine.
If a processor needs to access the
I/O bus but cannot (see the
all_io(D3oddi)
manual page),
startio(D3oddi)
is called.
startio( )
interrupts a processor
that can access the I/O bus,
and instructs it to initiate I/O
for the driver by locking the lock specified by
intralloc(D3oddi)
and running the
start( )
routine passed to
intralloc(D3oddi).
line 10-
If the call to
intralloc( )
fails, a message should be displayed to indicate
that the driver will not be operating in multiprocessor mode.
lines 11-12-
If the call to
intralloc( )
succeeds,
bdistributed(D3oddi)
is called.
© 2005 The SCO Group, Inc. All rights reserved.