Mac OS 9 PCI Expansion Card and Driver Support
Mac OS 9 supported PCI expansion cards through a hybrid architecture combining hardware-level Open Firmware initialization, native PowerPC driver standards, and dynamic OS-level driver loading. By using the Open Firmware device tree to detect hardware at boot, utilizing the Native Driver Architecture (NDRV), and managing runtime hardware interactions through the Driver Services Library, Mac OS 9 provided reliable plug-and-play capability for network adapters, graphics cards, storage controllers, and audio interfaces without requiring modern protected-memory driver frameworks.
Open Firmware and Hardware Enumeration
The process of supporting a PCI card in Mac OS 9 began before the operating system loaded. Power Macintosh hardware relied on IEEE 1275-compliant Open Firmware. When a PCI expansion card was installed, Open Firmware probed the PCI bus, read the card’s configuration space, and parsed any FCode (an architecture-independent bytecode) stored in the expansion card’s onboard ROM.
Open Firmware assigned base memory addresses, I/O ranges, and interrupt vectors to the card, then built a hierarchical system representation known as the Device Tree. When the Mac OS 9 kernel took control of the hardware, it inherited this device tree, allowing the operating system to recognize the manufacturer ID, device ID, and subsystem configurations of every installed card automatically.
The Native Driver Architecture (NDRV)
Mac OS 9 interacted with PCI cards primarily through Native Drivers (NDRVs). Unlike legacy drivers from the classic 68k Macintosh era, which ran through the 68k emulator, NDRVs were compiled natively for the PowerPC processor.
NDRVs provided standardized entry points for essential input/output operations, including:
- Initializing and configuring hardware registers.
- Handling control and status requests from higher-level software layers.
- Managing input and output data streams.
- Gracefully shutting down the device during system reboot or sleep states.
For video cards, NDRVs interfaced with the Display Manager and QuickDraw to accelerate 2D and 3D rendering. For mass storage devices, such as SCSI or ATA PCI controllers, drivers conformed to the SCSI Architecture Model (SAM) or the native ATA driver interfaces to hook directly into the File Manager.
The Driver Loader Library (DLL) and Driver Services Library (DSL)
Mac OS 9 dynamically managed hardware interaction through two crucial system-level libraries:
- Driver Loader Library (DLL): The DLL matched
hardware detected in the Open Firmware device tree with available
software drivers. It loaded drivers either directly from the expansion
card's ROM or from system files residing in the OS. If a card lacked a
ROM-based driver, the DLL searched the
Extensionsfolder within the System Folder for a matching driver file based on the device's specific PCI identifiers. - Driver Services Library (DSL): Once loaded, the driver accessed system services via the DSL. The DSL provided a stable interface for managing direct memory access (DMA) transfers, handling interrupts, accessing memory-mapped I/O registers, and performing timing routines. This prevented third-party driver developers from having to write hardware-specific low-level routines for different Macintosh logic boards.
Interrupt Handling and System Extensions
Classic Mac OS lacked true preemptive multitasking and a fully protected memory space, which meant PCI interrupt handling had to be fast and deterministic. When a PCI card signaled an interrupt, the Mac OS 9 interrupt dispatcher identified the card through the PCI interrupt tree and executed the secondary interrupt service routine (ISR) registered by the NDRV. Drivers minimized their time spent at the hardware interrupt level by deferring non-critical processing to deferred task queues.
Peripheral manufacturers packaged their drivers as System Extensions or Control Panels. Users installed these by dropping files into the System Folder. During the extensions phase of the Mac OS 9 boot sequence, these files registered themselves with the DLL, established their memory footprints in the system heap, and exposed their capabilities to software applications via standard Mac OS APIs.