Last update: 1999.8.22
This article discusses APM in BeOS R4 for x86. Assumes knowledge about the 386 architecture (IA-32) and the APM BIOS.
Although APM is not supported in BeOS R4, a set of routines to initialize and call the APM BIOS is in fact provided in the kernel and device drivers can utilize it. However, it is virtually useless since no event handling is performed at all. In addition, some APM BIOS implementations may cause a fault during BIOS calls. Practically, the device driver has to compensate such flaws.
APM BIOS function names are shown in  below.
APM related APIs call the APM BIOS in the BIOS ROM using segment information obtaind in the boot time. Some APM BIOS implementations, when called, can cause an exception and the system may fall down to the kernel debugger. Below are actual examples the author faced.
GA-686BX's APM BIOS does not return the segment sizes of 32-bit/16-bit code segments in the ESI register in [APM Protected Mode 32-bit Interface Connect], though it declares APM 1.2 conformance. Therefore, values that happened to be in ESI at that time will be used later in constructing segment descriptors. If the values are smaller than actual code segment sizes, execution may exceed the code segment limit and cause segmentation fault.
I dealt with this problem by making the code segment sizes bigger in constructing segment descriptors if the values are too small and seem to be invalid.
ThinkPad 535's APM BIOS allocates its data segment at the last 1KB of conventional memory (9FC00H) and accesses here when called. In protected mode, the caller must set up the page table appropriately so that the APM data segment's base address (in linear address) is mapped to this physical address. However, apm_init() does not do it and uses the data segment's physical address obtained from the APM BIOS as the data segment's base address, regarding it as linear address. This would be okay if the linear address and the physical address were same, but actually this does not appear true in the conventional memory and page fault will occur when the APM BIOS attempts to access the data segment.
To deal with it, the data segment's linear address must be mapped to the given physical address. Specifically, I mapped the data segment's physical address to an area using map_physical_memory(), and stored the virtual address of the area (should be equivalent to linear address because of 32-bit flat model) in the segment descriptor as the data segment's base address. Be sure to align the address and size of the physical memory region to be mapped to the page size (B_PAGE_SIZE, 4096 bytes) in using map_physical_memory().
This problem could also occur for the code segment, but it does not actually do as the code segment resides in the BIOS ROM (F0000H-FFFFFH) and linear address seems to be mapped directly to physical address in this region.
There is even another case where the data segment is allocated at 00400H. When the APM data segment resides in the conventional memory like these examples, the operating system, ignorant of the fact, may abuse the region. As a better solution, it would be necessary to copy the APM data segment to a safe region in the early stage of bootstrap and use the region as the data segment in calling the APM BIOS.
To ITO Takayuki's home page