Aug 97 - Macintosh Q and A
Volume Number: 13
Issue Number: 8
Column Tag: develop
Macintosh Q & A
by Apple Developer Support Center
Q: I'm debugging my PCI native driver and notice that the dCtlFlags
field of my Device Control Entry (DCE) has some undocumented bits set.
What do these flags mean?
A: The current bits in the dCtlFlags field of the DCE are:
• bit 0 - VMImmune - This bit indicates that your device driver is VM safe.
See Technote NW 13
http://devworld.apple.com/dev/technotes/nw/nw_13.html for details.
• bit 1 - reserved.
• bit 2 - kmDriverGestaltEnableMask (in "DriverGestalt.h") is set if the
driver supports the Driver Gestalt mechanism. See Designing PCI Cards and
Drivers for Power Macintosh Computers for a description of Driver Gestalt.
• bit 3 - Native Driver - Set if the driver is a native driver (ndrv). The
system will set this bit when it loads your native driver.
• bit 4 - Concurrent - Set if the native driver supports concurrent
operation. When loading a native driver, the system sets this bit based on the
kDriverIsConcurrent field of the driverOSRuntimeInfo.driverRuntime field of
your DriverDescription. See Designing PCI Cards and Drivers for Power
Macintosh Computers for a description of concurrent drivers.
• bit 5 - dOpenedMask (in "Devices.h") is set if the driver is open.
• bit 6 - dRAMBasedMask (in "Devices.h") is set if the dCtlDriver field is a
DRVRHeaderHandle rather than aDRVRHeaderPtr.
• bit 7 - drvrActiveMask (in "Devices.h") is set if the driver is currently
processing a request.
• bit 8 - dReadEnableMask (in "Devices.h") is set if the driver handles
_Read requests.
• bit 9 - dWritEnableMask (in "Devices.h") is set if the driver handles
_Write requests.
• bit 10 - dCtlEnableMask (in "Devices.h") is set if the driver handles
_Control requests.
• bit 11 - dStatEnableMask (in "Devices.h") is set if the driver handles
_Status requests.
• bit 12 - dNeedGoodByeMask (in "Devices.h") is set if the driver needs a
"goodbye" _Control call before the application heap is reinitialized.
• bit 13 - dNeedTimeMask (in "Devices.h") is set if the driver wants
periodic SystemTask time through the "accRun" _Control call.
• bit 14 - dNeedLockMask (in "Devices.h") is set if the driver requires
that its DCE and code be locked at all times when the driver is open.
• bit 15 - reserved.
See Inside Macintosh: Devices for more information about bits 5 through to 14.
______________________________
Q: I'm calling the serial driver to clear XON/XOFF flow control but flow
control is not being lifted. What's going on?
A: You have stumbled across a bug in Apple system software (ID 1635221). The File
System Manager patches _Control in such a way that the serdClrXOff (csCode = 22) is
mistaken for a block device "Return Media Icon" (csCode = 22) call. This causes the
serdClrXOff to never make it to the serial driver.
The simplest workaround is to clear ioVRefNum before making the serdClrXOff call.
The following code snippet demonstrates this technique:
OSErr DoClearXOff(short serialOutDrvrRefNum)
{
CntrlParam pb;
pb.ioCRefNum = serialOutDrvrRefNum;
pb.csCode = serdClrXOff;
pb.ioVRefNum = 0;
// This above line is required because of a bug
// in system software. The workaround, clearing
// ioVRefNum, should be benign when the bug is fixed
// in future systems.
return ( PBControlSync( (ParmBlkPtr) &pb ) );
}
______________________________
Q: Sometimes, MacsBug generates a PowerPC unmapped memory
exception with an address that starts with the symbol
BowelsOfTheMemoryMgr. What does this mean?
A: When you are displaying addresses in Macsbug, MacsBug shows offsets from the last
symbol it can find. In the Modern Memory Manager on Power Macintosh computers up
to MacOS version 7.6, the last symbol was __HSetStateQ. The code after __HSetStateQ
consists of various internal Memory Manager subroutines. So, if there's a hang or
crash in an internal Memory Manager subroutine, it shows up in MacsBug as
__HSetStateQ+xxxxxxxx.
Various system software engineers were tired of seeing bug reports that said
__HSetStateQ was crashing, so beginning with MacOS 7.6, we decided to add a new last
symbol to the Memory Manager. As a consequence, bug reports would be somewhat
more informative. We thought of naming the new symbol YourHeapIsCorrupt (since
that's usually the case when a program crashes the Memory Manager) but decided on
BowelsOfTheMemoryMgr instead because that's where you are.
So if you're crashing or hanging at BowelsOfTheMemoryMgr+xxxxxxxx, type HC to see
if your heap is corrupted (it probably will be) and then start debugging your code to
find out how it got corrupted.
______________________________
Q: What are the different Gestalt selectors for Macintosh networking?
A: Here is the breakdown:
MacTCP
The Gestalt selector for MacTCP is 'mtcp'.
• MacTCP versions 1.0 through 1.0.3 did not register this selector.
• MacTCP version 1.1 returns a value of 1.
• MacTCP version 1.1.1 returns a value of 2.
• MacTCP version 2.0 returns a value of 3.
A value of 0 is returned if the driver is not opened.
AppleTalk
The Gestalt selectors for AppleTalk are 'atkv' and 'atlk'. The 'atlk' Gestalt selector was
introduced in AppleTalk version 54 to provide basic version information. Calling
Gestalt with the 'atlk' selector provides the major revision version in the low-order
byte of the function result. For example, passing the 'atlk' selector in a Gestalt call or
through MacsBuG with a result of 0x0000003C means that AppleTalk version 60 is
present. (Please note that the 'atlk' selector is not available when AppleTalk is turned
off in the Chooser.)
The 'atkv' Gestalt selector was introduced as an alternative in AppleTalk version 56 to
provide more complete version information via the 'vers' resource. For example,
passing the 'atkv' selector to AppleTalk version 60 through a Gestalt call or MacsBuG
yields the following LONGINT result: 0x3C108000.
Open Transport
The Gestalt selectors for Open Transport are 'otan' and 'otvr'. You can test whether
Open Transport and its various parts are available by using the Gestalt function with
the 'otan' selector. The bits currently used are defined by constants, defined in
OpenTransport.h and shown below.
enum {
gestaltOpenTpt = 'otan',
gestaltOpenTptPresent = 0x00000001,
gestaltOpenTptLoaded = 0x00000002,
gestaltOpenTptAppleTalkPresent = 0x00000004,
gestaltOpenTptAppleTalkLoaded = 0x00000008,
gestaltOpenTptTCPPresent = 0x00000010,
gestaltOpenTptTCPLoaded = 0x00000020,
gestaltOpenTptNetwarePresent = 0x00000040,
gestaltOpenTptNetwareLoaded = 0x00000080
};
If Gestalt returns no error and responds with a non-zero value, Open Transport is
available. To find out whether OT, AppleTalk, TCP, or NetWare are present, you can
examine the response parameter bits as shown above. For example, passing the 'otan'
selector in a Gestalt call or through MacsBuG with a result of 0x0000001F means that
the Open Transport is present and loaded, AppleTalk driver is also present and loaded,
and MacTCP is present but NOT loaded.
The 'otvr' selector is used to determine the Open Transport Version in NumVersion
format. For example, passing the 'otvr' selector through a Gestalt call or MacsBuG to
OT version 1.1.1b9 yields the following LONGINT result: 0x01116009. (Note that OT
versions 1.0 through 1.0.8 did not register this selector.) For more information on
Apple's Version Numbering Scheme and NumVersion format, please see Technote OV12:
Version Territory.
Open Transport/PPP
The Gestalt selectors for Open Transport/PPP are 'otra' and 'otrv'. You can test
whether Open Transport/PPP and its various parts are available by using the Gestalt
function with the 'otra' selector. The bits currently used are defined by constants,
defined in OpenTptPPP.h check OT/PPP SDK and shown below.
enum {
gestaltOpenTptRemoteAccess = 'otra',
gestaltOpenTptRemoteAccessPresent = 0x00000000,
gestaltOpenTptRemoteAccessLoaded = 0x00000001,
gestaltOpenTptRemoteAccessClientOnly = 0x00000002,
gestaltOpenTptRemoteAccessPServer = 0x00000003,
gestaltOpenTptRemoteAccessMPServer = 0x00000004,
gestaltOpenTptPPPPresent = 0x00000005,
gestaltOpenTptARAPPresent = 0x00000006
};
Note: If you are writting an control strip or startup item that uses
OpenTransport/PPP, you should be aware that it takes a few event cycles for the
remote access software to complete loading. Your software should check the
gestaltOpenTptRemoteAccessPresent bit of the 'otra' gestalt to see if remote access
software is present, then periodicaly check the gestaltOpen TptRemoteAccessLoaded to
determine if loading is completed.
More information on acessing using the Open Transport/PPP API is available in the
Open Transport/PPP Developer Note found at the OpenTransport web site's Reference
and Technical Documentation section (found at
http://17.126.23.20/dev/opentransport/reference.html).
Open Transport/Modem
The Gestalt selectors for Open Transport/Modem are 'otmo' and 'otmv'. You can test
whether Open Transport/Modem and its various parts are available by using the
Gestalt function with the 'otmo' selector.
enum {
gestaltOpenTptModem = 'otmo',
gestaltOpenTptModemPresent = 0x00000000
};
______________________________
Q: I'm writing an Open Transport module that conforms to the
Transport Provider Interface (TPI). I find that OT passes data to my TPI
using M_DATA message blocks, rather than M_PROTO message blocks
with PRIM_type being T_DATA_REQ. What's going on?
A: The answer can be found at the bottom of the description of T_DATA_REQ (7tpi) in
Appendix A-2 of STREAMS Modules and Drivers (Unix Press, ISBN
0-13-066879-6):
The transport provider must also recognize a message of one or more M_DATA message
blocks without the leading M_PROTO message block as a T_DATA_REQ primitive. This
message type will be initiated from the write (BA_OS) operating system service
routine.
Open Transport deliberately uses this variant behavior as an optimization. By using
M_DATA, Open Transport avoids allocating a buffer for the M_PROTO header. As every
memory allocation takes time, avoiding this one makes the system faster.
This behavior isn't seen on expedited data because the specification doesn't allow for
this optimization on T_EXDATA_REQ.
______________________________
Q: If my web server is running along happily under Open Transport
(1.1 or 1.1.1), and the listener was bound to address 0.0.0.0, what
happens when someone uses the control panel and changes the IP
number? Right now it appears to just make the listener go deaf. I don't
appear to receive connections on the new IP number, and if I use the
control panel a second time to switch back to the original IP number, I
don't get connections for that IP number either.
Is there some event that gets sent to the listener that I'm not looking
for that tells me when this happens?
A: When an port changes its IP number, it is actually closing and re-opening. When
Open Transport closes a port, any endpoint that is plumbed to it is also closed, hence
you will get no further events on that endpoint.
The first thing you need to do is check for the provider events such as
kOTProviderWillClose and kOTProviderIsClosed.
You should also use the OTRegisterAsClient call and register a notifier for client
events, such as kOTPortDisabled, kOTPortEnabled, kOTPortOffline, kOTPortOnline,
kOTClosePortRequest, kOTYieldPortRequest, kOTNewPortRegistered.
You need to close up your endpoints and rebind them when the interface changes.
______________________________
Q: I'm trying to call the Control Strip routines
SBIsControlStripVisible() and SBShowHideControlStrip() defined in the
header file . When I try to link the PowerPC code, I get
a link error on these routines. Which library are they implemented in?
A: There is no PowerPC library for Control Strip calls. As a consequence, you must
create a routine descriptor and perform a Mixed Mode call to the 68K library.
The following is an example of how you can call the Control Strip routines from
PowerPC code:
/* Defined in current Universal Header */
#ifndef _ControlStripDispatch
enum {
_ControlStripDispatch = 0xAAF2
};
#endif
#if GENERATINGCFM
/* */
/* If we're not generating CFM, then assume the */