|
This Technote describes how to
write a device driver for an ATA host bus controller, known
as an ATA Interface Module, or AIM. An AIM is the ATA
equivalent of the SCSI Interface Module (SIM). It does not
control a device on the ATA bus, but implements a standard
hardware abstraction for the bus itself.
AIMs operate at the very lowest level of the traditional
Mac OS I/O subsystem, which makes them hard to write and
hard to debug. Only experienced Mac OS device driver writers
should consider developing an AIM.
This Note is directed at developers of ATA host bus
controller cards (typically PCI or CardBus).
Updated: [Dec 06 1999]
|
Introduction
This technote describes how to write a Mac OS device
driver for ATA host bus controller hardware. Such a driver
is known as an ATA Interface Module, or AIM. In some
respects it is the ATA equivalent to the more commonly known
SCSI Interface Module (SIM).
This technote is divided into two sections. This section,
and the Core Concepts sections
which follows it, represent the introductory material. They
describe high-level issues with writing AIMs; understanding
these sections is critical to writing a reliable AIM. The
remaining sections are reference material. They describe how
you can register an ATA
bus with ATA Manager, how you should
package your AIM so that it is
recognized by ATA Manager, what
entry points ATA Manager
expects you AIM to implement, the list of
function codes your
AIM's action routine must support, and some
support routines that ATA
Manager exports to support AIM implementation.
IMPORTANT:
AIMs are only supported by ATA Manager 4.0 and
above. Development of third-party ATA buses is not
supported on older versions of ATA Manager. Device
0/1 support is not available on some early ATA
Manager 4.0 systems; however, your AIM should always
support device 0/1 operations.
|
Before You Begin
Before you consider developing an AIM, you should be
familiar with the following concepts:
You will also need the following:
- "ATA.h" from the latest version of Universal Headers.
- If that version of "ATA.h" does not include the
AIM-related declarations described in this technote, you
will need the "ATAExtras.h" header file that is
included with this technote.
[2404935]
- Similarly, if the libraries included with Universal
Headers does not include ATAManager stub library, you
will need the one included here.
- Information about your bus controller from your
hardware vendor.
Back to top
Core Concepts
Before starting your AIM, you should be familiar with
some fundamental concepts, as described in the following
sections.
Theory of Operation
AIMs represent an abstraction of an ATA bus. Your AIM
isolates the ATA Manager and its clients from the
specific details of your ATA bus controller hardware. For
instance, an ATA bus may be part of a PC Card slot, or
perhaps reside on a PCI card, or may even be integrated as
part of a system chipset. Each physical ATA controller will
have specific requirements for how it is addressed, what
cycle times are supported and how they are programmed, how
interrupts from the controller are routed to the system, and
so on. By bundling the hardware-specific details of the ATA
controller in a plug-in software module, the ATA Manager
presents a consistent interface for drivers and applications
to communicate with ATA and ATAPI devices.
All of the operations which directly touch the hardware
in any manner are handled by your AIM. This includes:
- describing the features of the bus controller,
primarily the supported I/O
modes and cycle times, and controlling those features
- preparing physical DMA transfer buffers and building
DMA programs for those buffers
- alignment issues
- reading and writing the device's task file registers
- writing ATAPI command packets
- handling ATA and ATAPI transfer operations
- servicing hardware interrupts
- timing out failed bus transactions
- resetting the bus
Current versions of ATA Manager will only dispatch a
single request for a single device on the bus controlled by
your AIM at any given time. Overlapped ATA/ATAPI features
are not currently supported. AIMs written to the
specification in this document will never be expected to
handle concurrent requests.
In general, your AIM should be interrupt-driven. It
should do as much work as it can on a request, then return
to the ATA Manager pending an interrupt from the hardware.
For instance, when you receive a request to read data, you
would set your AIM's internal flags as needed, write the
task file to the device, and then return to ATA Manager.
When the device is ready to transfer data, it will assert an
interrupt which will call your AIM's hardware interrupt
handler. Your AIM would then call
ATAFamBusEventForAIM
to queue a secondary handler and return from the hardware
interrupt handler. ATA Manager will then call your AIM's
MyHandleBusEvent
function where you would complete the data transfer, clear
your AIM's internal flags, and call
ATAFamIODone . It is
important that all your cleanup be done before calling
ATAFamIODone , because ATA Manager may call you
with another request during ATAFamIODone . Also,
your AIM's MyHandleBusEvent function may be
called immediately when calling
ATAFamBusEventForAIM . Other than these two
cases, the AIM will not be called reentrantly.
There are some limits on the controller hardware that can
be supported by an AIM:
- Each ATA bus must be capable of simultaneous
operation, independent of any other ATA bus. If an ATA
controller chip implements two bus controllers, but they
share common wiring or a DMA engine such that only one
bus can be active at a time, then only one bus may be
supported under ATA Manager. ATA Manager has no
synchronization mechanism between buses.
- ATA controllers incapable of generating interrupts
are not supported.
- PCI ATA controllers which operate only in x86 "legacy
mode" (that is, they hard-decode only the lower-address
bits and cannot be relocated in PCI space) are not
supported. However, it is possible to support addressing
the controller in either memory or PCI I/O space.
Global Variables
Your AIM should allocate its per-bus global variables in
a memory block (typically allocated use
PoolAllocateResident ) and use ATA Manager's
per-AIM refCon facility to track its globals.
The reason to use the refCon (rather than C
extern and static variables, which
are stored in your fragment's data section) is that the ATA
Manager has a facility to update your AIM to a newer version
"on the fly." The process,
described below, involves
closing the CFM connection to the older version of your AIM
and replacing it with a connection to the newer version. If
you had important data in the older AIM's data section, that
data is lost when the data section is disposed as part of
closing the CFM connection. In contrast, ATA Manager
explicitly passes the refCon to the new version
of your AIM.
Note:
An AIM is a native driver ('ndrv' ) and
shares many of the properties of native drivers in
general. One of these properties is that your AIM
is instantiated once for each instance of your ATA
hardware on the machine (technically, one per ATA
node in the Name Registry). Therefore you can store
per-bus global variables in your data section, and
you will automatically get one copy of these global
variables per bus. |
However, you should avoid using this strategy
for per-bus global variables for the reason
described above.
It is acceptable to use your data section for
global variables as long as you have a strategy for
passing them between versions. You could, for
example, store the data primarily in you data
section, push it into the AIM's refCon
memory block when your AIM is suspended, and
restore it to your data section when your AIM is
resumed. Or you might choose to pass data between
versions of your AIM via Name Registry properties.
However, both of these techniques are significantly
more convoluted than using the AIM's
refCon , hence the recommendation to
just use the refCon approach.
Regardless of how you allocate your global variables, you
must ensure that they are held resident in memory (in the
virtual memory sense). All of the techniques described above
guarantee this.
Finally, your AIM should use PowerPC structure alignment
for its global variables. This has two advantages:
- If you do atomic operations on a global variable,
PowerPC alignment ensures that the variable is aligned
appropriate.
- PowerPC alignment yields better performance for
native code than 68K alignment.
AIM Update Process
As mentioned above, the ATA Manager has a process for
updating your AIM to a newer version "on the fly," without
shutting the bus down. The ATA Manager accomplishes this in
a 7 step process:
- Open a CFM connection to the new AIM
- Wait for all pending AIM requests to terminate
- Block any new AIM requests from starting
- Call the old AIM's suspend routine
(
MyAIMSuspend )
- Call the new AIM's resume routine
(
MyAIMResume ),
passing it the refCon from the old AIM
- Unblock the AIM to allow bus operations to continue
- Close the CFM connection to the old AIM
There are a number of important things about this process to keep in mind.
- The ATA Manager finds replacement AIMs by matching
the Name Registry node name to the
nameInfoStr field of the
DriverType structure of its
driver description.
In order for your AIM to be updated, these names much
match exactly.
- In addition, the ATA Manager will only update an AIM
if the
version field of the
DriverType structure of its
driver description is
newer than the version of the existing AIM.
- You must structure your per-bus globals such that
they can be passed from one version of your AIM to the
next. Some suggested techniques are:
- Using your AIM's
refCon to store a
pointer to your per-bus storage simplifies the process
of passing this information between versions. See the
previous section for
more details.
- Put the version number of your AIM in your per-bus
storage so that the newer AIM knows which older
version it is taking over from (and can compensate for
known bugs, oversights, and so on).
- Include some "reserved" fields in your per-bus
storage to give future versions of your AIM some room
for expansion.
- You can also use Name Registry properties to pass
information between versions of your AIM.
- AIM resume routines are not defined to return an
error code. You should design your AIM so that its resume
routine cannot fail.
AIM
Synchronization Model
As long as you follow one simple rule, the ATA Manager
takes care of most of the synchronization problems in
writing an AIM. The rule is:
Note:
When your AIM is called by anyone other than
ATA Manager, you must synchronize with ATA Manager by
posting a bus event. |
Posting a bus event
(ATAFamBusEventForAIM )
is a the way your AIM informs ATA Manager that its bus event
handler
(MyAIMHandleBusEvent )
should be called. ATA Manager queues the bus event and
eventually calls the bus event handler when it is safe to do
so.
If you follow this rule, ATA Manager guarantees that it
will never call your AIM on more than one thread of
execution at a time. So as long as you're executing within
the context of a routine that is called by ATA Manager, you
can access global variables without worrying about
synchronization issues.
An obvious example of where this is useful is for
handling interrupts. As a rule, your AIM will service I/O
requests as a state machine. When ATA Manager calls your AIM
to start a request
(MyAIMAction ), your
AIM will start an asynchronous I/O operation and then return
to ATA Manager. When the asynchronous operation completes,
your hardware will interrupt the processor, and system
software will execute your interrupt service routine. This
interrupt service routine executes at hardware interrupt
time. If you access your global variables from it, you must
worry about synchronizing that access with lower execution
levels. The solution is for your AIM to post a bus event.
ATA Manager will defer calling your bus event handler
(MyAIMHandleBusEvent )
until it can guarantee that it is the only thread of
execution running inside your AIM. Your bus event handler
can therefore safely access global variables without
worrying about synchronization.
IMPORTANT:
Your interrupt service routine must perform the
following tasks as quickly as possible:
|
- Identify the source of the interrupt.
- If the interrupt is from your device, clear
the source of the interrupt and post a bus
event.
The bulk of the work in handling an interrupt
should be done in your bus event handler.
If your AIM's hardware is hosted on a PCI bus,
you must be sure to handle hardware interrupts in
an expansion chassis friendly fashion. See DTS
Technote 1135
Dealing
with PCI Expansion Chassis Problems for
details.
Controllers which contain two ATA buses which
share a single PCI interrupt must extend the
interrupt source tree so that each ATA bus has a
separate interrupt node. Typically this is done in
your AIM's initialization
routine.
A less obvious example of the use of bus events is to
handle timeouts. If your AIM implements timeouts using the
system timer service (SetInterruptTimer ), the
timer routine will be executed at hardware interrupt time.
Your AIM can avoid synchronization problems by posting this
event as a bus event as well.
Note:
ATA Manager uses the bus event mechanism to both
guarantee synchronization and to defer the
processing of bus events until interrupts are
enabled (by way of a secondary interrupt). You
should not rely on ATA Manager's use of secondary
interrupts. Older versions of ATA Manager
implemented this using a deferred task, and the
implementation might change again in the future. |
In addition to guaranteeing that only one thread of
execution can be running inside your AIM at any point in
time, the ATA Manager also guarantees to dispatch only a
single request to your AIM at a time. Between the point when
ATA Manager dispatches a request (by calling
MyAIMAction ) and the
point when your AIM completes it (by calling
ATAFamIODone ), ATA
Manager will not dispatch any further requests to your AIM.
Instead, it will queue these requests on its internal
queues. This "one request at a time" guarantee is in
recognition of the fact that the ATA bus architecture does
not support parallel overlapped requests and that, by
guaranteeing this, ATA Manager simplifies your life.
Both of the synchronization guarantees described in this
section are defined on a bus-by-bus basis. If your AIM is
multiply instantiated on the system, and those instances
share common data, you must be careful to synchronize access
to that common data.
Finally, ATA Manager also handles enabling and disabling
of user code (in the virtual memory sense) for you. Readers
who are familiar with SIMs (the equivalent to AIMs for SCSI
buses) know that they are required to call
EnteringSIM and ExitingSIM
whenever they enter or leave the SIM. AIM developers are not
required to jump through that particular hoop because the
ATA Manager knows when non-reentrant portions of the AIM are
executing (because the non-reentrant parts of the AIM are
always executed as a result of the ATA Manager calling the
AIM) and so it can enable and disable user code
appropriately.
ATA I/O Modes
This section explains one of the trickier aspects of the
ATA Manager's API for setting transfer modes and timings. In
addition to the discussion here, you should read the
ATA
Device Software for Macintosh Computers (and its errata,
DTS Technote 1098
ATA
Device Software Guide Additions and Corrections)
carefully to fully understand how ATA client software
expects your AIM to handle transfer modes and timings.
Prior to ATA Manager 3.0, which was the first version of
the ATA Manager to support DMA transfers, transfer modes
were specified as absolute numbers. Thus, a value of 2 for a
transfer mode meant PIO mode 2. Starting with ATA Manager
3.0, transfer modes were specified as bitmaps. Thus a value
of 1 meant transfer mode 0, a value of 2 meant transfer mode
1, and so on. The ataModeType field of the
ATAReqBlock determines which mode this request
is in.
This is important to remember when trying to establish
the correct timing mode on the ATA bus. For example, the
flag bit mATAFlagUseConfigSpeed has different
meanings depending on the value of the
ataModeType field. If the
ataModeType field is set to
kATAModeAbsolute (pre-ATA Manager 3.0) then the
flag bit mATAFlagUseConfigSpeed indicates
whether to use timing values for the mode last set with a
Set Driver Configuration
request, or to use timing values for the PIO mode specified
in the field ataPBIOSpeed . If the
ataModeType field is set to
kATAModeBitmap (ATA Manager 3.0 and above) then
the flag bit mATAFlagUseConfigSpeed should
always be set. If so, your AIM must use the bus
mode (PIO, singleword DMA, multiword DMA, UltraDMA) and
timing values that were stored from the last
Set Driver Configuration
request. If mATAFlagUseConfigSpeed is not set,
your AIM should execute the request at the slowest possible
transfer speed.
AIMs versus SIMs
In many respects, AIMs are architecturally similar to
SCSI Interface Modules (SIMs), the name given to host bus
controller drivers in the Mas OS SCSI architecture. The
following table compares various features of AIMs and SIMs.
Feature
|
AIM
|
SIM
|
Single Thread
| Yes
| No
|
Single Request
| Yes
| No
|
Interrupt Polling
| Yes
| Yes
|
Enable/Disable User Code
| No
| Yes
|
Per-Bus Storage
| Maintained by ATA Manager
| Maintained by SCSI Manager
|
Per-Request Storage
| Single request, therefore put per-request data
in per-bus globals
| Allocated by client as part of SCSI parameter
block
|
Update "on the fly"
| Yes
| Not provided by SCSI Manager
|
'ndrv'
| Required
| Possible, but not required
|
Back to top
ATA Manager Additions
ATA Manager 4.0 defines two new ATA Manager function
codes to be used with the ataManager system
call. The new functions are defined below. The codes are
used to add and remove ATA buses, respectively.
enum {
kATAMgrAddATABus = 0x93,
kATAMgrRemoveATABus = 0x94
};
|
IMPORTANT:
If your AIM is loaded from an expansion ROM on a
card, you do not need to register it manually with
ATA Manager. At startup time, ATA Manager will
search the Name Registry for ATA nodes and
automatically register an ATA bus for any node with
an available AIM. ATA Manager considers any node
whose "device_type" property is
kATADeviceType ("ata\15\0") to be an
ATA node.
|
For compatibility reasons, ATA Manager also
recognizes nodes of type "ide\0". New AIMs should
use always kATADeviceType .
Adding an ATA Bus
To add an ATA bus to ATA Manager, you must call the
ataManager system call, passing in a parameter
block of type ataAddATABus .
struct ataAddATABus {
ataPBHeader * ataPBLink;
UInt16 ataPBQType;
UInt8 ataPBVers;
UInt8 ataPBReserved;
Ptr ataPBReserved2;
ProcPtr ataPBCallbackPtr;
OSErr ataPBResult;
UInt8 ataPBFunctionCode;
UInt8 ataPBIOSpeed;
UInt16 ataPBFlags;
SInt16 ataPBReserved3;
UInt32 ataPBDeviceID;
UInt32 ataPBTimeOut;
Ptr ataPBClientPtr1;
Ptr ataPBClientPtr2;
UInt16 ataPBState;
UInt16 ataPBSemaphores;
SInt32 ataPBReserved4;
RegEntryIDPtr ataNameRegEntry;
CFragConnectionID connID;
UInt32 busID;
UInt8 flags;
UInt8 socketType;
Ptr iconData;
Ptr stringData;
};
typedef struct ataAddATABus ataAddATABus;
|
The fields have the following meaning:
ataPBLink
ataPBQType
ataPBVers
ataPBReserved
ataPBReserved2
ataPBCallbackPtr
ataPBResult
ataPBFunctionCode
ataPBIOSpeed
ataPBFlags
ataPBReserved3
ataPBDeviceID
ataPBTimeOut
ataPBClientPtr1
ataPBClientPtr2
ataPBState
ataPBSemaphores
ataPBReserved4
- Standard ATA Manager parameter block header. See
ATA
Device Software for Macintosh Computers for details.
You must initialize
ataPBFunctionCode to
kATAMgrAddATABus , ataPBVers to
kATAPBVers2 .
ataNameRegEntry
- You must set this to the Name Registry node of the
ATA bus which you wish to add. The ATA Manager will use
Driver Loader Library to locate your native driver (AIM)
for this bus. See AIM
Packaging for more information about how your native
driver must be structured.
connID
- Reserved. You must set this field to zero and ignore
any value returned.
busID
- On successful completion of the request, the ATA
Manager sets this field to the ATA bus ID of the newly
created ATA bus.
flags
- You must set this to the bus flags for this bus. The
possible flags are defined
below. The undefined flag bits are reserved; you must
set them to zero.
socketType
- You must set this to the ATA socket type of the bus
using one of the constants defined in "ATA.h" (currently
one of
kATASocketInternal ,
kATASocketMB , or
kATASocketPCMCIA ).
iconData
- You must set this to either a pointer to a black and
white icon (256 bytes of data in
'ICN#'
format) that represents the ATA bus, or to
nil if there is no such icon. ATA Manager
makes a copy of the data, so you can dispose of it when
the call completes.
stringData
- You must set this to either a pointer to a string
that describes the location of the ATA bus, or to
nil if you do not wish to supply a location.
The string is a C string (zero terminated) of at most 31
characters in the system script encoding; longer strings
will be truncated by ATA Manager. ATA Manager makes a
copy of the data, so you can dispose of it when the call
completes.
In response to this request, the ATA Manager opens your
AIM and creates the internal data structures necessary for
it to track the AIM and its attached devices. As part of
processing this call, the ATA Manager calls your AIM's
initialization routine
(MyAIMInit ), which
must probe your bus for attached devices. If your AIM's
initialization routine returns an error, the ATA Manager
cleans up and completes the request with that error. If your
AIM's initialization routine succeeds and indicates that
devices are attached to the bus, ATA Manager will issue
kATAUpdateEvent and
kATAOnlineEvent events for each device.
The possible flags for the
flags field of the ataAddATABus
structure are defined below.
enum {
mATANoDMAOnBus = 0x80
};
|
The meaning of these flags is:
mATANoDMAOnBus
- If this flag is set, the bus the ATA Manager's
kATAMgrBusInquiry
function will indicate that the bus does not support DMA,
even if your AIM indicates that it does. This allows the
bus expert which registers this bus to override AIM
defaults for DMA support. The actual effect of this flag
is that the ATA Manager clears the
ataSingleDMAModes ,
ataMultiDMAModes and
ataUltraDMAModes fields returned by your AIM
in response to a kATAFnBusInquiry request
before returning those fields as part of the client's
kATAMgrBusInquiry request.
You must issue this request at system task time.
Removing an ATA Bus
To remove an ATA bus, you must call the
ataManager system call, passing in a parameter
block of type ataAddATABus .
struct ataRemoveATABus {
ataPBHeader * ataPBLink;
UInt16 ataPBQType;
UInt8 ataPBVers;
UInt8 ataPBReserved;
Ptr ataPBReserved2;
ProcPtr ataPBCallbackPtr;
OSErr ataPBResult;
UInt8 ataPBFunctionCode;
UInt8 ataPBIOSpeed;
UInt16 ataPBFlags;
SInt16 ataPBReserved3;
UInt32 ataPBDeviceID;
UInt32 ataPBTimeOut;
Ptr ataPBClientPtr1;
Ptr ataPBClientPtr2;
UInt16 ataPBState;
UInt16 ataPBSemaphores;
SInt32 ataPBReserved4;
UInt32 busID;
RegEntryIDPtr ataNameRegEntry;
};
typedef struct ataRemoveATABus ataRemoveATABus;
|
The fields have the following meaning:
ataPBLink
ataPBQType
ataPBVers
ataPBReserved
ataPBReserved2
ataPBCallbackPtr
ataPBResult
ataPBFunctionCode
ataPBIOSpeed
ataPBFlags
ataPBReserved3
ataPBDeviceID
ataPBTimeOut
ataPBClientPtr1
ataPBClientPtr2
ataPBState
ataPBSemaphores
ataPBReserved4
- Standard ATA Manager parameter block header. See
ATA
Device Software for Macintosh Computers for details.
You must initialize
ataPBFunctionCode to
kATAMgrRemoveATABus , ataPBVers
to kATAPBVers2 .
busID
- Reserved. You must set this field to zero and ignore
any value returned.
ataNameRegEntry
- You must set this to the Name Registry node of the
ATA bus which you wish to add.
In response to this request the ATA Manager will remove
the ATA bus associated with the Name Registry node specified
in ataNameRegEntry . The ATA Manager executes
the following steps:
- It calls your AIM's action routine
(
MyAIMAction )
with the kATAFnKillIO function code, to
indicate that your AIM should stop processing the current
request.
- It completes any pending I/O requests (including the
current one) for your AIM with the
nsDrvErr
error code.
- It calls your AIM's device light routine
(
MyAIMDeviceLight )
to turn off the device's light.
- It issues the
kATARemovedEvent event for
each device on your bus.
- It calls your AIM's close routine
(
MyAIMClose ),
ignoring any error result.
- It disposes of the resources it used to track the bus
and releases its CFM connection to your AIM.
You may issue this request at any execution level,
although if you issue it at anything other than system task
level the ATA Manager's connection to the AIM is not closed
until a future system task time.
Back to top
AIM Packaging
An AIM is packaged as a native driver
('ndrv' ). For ATA Manager to load your AIM, it
must be available to the Driver Loader Library. See
Designing
PCI Cards and Drivers for Power Macintosh Computers for
more information on how Driver Loader Library finds native
drivers.
Your AIM must export two named entry global variables:
- TheDriverDescription -- This is the standard native
driver description.
- ThePluginDispatchTable -- This contains information
specific to ATA Manager.
The structure of these global variables is described in
the following sections.
TheDriverDescription
An AIM must export the standard native driver description
structure under the name "TheDriverDescription". An example
of how your AIM should fill out this structure is given
below.
01 extern DriverDescription TheDriverDescription = {
02
03 // Signature
04
05 kTheDescriptionSignature,
06 kInitialDriverDescriptor,
07
08 // Driver Type
09
10 {
11 "\pMyAIMName",
12 kmajorRev, kminorAndBugRev, kstage, knonRelRev,
13 },
14
15 // OS Runtime Requirements of Driver
16
17 {
18 kDriverIsUnderExpertControl,
19 "\pMyAIMName",
20 },
21
22 // Service Category List
23
24 // Only one service category required
25
26 1,
27
28 // First Service Category
29
30 kServiceCategoryATA,
31 0,
32 1, 0, 0, 0
33 };
|
Some parts of this definition deserve further
explanation.
- Line 11
- You must set the
nameInfoStr field of
the DriverType structure to the name of the
Name Registry node your driver controls. This allows the
Driver Loader Library, and hence the ATA Manager, to
associate your driver with the appropriate hardware.
- Line 12
- You must set the
version field of the
DriverType structure the version number of
your driver. This allows the Driver Loader Library to
load the latest version of your driver if more than one
happens to be installed. It also allows the ATA Manager
to replace an initial ROM-based AIM with a newer
file-based AIM once the File Manager is available.
- Line 18
- AIMs are explicitly loaded by the ATA Manager (the
expert), so you must set the
driverRuntime
flags of the DriverOSRuntime structure to
kDriverIsUnderExpertControl .
- Line 19
- The driverName field of the
DriverOSRuntime structure is typically used
to hold the unit table name of the driver. As AIMs are
not installed in unit table, this field is not
significant. You should set to the same string you
used in Line 11.
- Lines 26 through 32
- AIMs are required to export at least one service
category, namely
kServiceCategoryATA . This
allows the ATA Manager to check that it correctly matched
the AIM to the Name Registry node. The other fields of
the DriverServiceInfo structure are reserved
for future versions of the ATA Manager; you must
initialize them as shown.
ThePluginDispatchTable
In addition to the standard drive description, you AIM
must export a plugin dispatch table under the name
"ThePluginDispatchTable". The
ATAPluginDispatchTable type describes the
format of this table.
struct ATAPluginDispatchTable {
ATAPluginHeader header;
ATAPluginInit init;
ATAPluginClose close;
ATAPluginAction action;
ATAPluginHandleBusEvent busEvent;
ATAPluginPoll poll;
ATAPluginEjectDevice eject;
ATAPluginDeviceLight light;
ATAPluginDeviceLock lock;
ATAPluginSuspend suspend;
ATAPluginResume resume;
};
typedef struct ATAPluginDispatchTable ATAPluginDispatchTable;
typedef OSStatus ATAPluginInit(ATAInitInfo *pb);
typedef OSStatus ATAPluginClose(UInt32 refCon, RegEntryIDPtr aimRegEntry);
typedef void ATAPluginAction(UInt32 refCon, ATAReqBlock *pb);
typedef void ATAPluginHandleBusEvent(UInt32 refCon, UInt32 aimData);
typedef Boolean ATAPluginPoll(UInt32 refCon, UInt32 interruptLevel, UInt32 *aimData);
typedef void ATAPluginEjectDevice(UInt32 refCon);
typedef void ATAPluginDeviceLight(UInt32 refCon, UInt32 whichDevice, UInt32 lightState);
typedef void ATAPluginDeviceLock(UInt32 refCon, UInt32 whichDevice, UInt32 lockState);
typedef void ATAPluginSuspend(UInt32 refCon);
typedef void ATAPluginResume(UInt32 refCon);
|
The fields have the following meaning:
header
- A header which describes the version of the overall
plugin dispatch table. See below.
init
- You must set this to a pointer to your AIM's
initialization routine
(
MyAIMInit ).
close
- You must set this to a pointer to your AIM's close
routine
(
MyAIMClose ).
action
- You must set this to a pointer to your AIM's action
routine
(
MyAIMAction ).
busEvent
- You must set this to a pointer to your AIM's bus
event handler routine
(
MyAIMHandleBusEvent ).
poll
- You must set this to a pointer to your AIM's
interrupt poll routine
(
MyAIMPoll ).
eject
- You must set this to a pointer to your AIM's eject
routine
(
MyAIMEjectDevice )
or nil if your AIM does not have an eject
routine.
light
- opt You must set this to a pointer to your AIM's
device light routine
(
MyAIMDeviceLight )
or nil if your AIM does not have an eject
routine.
lock
- You must set this to a pointer to your AIM's device
lock routine
(
MyAIMDeviceLock )
or nil if your AIM does not have an eject
routine.
suspend
- You must set this to a pointer to your AIM's suspend
routine
(
MyAIMSuspend ).
resume
- You must set this to a pointer to your AIM's resume
routine
(
MyAIMResume ).
The ATAPluginHeader , as defined below,
structure describes the version of the overall plugin
dispatch table.
struct ATAPluginHeader {
NumVersion headerVersion;
NumVersion dispatchVersion;
UInt32 reservedA;
UInt32 reservedB;
};
typedef struct ATAPluginHeader ATAPluginHeader;
enum {
kATAPluginVersion = 0x00000001,
kATAPluginCurrentVersion = kATAPluginVersion
};
|
The fields have the following meaning:
headerVersion
- You must set this to the version number of your AIM,
as defined above.
dispatchVersion
- If your AIM conforms to this version of the
specification, you must set this field to
kATAPluginVersion .
reservedA
- Reserved. You must set this to zero.
reservedB
- Reserved. You must set this to zero.
Note:
ATA Manager does not currently look at the
dispatchVersion field. Moreover,
Apple's AIMs do not currently set this field
correctly. Because of this confusion, any future
version of ATA Manager that implements an extended
plug-in interface will not use this field to
determine which version of the plug-in interface
that your AIM conforms to. |
Back to top
AIM Entry Points
Your AIM must implement a number of routines and export
those routines to the ATA Manager via the plugin dispatch
table. This section describes these routines in detail.
MyAIMInit
extern OSStatus MyAIMInit(ATAInitInfo *aimInit);
|
aimInit
|
A pointer to an ATAInitInfo
parameter block, described below.
|
result
| An error code; see below for details.
|
The ATA Manager calls your AIM's initialization routine
to commence operations on the ATA bus controlled by your
AIM. This routine is called when an ATA
bus is registered with ATA Manager. Your AIM must
allocate any private resources it needs (typically per-bus
storage), install its interrupt handler, initialize its
hardware, probe the bus for attached devices (and determine
whether they are ATA or ATAPI), and return information about
those devices to the ATA Manager. Depending on your
hardware, your AIM may need to reset the ATA bus to
determine if any devices are attached.
Your AIM must also create child Name Registry nodes for
the attached ATA devices. The nodes must have at least the
following properties:
- The "name" property must be set to either "ata-disk"
or "atapi-disk".
- The "device_type" property must be set to "block".
- The "device_id" property must be set to a
UInt32 that contains the ATA bus ID and
device ID (in the same format as the
ataPBDeviceID field of ATA Manager parameter
blocks).
Your AIM initialization routine must not issue any
commands to the ATA device.
Your AIM's initialization routine receives the address of
an ATAInitInfo parameter block as a parameter.
The parameter block contains both input and output fields.
struct ATAInitInfo {
UInt32 busID;
ATADevInfo FirstDevice;
ATADevInfo SecondDevice;
RegEntryIDPtr aimRegEntry;
UInt32 refCon;
};
typedef struct ATAInitInfo ATAInitInfo;
|
The fields have the following meaning:
busID
- ATA Manager sets this to the ATA bus ID it has
assigned to the new bus that is being registered.
FirstDevice
- Your AIM must initialize this structure to hold
information about the first device on the ATA bus. See
below for a description of the
ATADevInfo
structure. If the bus supports ATA devices 0 and 1, and
device 1 is present but device 0 isn't, your AIM should
set this structure to represent device 1 and set
SecondDevice to indicate that no second
device is attached.
SecondDevice
- Your AIM must initialize this structure to hold
information about the second device on the ATA bus.
aimRegEntry
- The ATA Manager sets this to the Name Registry node
of the ATA bus which is being registered.
refCon
- Your AIM may set this field to any 32-bit value,
typically a pointer to your per-bus storage. The ATA
Manager will pass this value as a parameter (typically
named
refCon ) whenever it calls your other
AIM entry points.
IMPORTANT:
The AIMInitInfo data structure and the
structures it points to are deallocated as soon as
your AIM returns from MyAIMInit . If
you wish to retain access to this data, you must
copy it to your own storage. Specifically, you
should make a copy of the RegEntryID
pointed to by aimRegEntry .
Copying the RegEntryIDPtr is
not sufficient!
|
The ATADevInfo structure holds information
about a specific ATA device on a bus. Your
struct ATADevInfo {
UInt8 devType;
SInt8 devID;
};
typedef struct ATADevInfo ATADevInfo;
enum {
kATAInvalidDeviceID = -1,
kATADevice0DeviceID = 0,
kATADevice1DeviceID = 1
};
|
The fields have the following meaning:
devType
- Your AIM must set this field to indicate the type of
the attached device. Possible ATA device types are listed
in "ATA.h" (current
kATADeviceUnknown ,
kATADeviceATA , kATADeviceATAPI ,
and kATADeviceReserved ).
devID
- Your AIM must set this field to indicate the ATA
device ID of the attached device. Possible device IDs are
kATAInvalidDeviceID ,
kATADevice0DeviceID and
kATADevice1DeviceID .
If your AIM wants to indicate that no ATA device is
attach, it must set devType to
kATADeviceUnknown and devID to
kATAInvalidDeviceID .
If your AIM initialization routine returns an error, or
it indicates that there are no devices on the bus, ATA
Manager fails the request to register the ATA bus, unloads
your AIM, and dispose of all references to it.
IMPORTANT:
It is especially important to take note of the
circumstances under which your AIM will be unloaded
when extending the interrupt source tree for
multiple bus controllers that share an interrupt.
Remember, your buses may be initialized in any
order. The first instance of an AIM that
successfully initializes should extend the
interrupt tree and store the child interrupt nodes
for each bus in the Name Registry. When the second
bus is initialized, it can look in the Name
Registry to determine whether the interrupt tree
has been extended or not.
|
Suggested result codes include:
noErr Initialization successful.
memFullErr Unable to allocate private
data.
nsDrvErr No device detected on node
paramErr Bad parameter
nrInvalidNodeErr Invalid Name Registry
node
nrNotFoundErr A required property was
not found in the Name Registry node
ATAInitFail Initialization failed
This routine is always be called at system task time.
MyAIMClose
extern OSStatus MyAIMClose(UInt32 refCon, RegEntryIDPtr aimRegEntry);
|
refCon
| A pointer to your per-bus storage, as returned
by MyAIMInit
|
aimRegEntry
|
The Name Registry node of the ATA bus which is
being deregistered.
|
result
|
An error code; see below for details.
|
The ATA Manager calls your AIM's close routine to
terminate operations on the ATA bus controlled by your AIM.
This routine is called when an ATA
bus is deregistered with ATA Manager. Your AIM must shut
down its hardware, remove any interrupt handlers, and
release any resources it owns. This will be the last request
that a particular instance of your AIM will receive.
Any error code returned by your AIM is ignored. You
should structure your AIM such that its close routine can
not fail.
This routine will always be called at system task time.
MyAIMAction
extern void MyAIMAction(UInt32 refCon, ATAReqBlock *pb);
|
refCon
| A pointer to your per-bus storage, as returned
by MyAIMInit
|
pb
|
A pointer to an ATAReqBlock
parameter block, described below.
|
The ATA Manager calls your AIM's action routine to
perform a transaction on the ATA bus. The
ATAReqBlock parameter block specifies the
action to perform and the place to store the results. The
meaning of many of the fields is dependent on the
ataFunctionCode field, which specifies exactly
what operation is to be performed. Each function code is
described in detail in AIM
Action Function Codes.
struct ATAReqBlock {
UInt32 connectionID;
UInt32 MsgID;
ATAResult * result;
ATADiagResult * DiagResult;
ATABusInfo * busInfo;
ATADevConfig * devConfig;
ATADataObject ioObject;
ataTaskFile ataPBTaskFile;
ATAPICmdPacket packetCBD;
Duration Timeout;
UInt32 BusID;
SInt8 DevID;
UInt8 ataFunctionCode;
UInt32 AbortID;
UInt32 ataPBLogicalBlockSize;
UInt32 ataPBFlags;
UInt32 reserved;
struct ATAReqBlock * nextREQ;
OSStatus ataPBResult;
UInt8 ataPBErrorRegister;
UInt8 ataPBStatusRegister;
UInt32 ataPBactualXferCount;
UInt32 ataPBState;
UInt32 ataPBSemaphores;
UInt8 XferType;
UInt8 ataModeType;
UInt8 ataPBIOSpeed;
UInt8 reserved2;
UInt16 reserved3;
};
typedef struct ATAReqBlock ATAReqBlock;
|
Unless otherwise stated, a field is has the same meaning
for all function codes (except
kATAFnKillIO ). The
fields have the following meaning:
connectionID
- Reserved. You must not modify this field or depend on
its contents.
MsgID
- Reserved. You must not modify this field or depend on
its contents.
result
- This field is used to hold the result of an AIM
action. This field is a structure
(
ATAResult ), not a
simple 'ioResult ' value, but the fields of
the structure are only relevant to the
kATAFnExecIO function
code. The only field relevant to the other function codes
is ataResult field, but your AIM does not
need to explicitly set this field because
ATAFamIODone
does it for you.
DiagResult
- This field is significant only for the
kATAFnRegAccess
function code and is described along with that function
code.
busInfo
- This field is significant only for the
kATAFnBusInquiry
function code and is described along with that function
code.
devConfig
- This field is significant only for the
kATAFnGetDriveConfig
and
kATAFnSetDriveConfig
function codes and is described along with those function
codes.
ioObject
- This field is significant only for the
kATAFnExecIO and
kATAFnDriveIdentify
function codes and is described along with those function
codes.
ataPBTaskFile
- This field is significant only for the
kATAFnExecIO
function code and is described along with that function
code.
packetCBD
- This field is significant only for the
kATAFnExecIO
function code and is described along with that function
code.
Timeout
- The ATA Manager sets this field to a timeout (in
milliseconds) for the request. It derives the value from
the
ataPBTimeOut field of the client's
request, or sets it to a default value (currently 31000)
if ataPBTimeOut was zero.
BusID
- ATA Manager sets up this field to the bus ID of the
ATA bus on which to perform the action. It derives this
value from
ataPBDeviceID field of the
client's request. Typically your AIM ignores this field
because the bus is already uniquely identified by the
per-bus storage pointed to by the refCon
passed to AIMAction .
DevID
- ATA Manager sets up this field to either
kATADevice0DeviceID or
kATADevice1DeviceID to describe which device
on the ATA bus to act upon. It derives this value from
the ataPBDeviceID field of the client's
request.
ataFunctionCode
- ATA Manager sets up this field to describe the action
that the AIM should take.
AIM Action Function
Codes lists the defined function codes.
AbortID
- ATA Manager does not use this field except insofar as
to initialize it to zero. Your AIM can use this field as
it sees fit.
ataPBLogicalBlockSize
- This field is significant only for the
kATAFnExecIO
function code and is described along with that function
code.
ataPBFlags
- The ATA Managers sets this field to the value of the
ataPBFlags field of the client's request.
Your AIM is expected to read this field and act on the
flags it contains.
reserved
- Reserved. You must not modify this field or depend on
its contents.
nextREQ
- ATA Manager does not use this field except insofar as
to initialize it to zero. Your AIM can use this field as
it sees fit.
ataPBResult
- ATA Manager does not use this field except insofar as
to initialize it to zero. Your AIM can use this field as
it sees fit, although typically it is used to hold a
temporary result.
ataPBErrorRegister
- ATA Manager does not use this field except insofar as
to initialize it to zero. Your AIM can use this field as
it sees fit, although typically it is used as temporary
storage for the error register.
ataPBStatusRegister
- ATA Manager does not use this field except insofar as
to initialize it to zero. Your AIM can use this field as
it sees fit, although typically it is used as temporary
storage for the status register.
ataPBactualXferCount
- ATA Manager does not use this field except insofar as
to initialize it to zero. Your AIM can use this field as
it sees fit, although typically it is used as temporary
storage for the transfer count.
ataPBState
- ATA Manager does not use this field except insofar as
to initialize it to zero. Your AIM can use this field as
it sees fit, although typically it is used to track the
state of the request.
ataPBSemaphores
- ATA Manager does not use this field except insofar as
to initialize it to zero. Your AIM can use this field as
it sees fit, although typically it is used to hold flags
that indicate the status of the request.
XferType
- ATA Manager does not use this field except insofar as
to initialize it to zero. Your AIM can use this field as
it sees fit, although typically it is used to hold the
I/O transfer type (PIO, single-word DMA, multi-word DMA).
ataModeType
- ATA Manager sets up this field to indicate whether
the
ataPBIOSpeed field contains an absolute
value (kATAModeAbsolute ) or a bitmap of
possible values (kATAModeBitmap ). It derives
this value from the ataPBVers field of the
client request; absolute mode is used only if the
parameter block is less than version 3. See
ATA I/O Modes for more
information about how your AIM should interpret this and
the ataPBIOSpeed field.
ataPBIOSpeed
- ATA Manager sets this field to the
ataPBIOSpeed field of the client's request.
reserved2
- Reserved. You must not modify this field or depend on
its contents.
reserved3
- Reserved. You must not modify this field or depend on
its contents.
Each field is described in more detail with the
appropriate function
code.
Your AIM typically processes an action request using a
state machine. When it receives the action request, it
initializes the state machine and starts the first
(asynchronous) step of processing the request. It then
returns control to the ATA Manager. When the first step is
complete, the hardware generates an interrupt and the AIM's
interrupt service routine is called. It notifies ATA Manager
of the bus event by calling
ATAFamBusEventForAIM .
ATA Manager then calls the AIM's bus event handler routine
(MyAIMHandleBusEvent ),
which starts the next (asynchronous) step of processing the
request. When the last step is done, the AIM calls
ATAFamIODone . ATA
Manager completes the original client's request and then
calls the AIM to start the next request.
This routine may be called at any execution level.
MyAIMHandleBusEvent
extern void MyAIMHandleBusEvent(UInt32 refCon, UInt32 aimData);
|
The ATA Manager calls your AIM's bus event handler
routine to handle events detected on your bus. Typically
these events are interrupts from your bus's interrupt
hardware. Your AIM informs ATA Manager of these events in
one of two ways:
- When an interrupt occurs (and is not masked), your
interrupt service routine is called. Your interrupt
service routine must inform ATA Manager of the bus event
by calling
ATAFamBusEventForAIM
and then return.
- When interrupts are masked (or otherwise deferred),
ATA Manager calls your AIM's interrupt poll routine
(
MyAIMPoll ) to poll
for masked interrupts. If the interrupt poll routine
detects an interrupt, it returns an indicative status to
ATA Manager.
Regardless of how it informs ATA Manager of the bus
event, your AIM can provide a bus event type which indicates
what type of bus event occurred. The ATA Manager passes the
same bus event type back to the bus event handler in the
aimData parameter. Typically this bus event
type is used to distinguish the type of bus event that has
occurred. For example, your AIM might use a value of 1 to
indicate that a DMA interrupt has occurred and a value of 2
to indicate that an I/O interrupt has occurred. ATA Manager
does not interrupt this value.
Typically your AIM responds to a bus event by moving the
current I/O request to the next state. For example, if the
current I/O request is waiting for an I/O completion bus
event, your AIM would respond to that bus event by calling
ATAFamIODone to
inform ATA Manager that the I/O request is complete. On the
other hand, if the current I/O request is not complete, your
AIM would respond by setting up the next asynchronous I/O
operation.
This routine may be called at any execution level. It is
typically executed with interrupts enabled (either from a
deferred task or a secondary interrupt) but that is not
guaranteed.
MyAIMPoll
extern Boolean MyAIMPoll(UInt32 refCon,
UInt32 interruptLevel,
UInt32 *aimDataPtr);
|
refCon
|
A pointer to your per-bus storage, as returned
by MyAIMInit .
|
interruptLevel
|
The current 68K interrupt mask: a value from 0
to 7.
|
aimDataPtr
|
If your AIM detected a bus event, it should set
the value pointed to by this parameter to the type
of bus event that occurred; see
AIM
Synchronization Model for more details.
|
result
|
True if the AIM detected a bus event, otherwise
false.
|
The ATA Manager calls your AIM's interrupt poll routine
when it detects that a synchronous I/O request is blocked
because interrupts are masked (or otherwise deferred). Your
AIM must look at its interrupt hardware to determine if
there is an interrupt pending. If there is, your AIM must
set the memory pointed to by aimDataPtr to the
type of bus event associated with that interrupt (see
AIM Synchronization
Model for more details on bus event types) and return
true. If there is no interrupt pending, your AIM must return
false.
The interruptLevel parameter is a
convenience only. Your AIM may use this value to determine
which interrupt sources to check. For example, if your AIM
receives device interrupts at level 2 and DMA interrupts at
level 4, and the current interruptLevel is 3, it
need not check the status of the DMA interrupt line because
that interrupt is not being masked.
This routine may be called at any execution level.
Background Material
Under the Mac OS I/O system architecture, it is possible
for the system to take a page fault in three hard-to-handle
cases:
- inside an interrupt handler (for example, Sound
Manager callbacks are made directly from a sound hardware
interrupt handler, but applications must be able to take
page faults in these callbacks)
- when interrupts are masked (for example, the OS
Utilities routine Enqueue will set the interrupt mask to
7 and then manipulate queue headers, which may be paged
out)
- when critical system resources are busy (for example,
the ATA Manager typically defers processing of bus events
until secondary interrupt time, but secondary interrupts
are serialized and a page fault from a hardware interrupt
handler while an unrelated secondary interrupt was
running would deadlock the system)
Page faults result in synchronous disk driver I/O
requests. If the underlying I/O hardware requires interrupts
to complete an I/O request, and interrupts are masked or
otherwise deferred when the page fault happens, the system
will deadlock.
In order to avoid this deadlock, the system polls for
interrupts during any "sync wait" loop which occurs while
interrupts are masked (or otherwise deferred). Given that
the system has no knowledge of your AIM's interrupt
architecture, it calls your AIM's interrupt poll routine to
accomplish this polling.
See DTS Technote 1094
Virtual
Memory Application Compatibility and DTS Q&A DV 34
Secondary
Interrupts on the Page Fault Path for more details about
this technique.
MyAIMEjectDevice
extern void MyAIMEjectDevice(UInt32 refCon);
|
refCon
| A pointer to your per-bus storage, as returned
by MyAIMInit
|
The ATA Manager calls your AIM's eject routine in
response to a kATAMgrDriveEject request.
IMPORTANT:
This routine ejects the entire ATA bus, not simply
the media from a device on the bus. The distinction
is a subtle but important one. An example of an AIM
that implements the eject routine is the built-in
PC Card AIM, which ejects the PC Card in response
to this call. |
If your ejection hardware is asynchronous, this operation
should simply start the ejection operation. If an
asynchronous ejection operation is not complete by the time
the ATA bus is deregistered, your close routine
(MyAIMClose ) is
responsible for waiting until it is.
This routine is optional. If your AIM does not support
this function, it should set the appropriate plugin dispatch
table entry to nil .
This routine may be called at any execution level.
MyAIMDeviceLight
extern void MyAIMDeviceLight(UInt32 refCon,
UInt32 whichDevice,
UInt32 lightState);
|
refCon
| A pointer to your per-bus storage, as returned
by MyAIMInit
|
whichDevice
| The ATA socket type of the device, derived from
the socketType field of the
ataAddATABus structure used to
register the bus
|
lightState
| The state in which to set the light: one of the
constants given below
|
The ATA Manager calls your AIM's device light routine to
turn on and off the activity light, if any, associated with
your AIM. Typically the ATA Manager enables the activity
light in response to a device driver request (the driver
sets the mATAFlagLEDEnable flag in the
ataPBFlags field of the parameter block it
passes to the ataManager system call).
The constants for the lightState parameter
are defined below.
enum {
kATADeviceLightOff = 0x00,
kATADeviceLightOn = 0x01
};
|
An example of an AIM that implements this routine is the
media bay AIM for PowerBook computers, where it controls the
LED on the media bay device.
This routine is optional. If your AIM does not support
this function, it should set the appropriate plugin dispatch
table entry to nil .
This routine may be called at any execution level.
MyAIMDeviceLock
extern void MyAIMDeviceLock(UInt32 refCon,
UInt32 whichDevice,
UInt32 lockState);
|
refCon
| A pointer to your per-bus storage, as returned
by MyAIMInit
|
whichDevice
| The ATA socket type of the device, derived from
the socketType field of the
ataAddATABus structure used to
register the bus
|
lockState
| Whether the device is locked or not; one of the
constants given below
|
The ATA Manager calls your AIM's device lock routine to
lock and unlock the hardware associated with your AIM. A
locked device cannot be ejected by the user. The ATA Manager
locks and unlocks the AIM based on the
mATApcLockUnlock flag in the
atapcValid field of the
ataDevConfiguration parameter block supplied to
a kATAMgrSetDrvConfiguration request.
The constants for the lockState parameter
are defined below.
enum {
kATADeviceUnlock = 0x00,
kATADeviceLock = 0x01
};
|
An example of an AIM that implements this routine is the
built-in PC Card AIM, which prevents users from ejecting the
PC Card if it has been locked.
This routine is optional. If your AIM does not support
this function, it should set the appropriate plugin dispatch
table entry to nil .
This routine may be called at any execution level.
MyAIMSuspend
extern void MyAIMSuspend(UInt32 refCon);
|
refCon
| A pointer to your per-bus storage, as returned
by MyAIMInit
|
The ATA Manager calls your AIM's suspend routine as part
of the process of updating an AIM to a newer version. See
AIM Update Process for more
details.
Your AIM must "disconnect" itself from all system
callbacks except those directly associated with the ATA
Manager. This includes:
- interrupt handlers
- timer tasks
- power management callbacks
This allows the ATA Manager to unload the code associated
with the older version of your AIM. Your AIM must not
dispose of the per-bus storage associated with
refCon . ATA Manager will pass the same
refCon to the resume routine of the newer AIM,
which is responsible for "reconnecting" the AIM to the
system.
The ATA Manager guarantees that it will not call your AIM
from the beginning of your suspend routine until your resume
routine returns.
This routine will always be called at system task time.
MyAIMResume
extern void MyAIMResume(UInt32 refCon);
|
refCon
| A pointer to your per-bus storage, as returned
by MyAIMInit
|
The ATA Manager calls your AIM's resume routine as part
of the process of updating an AIM to a newer version. See
AIM Update Process for more
details.
Your AIM must "redisconnect" itself to all system
callbacks which were disconnected by the suspend routine.
This includes:
- interrupt handlers
- timer tasks
- power management callbacks
Your AIM is required to continue operations using the
per-bus storage inherited from the older version and pointed
to by refCon . If the format of your per-bus
storage changes between versions, your resume routine must
convert from the old to the new format.
The ATA Manager guarantees that it will not call your AIM
from the beginning of your suspend routine until your resume
routine returns.
This routine will always be called at system task time.
Back to top
AIM Action Function Codes
When ATA Manager calls your AIM's action routine
(MyAIMAction ), it
sets the ataFunctionCode field of the
ATAReqBlock parameter block to a value which
identifies the type of operation to be performed. The
possible function codes are listed below:
enum {
kATAFnNOP = 0x00,
kATAFnExecIO = 0x01,
kATAFnBusInquiry = 0x02,
kATAFnQRelease = 0x03,
kATAFnCmd = 0x04,
kATAFnAbort = 0x05,
kATAFnBusReset = 0x06,
kATAFnRegAccess = 0x07,
kATAFnDriveIdentify = 0x08,
kATAPIFnExecIO = 0x09,
kATAPIFnCmd = 0x0A,
kATAFnGetDriveConfig = 0x0B,
kATAFnSetDriveConfig = 0x0C,
kATAFnKillIO = 0x0D
};
|
The following sections describe each function code in
detail. If your AIM receives a request with a function code
it does not recognize, it should fail the request with a
status of paramErr .
No Operation (kATAFnNOP)
This is a "no operation" request. ATA Manager should
never issue this request to your AIM. If it does, your AIM
should immediately complete the request successfully by
calling
ATAFamIODone with a
status of noErr .
Execute I/O (kATAFnExecIO)
ATA Manager issues this request to your AIM as the result
of a client's kATAMgrExecIO request. Your AIM
is expected to execute the specified I/O transaction to the
specified device on the specified bus. The bulk of the
ATAReqBlock is set up as
described above; only the fields specific to this
request are described here.
The structure of the
result field of the ATAReqBlock is
shown below.
struct ATAResult {
OSStatus ataResult;
SInt8 ataStatusRegister;
SInt8 ataErrorRegister;
UInt32 actualXferCount;
ataTaskFile * TaskFile;
};
typedef struct ATAResult ATAResult;
|
The fields have the following meaning:
ataResult
- The overall error result for the request. Unlike the
other fields in the
ATAResult structure,
this field is relevant for all function codes. Your AIM
must not explicitly set this field because
ATAFamIODone
does it for you.
ataStatusRegister
- For execute I/O requests, your AIM must set this
field to the contents of the ATA status register. When
you complete the request, ATA Manager copies this field
to the
ataPBStatusRegister field of the
client's parameter block.
ataErrorRegister
- For execute I/O requests, your AIM must set this
field to the contents of the ATA error register. When you
complete the request, ATA Manager copies this field to
the
ataPBErrorRegister field of the client's
parameter block.
actualXferCount
- For execute I/O requests, your AIM must set this
field to number of bytes actually transferred. When you
complete the request, ATA Manager copies this field to
the
ataPBActualTxCount field of the client's
parameter block.
TaskFile
- For execute I/O requests, your AIM must copy the
current contents of the ATA task file to the structure
pointed to by this field, if it is not
nil .
Typically you copy this directly from the
ataPBTaskFile field of the
ATAReqBlock . ATA Manager does not currently
look at this field.
The structure of the ioObject field of the
ATAReqBlock is shown below.
struct ATADataObject {
UInt8 * ioBuf;
UInt32 Count;
};
typedef struct ATADataObject ATADataObject;
|
The meaning of the fields in the
ATADataObject structure are dependent on
whether scatter/gather is enabled for this request.
Scatter/gather is enabled if
mATAFlagUseScatterGather is set in the
ataPBFlags for the request. If scatter/gather
is not enabled, the fields have the following meaning:
ioBuf
- ATA Manager sets this field to point to the start of
the data buffer for the transfer.
Count
- ATA Manager sets this field to the count of the
number of bytes to transfer.
If scatter/gather is enabled, the fields have the
following meaning:
ioBuf
- ATA Manager sets this field to point to an array of
IOBlock structures (defined in "ATA.h").
Your AIM should transfer the data between the device and
the scatter/gather buffer defined by this array.
Count
- ATA Manager sets this field to the number of
IOBlock structures in the array pointed to
by ioBuf .
The ataPBTaskFile field of the
ATAReqBlock has the same structure as the
ataPBTaskFile field of the ataIOPB
(defined in "ATA.h"). Before issuing an execute I/O request
to your AIM, ATA Manager copies, without interpretation, the
task file from the client's ataIOPB to the
ataPBTaskFile field of the
ATAReqBlock . [It does, however, force the
mATADriveSelect bit of the
ataTFSDH field of the task file based on the
devID field of the ATAReqBlock .]
When your AIM completes the request, the ATA Manager copies
the ataPBTaskFile field back to the client's
ataIOPB .
The packetCBD field of the
ATAReqBlock has the same structure as the
ATAPICmdPacket type defined in "ATA.h". By
default, the ATA Managers clears this field before issuing
an execute I/O request to your AIM. However, if the client
issued an ATAPI request (mATAFlagProtocolATAPI
was set in the ataPBFlags and
ataPBPacketPtr was not nil), ATA Manager copies
the ATAPICmdPacket pointed to by
ataPBPacketPtr into the packetCBD
field of the ATAReqBlock .
For execute I/O requests, the ATA Manager sets the
ataPBLogicalBlockSize field of the
ATAReqBlock to
ataPBLogicalBlockSize field of the client's
request.
Bus Inquiry
(kATAFnBusInquiry)
ATA Manager issues this request to your AIM as the result
of a client's kATAMgrBusInquiry request. Your
AIM is expected to return information about the specified
ATA bus. The bulk of the ATAReqBlock is set up
as described above; only the
fields specific to this request are described here.
The structure of the busInfo field of the
ATAReqBlock is shown below:
struct ATABusInfo {
UInt8 ataPIOModes;
UInt8 ataSingleDMAModes;
UInt8 ataMultiDMAModes;
UInt8 ataUltraDMAModes;
UInt32 ataIOPBsize0;
UInt32 ataIOPBsize1;
SInt8 ataContrlType[16];
NumVersion ataHBAversion;
UInt32 reserved3;
};
typedef struct ATABusInfo ATABusInfo;
|
The fields have the following meaning:
ataPIOModes
- Your AIM must set this field to a bit mask
representing the PIO transfer modes it supports. On
completion of the request, ATA Manager copies this field
into the
ataPIOModes field of the client's
request.
ataSingleDMAModes
- Your AIM must set this field to a bit mask
representing the singleword DMA transfer modes it
supports. On completion of the request, ATA Manager
copies this field into the
ataSingleDMAModes
field of the client's request (unless the bus was
registered with the
mATANoDMAOnBus flag,
in which case this field is ignored and the ATA Manager
clears the ataSingleDMAModes field of the
client's request).
ataMultiDMAModes
- Your AIM must set this field to a bit mask
representing the multiword DMA transfer modes it
supports. On completion of the request, ATA Manager
copies this field into the
ataMultiDMAModes
field of the client's request (unless the bus was
registered with the
mATANoDMAOnBus flag,
in which case this field is ignored and the ATA Manager
clears the ataMultiDMAModes field of the
client's request).
ataUltraDMAModes
- Your AIM must set this field to a bit mask
representing the UltraDMA transfer modes it supports. On
completion of the request, ATA Manager copies this field
into the
ataUltraDMAModes field of the
client's request (unless the bus was registered with the
mATANoDMAOnBus flag,
in which case this field is ignored and the ATA Manager
clears the ataUltraDMAModes field of the
client's request).
ataIOPBsize0
- Your AIM must set this field to
kATADefaultBlockSize (512). This field was
originally intended to hold the size of an ATA sector on
device 0, but developments in the ATA standard (namely
ATAPI) have obviated the need for this information.
ataIOPBsize1
- Your AIM must set this field to
kATADefaultBlockSize (512). This field was
originally intended to hold the size of an ATA sector on
device 1, but developments in the ATA standard (namely
ATAPI) have obviated the need for this information.
ataContrlType
- Your AIM may set this field to any value, including
characters or binary data. The field is intended as a
mechanism to report a vendor or model name, or other data
for identification or diagnostic purposes. If you do not
implement this functionality, you should clear the entire
field. On completion of the request, ATA Manager copies
this field into the
ataContrlType field of
the client's request.
ataHBAversion
- Your AIM must put its version number in this field.
On completion of the request, ATA Manager copies this
field into the
ataHBAversion field of the
client's request.
reserved3
- Reserved. You must not modify this field or depend on
its contents.
I/O Queue Release (kATAFnQRelease)
Requests of this type should never be passed through to
your AIM. Your AIM should treat this as an unrecognized
function code.
ATA Command (kATAFnCmd)
Requests of this type should never be passed through to
your AIM. Your AIM should treat this as an unrecognized
function code.
Abort Command (kATAFnAbort)
Requests of this type should never be passed through to
your AIM. Your AIM should treat this as an unrecognized
function code.
Reset ATA Bus
(kATAFnBusReset)
ATA Manager issues this request to your AIM as the result
of a client's kATAMgrBusReset request. Your AIM
is expected to reset the specified ATA bus. The
ATAReqBlock is set up as
described above; there are no fields specific to this
request.
Register Access
(kATAFnRegAccess)
ATA Manager issues this request to your AIM as the result
of a client's kATAMgrRegAccess request. Your
AIM is expected to read or write the specified ATA
registers. The bulk of the ATAReqBlock is set
up as described above; only the
fields specific to this request are described here.
IMPORTANT:
Your AIM must determine whether to read or write
the ATA registers based on the
mATAFlagIOWrite flag in the
ataPBFlags field of the
ATAReqBlock . |
The structure of the DiagResult field of the
ATAReqBlock is shown below.
struct ATADiagResult {
UInt16 ataRegMask;
OSStatus ataResult;
UInt16 ataDataReg;
UInt8 ataTFFeatures;
UInt8 ataTFCount;
UInt8 ataTFSector;
UInt8 ataTFCylinderLo;
UInt8 ataTFCylinderHi;
UInt8 ataTFSDH;
UInt8 ataTFCommand;
UInt8 ataAltStatDevCnt;
};
typedef struct ATADiagResult ATADiagResult;
|
The fields have the following meaning:
ataRegMask
- The ATA Manager sets bits in this field to indicate
which registers to read or write. The bit mask are
defined in "ATA.h" (
mATAAltSDevCValid ,
mATAStatusCmdValid ,
mATASDHValid , and so on).
ataResult
- Reserved. You must not modify this field or depend on
its contents.
ataDataReg
- For a write operation, your AIM must write this field
to the ATA data register (always a 16-bit write) if
mATADataValid is set in
ataRegMask . For a read operation, your AIM
must read the ATA data register (always a 16-bit read)
and put it in this field if mATADataValid is
set in ataRegMask .
ataTFFeatures
- For a write operation, your AIM must write this field
to the ATA error register if
mATAErrFeaturesValid is set in
ataRegMask . For a read operation, your AIM
must read the ATA features register and put it in this
field if mATAErrFeaturesValid is set in
ataRegMask .
ataTFCount
- For a write operation, your AIM must write this field
to the ATA sector count register if
mATASectorCntValid is set in
ataRegMask . For a read operation, your AIM
must read the ATA sector count register and put it in
this field if mATASectorCntValid is set in
ataRegMask .
ataTFSector
- For a write operation, your AIM must write this field
to the ATA sector number register if
mATASectorNumValid is set in
ataRegMask . For a read operation, your AIM
must read the ATA sector number register and put it in
this field if mATASectorNumValid is set in
ataRegMask .
ataTFCylinderLo
- For a write operation, your AIM must write this field
to the ATA cylinder low register if
mATACylinderLoValid is set in
ataRegMask . For a read operation, your AIM
must read the ATA cylinder low register and put it in
this field if mATACylinderLoValid is set in
ataRegMask .
ataTFCylinderHi
- For a write operation, your AIM must write this field
to the ATA cylinder high register if
mATACylinderHiValid is set in
ataRegMask . For a read operation, your AIM
must read the ATA cylinder high register and put it in
this field if mATACylinderHiValid is set in
ataRegMask .
ataTFSDH
- For a write operation, your AIM must write this field
to the ATA SDH register if
mATASDHValid is
set in ataRegMask . For a read operation,
your AIM must read the ATA SDH register and put it in
this field if mATASDHValid is set in
ataRegMask .
ataTFCommand
- For a write operation, your AIM must write this field
to the ATA command register if
mATAStatusCmdValid is set in
ataRegMask . For a read operation, your AIM
must read the ATA status register and put it in this
field if mATAStatusCmdValid is set in
ataRegMask .
ataAltStatDevCnt
- For a write operation, your AIM must write this field
to the ATA device control register if
mATAAltSDevCValid is set in
ataRegMask . For a read operation, your AIM
must read the ATA alternate status register and put it in
this field if mATAAltSDevCValid is set in
ataRegMask .
Drive Identify
(kATAFnDriveIdentify)
ATA Manager issues this request to your AIM as the result
of a client's kATAMgrDriveIdentify request.
Your AIM is expected to execute an ATA drive identify
command (kATAcmdDriveIdentify ). This request is
very similar to a standard execute
I/O request except for the following:
- Your AIM must force the I/O to be byte swapped
(typically by setting
mATAFlagByteSwap in
ataPBFlags ).
- Your AIM must always attempt to transfer 512 bytes
(typically by overwriting the
Count field of
the ioObject with 512).
- Your AIM must always use a 512 byte logical block
size (typically be overwriting
ataPBLogicalBlockSize with 512).
- Your AIM must issue an ATA drive identify command
(typically by overwriting the
ataTFCommand
field of the ataPBTaskFile with
kATAcmdDriveIdentify and the
ataTFSDH of the ataPBTaskFile
with mATASectorSize ).
Once it has modified the parameter block in this way,
your AIM can simply pass this request through to the execute
I/O logic.
Execute ATAPI I/O (kATAPIFnExecIO)
Requests of this type should never be passed through to
your AIM. Your AIM should treat this as an unrecognized
function code.
ATAPI Command (kATAPIFnCmd)
Requests of this type should never be passed through to
your AIM. Your AIM should treat this as an unrecognized
function code.
Get Drive
Configuration (kATAFnGetDriveConfig)
ATA Manager issues this request to your AIM as the result
of a client's kATAMgrGetDrvConfiguration
request. Your AIM is expected to return information about a
device's current configuration. The bulk of the
ATAReqBlock is set up as
described above; only the fields specific to this
request are described here.
The structure of the devConfig field of the
ATAReqBlock is shown below.
struct ATADevConfig {
SInt32 ataConfigSetting;
UInt8 ataPIOSpeedMode;
UInt8 reserved;
UInt16 atapcValid;
UInt16 ataRWMultipleCount;
UInt16 ataSectorsPerCylinder;
UInt16 ataHeads;
UInt16 ataSectorsPerTrack;
UInt16 ataSocketNumber;
UInt8 ataSocketType;
UInt8 ataDeviceType;
UInt8 atapcAccessMode;
UInt8 atapcVcc;
UInt8 atapcVpp1;
UInt8 atapcVpp2;
UInt8 atapcStatus;
UInt8 atapcPin;
UInt8 atapcCopy;
UInt8 atapcConfigIndex;
UInt8 ataSingleDMASpeed;
UInt8 ataMultiDMASpeed;
UInt16 ataPIOCycleTime;
UInt16 ataMultiCycleTime;
UInt8 ataUltraDMASpeed;
UInt8 reserved2;
UInt16 ataUltraCycleTime;
UInt16 Reserved1[5];
};
typedef struct ATADevConfig ATADevConfig;
|
The fields have the following meaning:
ataConfigSetting
- Your AIM must set this field to indicate the device
configuration settings currently in use. The possible
values are defined in
ATA
Device Software for Macintosh Computers. On
completion of the request, ATA Manager copies this field
into the
ataConfigSetting field of the
client's request.
ataPIOSpeedMode
- Your AIM must set this field to indicate which PIO
models are enabled for this device. On completion of the
request, ATA Manager copies this field into the
ataPIOSpeedMode field of the client's
request.
reserved
- Reserved. You must not modify this field or depend on
its contents.
atapcValid
- Reserved. You must not modify this field or depend on
its contents. On completion of the request, ATA Manager
updates the
mATApcLockUnlock flag to
indicate whether the device is currently locked.
ataRWMultipleCount
ataSectorsPerCylinder
ataHeads
ataSectorsPerTrack
- Reserved. Your AIM must set these fields to
zero. On completion of the request, ATA Manager
copies this field into the corresponding fields of the
client's request.
ataSocketNumber
- Reserved. You must not modify this field or depend on
its contents. This field was used in previous versions of
ATA Manager (which handled much of the PC Card socket
configuration internally) but is now obsolete, replaced
by functionality in PC Card Manager.
ataSocketType
- Your AIM should ignore this field; on completion, ATA
Manager will set it based on your AIM's socket type.
ataDeviceType
- Your AIM must set this to the type of the device (for
example,
kATADeviceATA or
kATADeviceATAPI ) specified by the
devID and busID fields of the
ATAReqBlock . Typically your AIM returns a
copy of the information it derived during initialization
(MyAIMInit ) On
completion of the request, ATA Manager copies this field
into the ataDeviceType field of the client's
request.
atapcAccessMode
- Reserved. You must not modify this field or depend on
its contents. This field is obsolete with ATA Manager
4.0. It was previously defined to support different
access modes for PC Card devices but that support was
never implemented.
atapcVcc
atapcVpp1
atapcVpp2
atapcStatus
atapcPin
atapcCopy
atapcConfigIndex
- Reserved. You must not modify these fields or depend
on their contents. These fields were used in previous
versions of ATA Manager (which handled much of the PC
Card socket configuration internally) but are now
obsolete, replaced by functionality in PC Card Manager.
ataSingleDMASpeed
- Your AIM must set this field to indicate which
singleword DMA speeds are enabled for this device. On
completion of the request, ATA Manager copies this field
into the
ataSingleDMASpeed field of the
client's request.
ataMultiDMASpeed
- Your AIM must set this field to indicate which
multiword DMA speeds are enabled for this device. On
completion of the request, ATA Manager copies this field
into the
ataMultiDMASpeed field of the
client's request.
ataPIOCycleTime
- Your AIM must set this field to the current minimum
cycle time (in milliseconds) for mode 3 or greater PIO
transfers. On completion of the request, ATA Manager
copies this field into the
ataPIOCycleTime
field of the client's request.
ataMultiCycleTime
- Your AIM must set this field to the current minimum
cycle time (in milliseconds) for multiword DMA transfers.
On completion of the request, ATA Manager copies this
field into the
ataMultiCycleTime field of
the client's request.
ataUltraDMASpeed
- Your AIM must set this field to indicate which
UltraDMA speeds are enabled for this device. On
completion of the request, ATA Manager copies this field
into the
ataUltraDMASpeed field of the
client's request.
reserved2
- Reserved. You must not modify this field or depend on
its contents.
ataUltraCycleTime
- Your AIM must set this field to the current minimum
cycle time (in milliseconds) for UltraDMA transfers. On
completion of the request, ATA Manager copies this field
into the
ataUltraCycleTime field of the
client's request.
Reserved1
- Reserved. You must not modify this field or depend on
its contents.
Set Drive
Configuration (kATAFnSetDriveConfig)
ATA Manager issues this request to your AIM as the result
of a client's kATAMgrSetDrvConfiguration
request. Your AIM is expected to set the device's current
configuration based on the supplied parameter block. The
bulk of the ATAReqBlock is set up
as described above; only the
fields specific to this request are described here.
IMPORTANT:
To understand how your AIM should interpret the
various I/O mode and cycle time fields of this
request, see the ATA I/O
section, earlier in this document. |
The devConfig field of the
ATAReqBlock is
defined above. For a
kATAFnSetDriveConfig request, the fields have
the following meaning:
ataConfigSetting
- The ATA Manager sets this field to required device
configurations settings. The value is derived from the
ataConfigSetting field of the client
request. The possible values are defined in
ATA
Device Software for Macintosh Computers. Your AIM
must act on these configuration settings for all
subsequent I/O operations.
ataPIOSpeedMode
- The ATA Manager sets this field to required PIO speed
mode for the device. The value is derived from the
ataPIOSpeedMode field of the client request.
Your AIM must use this PIO speed for all subsequent PIO
transfers.
reserved
- Reserved. You must not modify this field or depend on
its contents.
atapcValid
- Reserved. You must not modify this field or depend on
its contents. This field was used in previous versions of
ATA Manager (which handled much of the PC Card socket
configuration internally) but is now obsolete, replaced
by functionality in PC Card Manager. Note that ATA
Manager still honors the
mATApcLockUnlock
flag in this field by calling your device lock
(MyAIMDeviceLock) routine
as part of handling a
kATAMgrSetDrvConfiguration request.
ataRWMultipleCount
ataSectorsPerCylinder
ataHeads
ataSectorsPerTrack
- Reserved. You must not modify this field or depend on
its contents.
ataSocketNumber
- Reserved. You must not modify this field or depend on
its contents. This field was used in previous versions of
ATA Manager (which handled much of the PC Card socket
configuration internally) but is now obsolete, replaced
by functionality in PC Card Manager.
ataSocketType
- Reserved. You must not modify this field or depend on
its contents.
ataDeviceType
- Reserved. You must not modify this field or depend on
its contents.
atapcAccessMode
- Reserved. You must not modify this field or depend on
its contents. This field is obsolete with ATA Manager
4.0. It was previously defined to support different
access modes for PC Card devices but that support was
never implemented.
atapcVcc
atapcVpp1
atapcVpp2
atapcStatus
atapcPin
atapcCopy
atapcConfigIndex
- Reserved. You must not modify these fields or depend
on their contents. These fields were used in previous
versions of ATA Manager (which handled much of the PC
Card socket configuration internally) but are now
obsolete, replaced by functionality in PC Card Manager.
ataSingleDMASpeed
- The ATA Manager sets this field to the required
singleword DMA speed modes for the device. The value is
derived from the
ataSingleDMASpeed field of
the client request. It is only valid if
ataModeType is kATAModeBitmap .
Your AIM may use these speeds for all subsequent
singleword DMA transfers.
ataMultiDMASpeed
- The ATA Manager sets this field to the required
multiword DMA speed modes for the device. The value is
derived from the
ataMultiDMASpped field of
the client request. It is only valid if
ataModeType is kATAModeBitmap .
Your AIM may use these speeds for all subsequent
multiword DMA transfers.
ataPIOCycleTime
- The ATA Manager sets this field to the required
maximum PIO cycle time for the device. The value is
derived from the
ataPIOCycleTime field of
the client request. It is only valid if
ataModeType is kATAModeBitmap .
Your AIM may use this, or a slower time, for subsequent
PIO transfers.
ataMultiCycleTime
- The ATA Manager sets this field to the required
maximum multiword DMA cycle time for the device. The
value is derived from the
ataMultiCycleTime
field of the client request. It is only valid if
ataModeType is kATAModeBitmap .
Your AIM may use this, or a slower time, for subsequent
multiword DMA transfers.
ataUltraDMASpeed
- The ATA Manager sets this field to the required
UltraDMA speed modes for the device. The value is derived
from the
ataUltraDMASpeed field of the
client request. It is only valid if
ataModeType is kATAModeBitmap .
Your AIM may use these speeds for all subsequent UltraDMA
transfers.
reserved2
- Reserved. You must not modify this field or depend on
its contents.
ataUltraCycleTime
- The ATA Manager sets this field to the required
maximum UltraDMA cycle time for the device. The value is
derived from the
ataUltraCycleTime field of
the client request. It is only valid if
ataModeType is kATAModeBitmap .
Your AIM may use this, or a slower time, for subsequent
UltraDMA transfers.
Reserved1
- Reserved. You must not modify this field or depend on
its contents.
Kill Current I/O
(kATAFnKillIO)
The ATA Manager issues this request to your AIM as part
of the process of removing your ATA
bus. You AIM must respond to this request by terminating
any hardware transaction on the ATA bus. This is an
immediate request: your AIM must complete the request before
returning from its action routine
(MyAIMAction ) and
must not call
ATAFamIODone for
the request.
IMPORTANT:
kATAFnKillIO is different from other
action requests in that none of the standard
ATAReqBlock fields are set up for
kATAFnKillIO . The only valid field in
the ATAReqBlock for a
kATAFnKillIO request is the function
code itself (ataFunctionCode ). |
Back to top
AIM Support Routines
This section describes the AIM support routines exported
by the ATA Manager for convenience of AIMs. Your AIM must
use the routines described below to signal the ATA Manager
that certain events have occurred.
ATAFamIODone
extern void ATAFamIODone(ATAReqBlock *theReq, OSStatus result);
|
theReq
| The action request to complete
|
result
| The final status of the request, either
noErr or a negative error code
|
Your AIM must call this routine to inform ATA Manager
that the AIM action request is complete. ATA Manager
executes the following steps:
- It copies information from the AIM request block
(
theReq ) into the client's ATA request
block.
- If stores
result in the
ataResult field of the client's request
block.
- It calls the client's completion routine, if one was
supplied.
- It dispatches the next ATA request, if any, to the
AIM's action routine.
You must call this routine from the context of your AIM's
action routine
(MyAIMAction ) or its
bus event handler
(MyAIMHandleBusEvent ).
ATAFamBusEventForAIM
extern void ATAFamBusEventForAIM(UInt32 busID, UInt32 aimData);
|
busID
| The ATA bus on which the event occurred
|
aimData
|
The bus event type; the ATA Manager does not
interpret this value, it simply passes it back to
your AIM's bus event handler
(MyAIMHandleBusEvent )
|
Your AIM must call this routine when it wants to
scheduled its bus event handler
(MyAIMHandleBusEvent )
to be executed. Typically it does this from a hardware
interrupt handler. ATA queues the bus event and calls your
AIM's bus event handler at the next opportune moment.
See AIM
Synchronization Model for an in-depth discussion of why
this is both necessary and convenient.
You may call this routine at any execution level.
References
Designing
PCI Cards and Drivers for Power Macintosh Computers
ATA
Device Software for Macintosh Computers
ATA
Device 0/1 Software Developer's Guide
DTS Technote 1098
ATA
Device Software Guide Additions and Corrections.
ANSI NCITS 317-1998 AT Attachment - 4 with
Packet Interface Extension
DTS Technote 1094
Virtual
Memory Application Compatibility
DTS Q&A DV 34
Secondary
Interrupts on the Page Fault Path
Back to top
Downloadables
|
Acrobat version of this Note (128K).
|
Download
|
|
AIM Interfaces and Libraries (8 KB)
|
Download
|
Back to top
|