Copyright ©1995 by NeXT Computer, Inc.  All Rights Reserved.

IODevice



Inherits From: Object
Declared In: driverkit/IODevice.h



Class Description

IODevice is an abstract class that is the superclass of all device driver classes. Functionality provided by IODevice includes:

Standard driver startup and connection to driver objects
Standard ways of getting and setting driver parameters
Getting and setting standard information such as the instance's unit number
Mapping IOReturn values to strings and to UNIX error numbers
Adding and removing drivers from UNIX device switch tables
Getting the Driver Kit version that the IODevice was compiled under


Getting and Setting Parameters

The IODevice methods getCharValues:forParameter:count:, getIntValues:forParameter:count:, setIntValues:forParameter:count:, and setCharValues:forParameter:count: provide a general, extensible means for user-level programs to get and set device-specific parameters for drivers that reside in the kernel. The general scheme is as follows:

A parameter's value is either an array of ints or an array of chars. The maximum number of elements in a parameter array is IO_MAX_PARAMETER_ARRAY_LENGTH, a system constant (currently 512 though you shouldn't count on this value).
Parameters are specified with human-readable strings. For example, the parameter for getting an IODevice's unit number is named "IOUnit" and defined as the constant IO_UNIT.
Any subclass of IODevice can define any parameters it wishes. Any class that does so must implement the appropriate methods by which the parameters can be accessed (getIntValues:..., for example). If such a method is invoked with a parameter name that the class does not recognize, the method invocation should be passed up to super. If no classes recognize the parameter name, IODevice returns IO_R_UNSUPPORTED.
By sending messages to an IODeviceMaster object, a user program can find the desired instance of a device driver and get or set device-specific parameters.


Implementing a Subclass

Subclasses of IODevice that are indirect or direct device drivers must implement the following methods:

+ deviceStyle
+ probe:
initFromDeviceDescription:

Indirect device drivers also need to implement the requiredProtocols class method.

Note:  If your class's direct superclass isn't IODevice, check the documentation for the superclass--it may implement some or all of these methods for you.

During initialization, indirect and direct drivers must invoke the following methods:

registerDevice
setDeviceKind:
setLocation:
setName:

The registerDevice method should be invoked at the end of initialization. Generally, indirect and direct drivers also invoke setUnit:.



Instance Variables

None declared in this class.



Method Types

Creating, initializing, and freeing instances
+ probe:
init
initFromDeviceDescription:
free
Registering the class + deviceStyle
+ registerClass:
+ unregisterClass:
+ requiredProtocols
Registering the instance registerDevice
unregisterDevice
Getting and setting standard information
setDeviceKind:
deviceKind
setLocation:
location
setName:
name
setUnit:
unit
Converting an IOReturn value + stringFromReturn:
stringFromReturn:
errnoFromReturn:
Adding and removing the driver from UNIX device switch tables
+ addToBdevswFromDescription:open:close:strategy: dump:psize:isTape:
+ addToCdevswFromDescription:open:close:read:write: ioctl:stop:reset:select:mmap:getc:putc:
+ blockMajor
+ characterMajor
+ removeFromBdevsw
+ removeFromCdevsw
+ setBlockMajor:
+ setCharacterMajor:
Getting the Driver Kit version of the IODevice
+ driverKitVersion
+ driverKitVersionForDriverNamed:
Getting and setting parameter values
setCharValues:forParameter:count:
getCharValues:forParameter:count:
setIntValues:forParameter:count:
getIntValues:forParameter:count:



Class Methods

addToBdevswFromDescription:open:close:strategy:dump:psize:isTape:
+ (BOOL)addToBdevswFromDescription:(id)deviceDescription
open:(IOSwitchFunc)openFunc
close:(IOSwitchFunc)closeFunc
strategy:(IOSwitchFunc)strategyFunc
dump:(IOSwitchFunc)dumpFunc
psize:(IOSwitchFunc)psizeFunc
isTape:(BOOL)isTape

Adds the specified values to the bdevsw table. Drivers that have UNIX block entry points should use this method during initialization.

The major number to use is taken from the value of the "Block Major" key in the class's configuration table. If "Block Major" isn't specified, the first available major number is used. If the entry is successfully added, this method invokes setBlockMajor:.

If the entry was successfully added, this method returns YES; otherwise, it logs an error message and returns NO.

See also:  + blockMajor, + addToCdevswFromDescription:open:close:read:write:
ioctl:stop:reset:select:mmap:getc:putc:



addToCdevswFromDescription:open:close:read:write:ioctl:stop:reset:select:mmap:getc:putc:
+ (BOOL)addToCdevswFromDescription:(id)deviceDescription
open:(IOSwitchFunc)openFunc
close:(IOSwitchFunc)closeFunc
read:(IOSwitchFunc)readFunc
write:(IOSwitchFunc)writeFunc
ioctl:(IOSwitchFunc)ioctlFunc
stop:(IOSwitchFunc)stopFunc
reset:(IOSwitchFunc)resetFunc
select:(IOSwitchFunc)selectFunc
mmap:(IOSwitchFunc)mmapFunc
getc:(IOSwitchFunc)getcFunc
putc:(IOSwitchFunc)putcFunc

Adds the specified values to the cdevsw table. Drivers that have UNIX character entry points should use this method during initialization.

The major number to use is taken from the value of the "Character Major" key in the class's configuration table. If "Character Major" isn't specified, the first available major number is used. If the entry is successfully added, this method invokes setCharacterMajor:.

If the entry was successfully added, this method returns YES; otherwise, it logs an error message and returns NO.

See also:  + characterMajor, + addToBdevswFromDescription:open:close:strategy:
dump:psize:isTape:



blockMajor
+ (int)blockMajor

Returns the block major number associated with this driver, or 1 if this driver has no block major number. The block major number is set using setBlockMajor:, which is invoked by addToBdevswFromDescription....



characterMajor
+ (int)characterMajor

Returns the character major number associated with this driver, or 1 if this driver has no character major number. The character major number is set using setCharacterMajor:, which is invoked by addToCdevswFromDescription....



deviceStyle
+ (IODeviceStyle)deviceStyle

Implemented by subclasses to return the basic style of driver (IO_DirectDevice, IO_IndirectDevice, or IO_PseudoDevice). The meaning of direct, indirect, and pseudo device drivers is discussed in Chapters 1 and 2.

See also:  + deviceStyle (IODirectDevice)



driverKitVersion
+ (int)driverKitVersion

Returns the version of the currently running DriverKit objects. The Driver Kit compares this value to the value returned by driverKitVersionForDriverNamed: to determine whether the driver is compatible with the driver environment.



driverKitVersionForDriverNamed:
+ (int)driverKitVersionForDriverNamed:(char *)driverName

Returns the version of the Driver Kit that the specified driver was compiled for. The Driver Kit compares this value to the value returned by driverKitVersion to determine whether the driver is compatible with the driver environment.



probe:
+ (BOOL)probe:(id)deviceDescription

Does nothing and returns NO. This method is invoked by the kernel (in the context of the kernel I/O task) to conditionally instantiate an instance of an IODevice subclass.

This method should be implemented by every direct and indirect driver. It should determine whether it needs to instantiate itself, examining the hardware if appropriate. It should then allocate and initialize all the necessary instances for the specified deviceDescription. Should return YES if any IODevice objects were created; otherwise, this method should return NO.

See Chapter 1 for information on when probe: is invoked.

See also:  initFromDeviceDescription:



registerClass:
+ (void)registerClass:aClass

Adds the specified class to the kernel list of device driver classes.

See also:   + unregisterClass:



removeFromBdevsw
+ (BOOL)removeFromBdevsw

Removes the driver's entry from the bdevsw table. This method finds the driver's entry in the table by invoking blockMajor. If blockMajor is 1, this method does nothing and returns NO. Otherwise, this method sets the block major number to 1 (using setBlockMajor:) and returns YES.



removeFromCdevsw
+ (BOOL)removeFromCdevsw

Removes the driver's entry from the cdevsw table. This method finds the driver's entry in the table by invoking characterMajor. If characterMajor is 1, this method does nothing and returns NO. Otherwise, this method sets the character major number to 1 (using setCharacterMajor:) and returns YES.



requiredProtocols
+ (Protocol **)requiredProtocols

Returns NULL. Indirect device drivers should implement this method to return a NULL-terminated list of the protocols to which associated drivers must conform. Kernel-level indirect devices must implement this.



setBlockMajor:
+ (void)setBlockMajor:(int)bmajor

Sets the driver's block major number. You usually don't have to invoke this, since it's invoked by addToBdevswFromDescription:....



setCharacterMajor:
+ (void)setCharacterMajor:(int)cmajor

Sets the driver's character major number. You usually don't have to invoke this, since it's invoked by addToCdevswFromDescription:....



stringFromReturn:
+ (const char *)stringFromReturn:(IOReturn)returnValue

Returns a text string that describes the specified IOReturn value.

See also:  stringFromReturn:



unregisterClass:
+ (void)unregisterClass:classId

Removes the specified class from the kernel list of device driver classes. This method is invoked when a class is being removed from the address space of a program such as the kernel.

See also:  + registerClass:



Instance Methods

deviceKind
(const char *)deviceKind

Returns a string that identifies the object in general terms. For example, IOSCSIDisk objects return "SCSIDisk". See the description of setDeviceKind: for more information.

See also:  setDeviceKind:



errnoFromReturn:
(int)errnoFromReturn:(IOReturn)returnValue

Returns a UNIX error number that corresponds to the specified IOReturn value. Subclasses that add additional IOReturn values should override this method and send an errnoFromReturn: to super for IOReturn values that the subclass doesn't handle.



free
free

Frees resources used by the IODevice and returns nil.



getCharValues:forParameter:count:
(IOReturn)getCharValues:(unsigned char *)array forParameter:(IOParameterName)parameter
count:(unsigned int *)count

Gets the array of character values associated with parameter. IODevice accepts the following character parameters: IO_CLASS_NAME (which returns [[self class] name]), IO_DEVICE_NAME (which returns [self name]), and IO_DEVICE_KIND (which returns [self deviceKind]).

Subclasses should override this method if they support parameters not understood by the superclass. Here's an example of overriding this method:

- (IOReturn)getCharValues   : (unsigned char *)parameterArray
forParameter : (IOParameterName)parameterName
count : (unsigned int *)count
{
const char  *param;
unsigned int length;
unsigned int maxCount = *count;

if(strcmp(parameterName, my_PARAMETER_NAME) == 0){
param = _myParameter;  /* _myParameter is an instance var */
length = strlen(param);
if(length >= maxCount) {
length = maxCount - 1;
}
*count = length + 1;
strncpy(parameterArray, param, length);
parameterArray[length] = '\0';
return IO_R_SUCCESS;
}
else {
/* Pass parameters we don't recognize to our superclass. */
return [super getCharValues:parameterArray
forParameter:parameterName count:count];
}
}

Returns IO_R_SUCCESS if parameter is a valid parameter with character values that can be read; otherwise, returns IO_R_UNSUPPORTED.

See also:  getIntValues:forParameter:count:, setCharValues:forParameter:count:



getIntValues:forParameter:count:
(IOReturn)getIntValues:(unsigned int *)array forParameter:(IOParameterName)parameter
count:(unsigned int *)count

Returns IO_R_UNSUPPORTED. Subclasses should implement this method if necessary to return (in array) the array of integer values associated with parameter. See getCharValues:forParameter:count: for an example of implementing this kind of method. This method should return IO_R_SUCCESS if parameter is a valid parameter with integer values that can be read; otherwise, it should return IO_R_UNSUPPORTED.

See also:  getCharValues:forParameter:count:, setIntValues:forParameter:count:



init
init

Initializes and returns a newly allocated IODevice. Returns self if successful; otherwise, returns nil.

Note:  Direct and indirect drivers should use initFromDeviceDescription: instead of this method.



initFromDeviceDescription:
initFromDeviceDescription:deviceDescription

Does nothing and returns self. Subclasses that implement this method should have it initialize and return a newly allocated instance of the subclass, using the information from deviceDescription. This method should return nil on error.

See also:  initFromDeviceDescription: (IODirectDevice)



location
(const char *)location

Returns the device-specific location of the IODevice--for example, "0xf7f04000". See the description of setLocation: for information on how this location is used.

See also:  setLocation:



name
(const char *)name

Returns the device-specific name of the IODevice--for example, "sd0a". See the description of setName: for information on how the name is used.

See also:  setName:



registerDevice
registerDevice

Registers the IODevice in the current name space and adds a string to the system log that announces the device's registration. The IODevice must be ready to perform I/O, its name must have been set already using setName:, and its location (set with setLocation:) must be either valid or NULL.

This method also probes all indirect IODevices that require this object's protocols, giving them a chance to connect to this object.

Each IODevice should invoke this method at the end of its initialization. Returns self.

Note:  I/O can begin before this method returns.

See also:  unregisterDevice



setCharValues:forParameter:count:
(IOReturn)setCharValues:(unsigned char *)array forParameter:(IOParameterName)parameter
count:(unsigned int)count

Returns IO_R_UNSUPPORTED. Subclasses should implement this method if necessary to set (from array) the array of character values associated with parameter. See getCharValues:forParameter:count: for an example of implementing this kind of method. This method should return IO_R_SUCCESS if parameter is a valid parameter with character values that can be written; otherwise, it should return IO_R_UNSUPPORTED.

See also:  setIntValues:forParameter:count:, getCharValues:forParameter:count:



setDeviceKind:
(void)setDeviceKind:(const char *)type

Sets a string that identifies the object in general terms. For example, IOFrameBufferDisplay objects have a device kind of "Linear Framebuffer". The string should be no longer than IO_STRING_LENGTH 1 characters. The standard parameter name IO_DEVICE_KIND refers to this string.

See also:  deviceKind



setIntValues:forParameter:count:
(IOReturn)setIntValues:(unsigned int *)array forParameter:(IOParameterName)parameter
count:(unsigned int)count

Returns IO_R_UNSUPPORTED. Subclasses should implement this method if necessary to set (from array) the array of character values associated with parameter. See getCharValues:forParameter:count: for an example of implementing this kind of method. This method should return IO_R_SUCCESS if parameter is a valid parameter with integer values that can be written; otherwise, it should return IO_R_UNSUPPORTED.

See also:  setCharValues:forParameter:count:, getIntValues:forParameter:count:



setLocation:
(void)setLocation:(const char *)location

Sets the device-specific location of the IODevice--for example, "0xf7f04000". If the location is irrelevant, its value should be set to NULL. The location is used in the system log when this object is registered and unregistered.

See also:  location



setName:
(void)setName:(const char *)name

Sets the device-specific name of the IODevice--for example, "sd0a". The name should be no longer than IO_STRING_LENGTH 1 characters.

The specified name is used to identify this instance. For example, it's used in the system log when this object is registered and unregistered, and it's used by the UNIX command iostat. The name is also used by user-level programs to find this object, using the IODeviceMaster method lookUpByDeviceName:objectNumber:deviceKind:. The standard parameter name IO_DEVICE_NAME refers to this string.

See also:  name



setUnit:
(void)setUnit:(unsigned int)unit

Sets the IODevice's unit number, a device-specific number that can be used like a UNIX minor number.

See also:  unit



stringFromReturn:
(const char *)stringFromReturn:(IOReturn)returnValue

Returns the text string that corresponds to the specified IOReturn value. Subclasses that add additional IOReturn values should override this method and invoke stringFromReturn: against the superclass for IOReturn values that the subclass doesn't handle.

See also:  + stringFromReturn:



unit
(unsigned int)unit

Returns the IODevice's unit number, a device-specific number that can be used like a UNIX minor number.

See also:  setUnit:



unregisterDevice
(void)unregisterDevice

Removes the IODevice from the current name space.

See also:  registerDevice