Kernel callout categories
The startup library provides kernel callouts that look after different categories of tasks. You can use these callouts as models when you write your own.
Source code
The source code for kernel callouts is found in the BSP source code directories, originally installed in bsp_working_dir/src/hardware/startup/lib/. This directory and its subdirectories include generic code as well as processor-specific kernel callouts. Before you begin writing a kernel callout, check these directories to see if a callout is already available:
- for your device or board (no need to write a kernel callout)
- for a device similar to your device or board (you need to modify the similar kernel callout)
In the CPU-dependent level of the source file tree, look for files with names that match the pattern: callout_*.[sS]. These files are the callouts provided by the startup library. Whether a file ends in .s or .S depends on whether it's sent through the C preprocessor before being handed off to an assembler. For simplicity, we'll simply refer to both types as .s files.
The filenames break down further as follows: callout_category_device.s, where category is one of:
debug(kernel debug)interrupt(interrupt controller)timer(timer and clock)reboot(system reboot)power(power management; not currently supported)cache(cache control)
and where device identifies the unique hardware the callouts were written for.
Typically, the kernel uses all or none of the callouts in a particular source file. For example, the callout_debug_8250.s file contains the display_char_8250(), poll_key_8250(), and break_detect_8250() kernel callouts, which are all used for working with an 8250-style UART chip.
For more information, see Writing a kernel callout
in this chapter.
Macros for kernel callouts
All kernel callouts use macros found in callout.ah to define their start and end. For example, the following excerpt describes the interrupt_id_405() kernel callout:
CALLOUT_START interrupt_id_405, 0, 0
li %r14,-1
mfdcr %r5,PPC405_DCR_UIC0_MSR
...
andc %r4,%r4,%r5
mtdcr PPC405_DCR_UIC0_ER,%r4
1:
CALLOUT_END interrupt_id_405
The CALLOUT_START parameters specify the following information:
- The name of the kernel callout (for example, interrupt_id_405)
- The address of a variable that specifies the amount of static read/write storage the callout requires, or 0, if no storage is required
- The name of a patch routine that modifies the callout code after the startup code copies it to kernel memory, or 0, if the callout requires no patch routine
CALLOUT_END specifies the CALLOUT_START to match (for example, interrupt_id_405).
For more information, see
Kernel callout start and end macros
and
Patching the kernel callout code
in this chapter.
Patch routines
Kernel callout code references addresses using routines that edit code after it has been copied into system memory. When a callout uses one of these routines, it is specified using the CALLOUT_START constant. If the callout code only needs to access CPU registers, a patch routine is not required.
For example, in the following excerpt from a display_char() kernel
callout, the CALLOUT_START macro's third argument invokes the routine
patch_debug(). This routine replaces the
0x1234 and 0x5678 memory locations with the
base address of the serial controller register:
CALLOUT_START display_char_5200, 0, patch_debug
lis %r6,0x1234
ori %r6,%r6,0x5678
For further discussion of when these routines are necessary, see Patching the kernel callout code
in this chapter.
