Showing changes from revision #6 to #7:
Added | Removed | Changed
The device descriptor starts with a fixed format header, as described below. Following this header are more function pointers providing device-specific calls.
struct device { uint16_t type; // + 0 uint16_t id; // + 2 uint32_t location; // + 4 uint32_t version; // + 8 const char *description; // + 12 void *address; // + 16 uint32_t reserved1[3]; // + 20 bool (*Activate)(struct device *); // + 32 void (*Deactivate)(struct device *); // + 36 void (*Reset)(struct device *); // + 40 int32_t (*Sleep)(struct device *, int32_t state); // + 44 int32_t devicenumber; // + 48 bool (*TestIRQ)(struct device *); // + 52 void (*ClearIRQ)(struct device *); // + 56 uint32_t reserved2[1]; // + 60 };
Hence, the first device specific function pointer is offset 32 bytes from the device pointer.
The type word describes what the device is.
This half-word, together with the version number, indicate which device specific calls are available.
16-bit product code – a unique identifier for this particular device. Note that the ID is only unique within the context of the device type; two devices of different types may share the same ID.
The location describes the location of the device in terms of the bus architecture of the computer. Again, it is grouped by bytes.
The version describes the version of the device API implemented. It consists of a major version number (bits 31-16) and a minor version number (bits 15-0). A change in major version number indicates an incompatible change of API. An increase in the minor version number indicates backwards-compatible extensions to the API (eg extra functions).
A textual description of the device. This should be English, human-readable and Basic Latin (characters &20-&7E). Descriptors along the lines of those output by *Podules are expected. For example:
This field may either be 0, or may be a pointer to the logical base address of the memory-mapped registers of the device in question. Drivers should not normally use this field to directly poke the device. If they do, they must be absolutely certain that there is no other way to achieve the effect, and that the device type word is known to them. What exactly the address points to depends on the exact device in question.
A device driver must call the Activate entry point before using a device. A success/failure indication is returned: 1 indicates successful activation, 0 indicates unsuccessful. Devices may ignore activate/deactivate calls, count them, or may alternatively provide full locking to allow only one activation. Typically this would be called by in a driver’s module initialisation routine. Alternatively, it might be called just before a DeviceFS device is opened for access.
A device driver must call the Deactivate entry point when it has finished using a device.
The Kernel will call the Reset entry point of every device on the system before performing a software reset (eg OS_Reset or Ctrl-Break), after it has issued Service_PreReset. All devices must enter a quiescent state.
This call reads or sets a device’s power-down state. If the second parameter is -1, then the current state is returned; otherwise the second parameter must be a value in the range 0-255 giving sleepiness (0 = full power, 255 = off) and the old sleepiness is returned. Note that the value returned does not have to match the last value programmed: for example, if a device cannot power down, it will always return 0.
If this is -1, then the device has no associated interrupt. Otherwise, bits 0-23 give the device number and bit 31 flags that the device vector is shared, ie this is the R0 that should be passed to OS_ClaimDeviceVector. If bit 31 is set then the TestIRQ routine must be used to determine whether the vector should be claimed or passed on.
Returns 0 if the device is not interrupting, or 1 if the device is interrupting. When DeviceNumber is -1, this must be a null pointer.
This entry point should be called after your code has serviced any interrupt generated by the device, but before HAL_IRQClear is called. This allows the HAL device implementation to perform any extra processing required to handle the interrupt, e.g. if the IRQ had been routed through an intermediate interrupt controller, such as the OMAP3 GPIO controller.
This is an optional entry point, and thus should only be called if it’s not a null pointer. Additionally, since the entry point was added after the first version of the HAL device API was introduced, do not assume that any device-specific APIs supports the ClearIRQ entry unless it is explicitly listed as supported.
Reserved fields should be set to zero.