{"id":4954,"date":"2026-09-06T01:37:50","date_gmt":"2026-09-06T04:37:50","guid":{"rendered":"https:\/\/tucumandevelopers.com\/index.php\/2026\/09\/06\/openbsd-stories-strange-medieval-devices\/"},"modified":"2026-09-06T01:37:50","modified_gmt":"2026-09-06T04:37:50","slug":"openbsd-stories-strange-medieval-devices","status":"publish","type":"post","link":"https:\/\/tucumandevelopers.com\/index.php\/2026\/09\/06\/openbsd-stories-strange-medieval-devices\/","title":{"rendered":"OpenBSD Stories: Strange Medieval Devices"},"content":{"rendered":"<div>\n<div><\/div>\n<div data-article-id=\"4585663\" id=\"article-body\">\n<h3> <a name=\"the-problem-amp-industry-shift\" href=\"#the-problem-amp-industry-shift\"> <\/a> The Problem &amp; Industry Shift <\/h3>\n<p>The OpenBSD project is renowned for its security focus, but its hardware support philosophy is equally distinctive: it actively supports a vast array of obscure and obsolete devices, some of which feel like relics from a medieval technological era. While mainstream OSes drop support for legacy hardware to reduce maintenance costs, OpenBSD&#8217;s driver architecture and coding standards allow it to keep these strange devices functional. This article explores the engineering behind OpenBSD&#8217;s support for such devices, the challenges involved, and the trade-offs the project makes to preserve this unique capability.<\/p>\n<p>In an industry that pushes rapid hardware obsolescence, OpenBSD&#8217;s approach is a contrarian shift. The project&#8217;s commitment to &#8220;portability&#8221; isn&#8217;t just about running on many platforms; it&#8217;s about ensuring that even the strangest hardware\u2014like ancient SCSI controllers or obscure network cards\u2014can be used reliably. This is achieved through a clean abstraction layer, rigorous code review, and a driver model that separates bus handling from device logic.<\/p>\n<h3> <a name=\"architecture-amp-core-mechanics\" href=\"#architecture-amp-core-mechanics\"> <\/a> Architecture &amp; Core Mechanics <\/h3>\n<p>OpenBSD&#8217;s device driver framework is built on a layered architecture that decouples hardware discovery from device operation. The core is the <code>bus_space<\/code> and <code>bus_dma<\/code> APIs, which abstract memory-mapped I\/O and DMA operations across different bus types (PCI, ISA, etc.). This allows a single driver to work on multiple platforms without modification.<\/p>\n<p>For example, consider a hypothetical driver for a &#8220;medieval&#8221; device\u2014say, a 1980s-era SCSI controller. The driver registers itself with the system via a <code>cfattach<\/code> structure, which defines the match and attach functions. During autoconfiguration, the kernel walks the device tree, calling match functions to determine if a device is present. Once matched, the attach function initializes the device and registers it with the appropriate subsystem.<\/p>\n<p>Below is a simplified ASCII diagram of the autoconfiguration process: <\/p>\n<div>\n<pre><code>+----------------+ +----------------+ +----------------+ | mainbus | --&gt; | pci* | --&gt; | scsi* | | (root bus) | | (PCI bus) | | (SCSI bus) | +----------------+ +----------------+ +----------------+ | | | | match\/attach | match\/attach | match\/attach v v v +---------+ +---------+ +---------+ | device | | device | | device | +---------+ +---------+ +---------+ <\/code><\/pre>\n<div>\n<\/p><\/div>\n<\/p><\/div>\n<p>Each bus driver iterates over its children, calling their <code>match<\/code> functions. If a match returns success, the <code>attach<\/code> function is invoked. This recursive process builds a device tree that reflects the physical topology.<\/p>\n<p>For strange devices, the match function often relies on device IDs or even probing heuristics. For instance, some legacy devices lack proper PCI configuration registers, so drivers must perform risky I\/O probes. OpenBSD mitigates this by requiring careful probe routines that avoid system crashes.<\/p>\n<h3> <a name=\"production-code-example\" href=\"#production-code-example\"> <\/a> Production Code Example <\/h3>\n<p>Let&#8217;s look at a simplified driver skeleton for a fictional &#8220;medieval&#8221; device\u2014a 16-bit ISA sound card with a proprietary interface. The code below demonstrates key engineering decisions: using bus_space for I\/O, handling interrupts, and implementing a minimal <code>match<\/code> function. <\/p>\n<div>\n<pre><code><span>\/* * Example driver for a fictional medieval ISA device. * This is not a real driver but illustrates OpenBSD driver patterns. *\/<\/span> <span>#include<\/span> <span>&lt;sys\/param.h&gt;<\/span><span> #include<\/span> <span>&lt;sys\/systm.h&gt;<\/span><span> #include<\/span> <span>&lt;sys\/device.h&gt;<\/span><span> #include<\/span> <span>&lt;sys\/bus.h&gt;<\/span><span> <\/span> <span>struct<\/span> <span>medieval_softc<\/span> <span>{<\/span> <span>struct<\/span> <span>device<\/span> <span>sc_dev<\/span><span>;<\/span> <span>bus_space_tag_t<\/span> <span>sc_iot<\/span><span>;<\/span> <span>\/* I\/O space tag *\/<\/span> <span>bus_space_handle_t<\/span> <span>sc_ioh<\/span><span>;<\/span> <span>\/* I\/O space handle *\/<\/span> <span>int<\/span> <span>sc_irq<\/span><span>;<\/span> <span>\/* IRQ number *\/<\/span> <span>};<\/span> <span>int<\/span> <span>medieval_match<\/span><span>(<\/span><span>struct<\/span> <span>device<\/span> <span>*<\/span><span>,<\/span> <span>struct<\/span> <span>cfdata<\/span> <span>*<\/span><span>,<\/span> <span>void<\/span> <span>*<\/span><span>);<\/span> <span>void<\/span> <span>medieval_attach<\/span><span>(<\/span><span>struct<\/span> <span>device<\/span> <span>*<\/span><span>,<\/span> <span>struct<\/span> <span>device<\/span> <span>*<\/span><span>,<\/span> <span>void<\/span> <span>*<\/span><span>);<\/span> <span>struct<\/span> <span>cfattach<\/span> <span>medieval_ca<\/span> <span>=<\/span> <span>{<\/span> <span>sizeof<\/span><span>(<\/span><span>struct<\/span> <span>medieval_softc<\/span><span>),<\/span> <span>medieval_match<\/span><span>,<\/span> <span>medieval_attach<\/span> <span>};<\/span> <span>struct<\/span> <span>cfdriver<\/span> <span>medieval_cd<\/span> <span>=<\/span> <span>{<\/span> <span>NULL<\/span><span>,<\/span> <span>\"medieval\"<\/span><span>,<\/span> <span>DV_DULL<\/span> <span>};<\/span> <span>\/* * Match function: check if the device is present at the given ISA I\/O port. * We use bus_space_map to probe the port and read a signature. *\/<\/span> <span>int<\/span> <span>medieval_match<\/span><span>(<\/span><span>struct<\/span> <span>device<\/span> <span>*<\/span><span>parent<\/span><span>,<\/span> <span>struct<\/span> <span>cfdata<\/span> <span>*<\/span><span>cf<\/span><span>,<\/span> <span>void<\/span> <span>*<\/span><span>aux<\/span><span>)<\/span> <span>{<\/span> <span>struct<\/span> <span>isa_attach_args<\/span> <span>*<\/span><span>ia<\/span> <span>=<\/span> <span>aux<\/span><span>;<\/span> <span>bus_space_tag_t<\/span> <span>iot<\/span> <span>=<\/span> <span>ia<\/span><span>-&gt;<\/span><span>ia_iot<\/span><span>;<\/span> <span>bus_space_handle_t<\/span> <span>ioh<\/span><span>;<\/span> <span>int<\/span> <span>rv<\/span> <span>=<\/span> <span>0<\/span><span>;<\/span> <span>\/* Map the I\/O port range (e.g., 0x300-0x307) *\/<\/span> <span>if<\/span> <span>(<\/span><span>bus_space_map<\/span><span>(<\/span><span>iot<\/span><span>,<\/span> <span>0x300<\/span><span>,<\/span> <span>8<\/span><span>,<\/span> <span>0<\/span><span>,<\/span> <span>&amp;<\/span><span>ioh<\/span><span>)<\/span> <span>!=<\/span> <span>0<\/span><span>)<\/span> <span>return<\/span> <span>0<\/span><span>;<\/span> <span>\/* Read a signature register; if it matches, the device is present *\/<\/span> <span>if<\/span> <span>(<\/span><span>bus_space_read_1<\/span><span>(<\/span><span>iot<\/span><span>,<\/span> <span>ioh<\/span><span>,<\/span> <span>0<\/span><span>)<\/span> <span>==<\/span> <span>0x5A<\/span><span>)<\/span> <span>rv<\/span> <span>=<\/span> <span>1<\/span><span>;<\/span> <span>bus_space_unmap<\/span><span>(<\/span><span>iot<\/span><span>,<\/span> <span>ioh<\/span><span>,<\/span> <span>8<\/span><span>);<\/span> <span>return<\/span> <span>rv<\/span><span>;<\/span> <span>}<\/span> <span>void<\/span> <span>medieval_attach<\/span><span>(<\/span><span>struct<\/span> <span>device<\/span> <span>*<\/span><span>parent<\/span><span>,<\/span> <span>struct<\/span> <span>device<\/span> <span>*<\/span><span>self<\/span><span>,<\/span> <span>void<\/span> <span>*<\/span><span>aux<\/span><span>)<\/span> <span>{<\/span> <span>struct<\/span> <span>medieval_softc<\/span> <span>*<\/span><span>sc<\/span> <span>=<\/span> <span>(<\/span><span>struct<\/span> <span>medieval_softc<\/span> <span>*<\/span><span>)<\/span><span>self<\/span><span>;<\/span> <span>struct<\/span> <span>isa_attach_args<\/span> <span>*<\/span><span>ia<\/span> <span>=<\/span> <span>aux<\/span><span>;<\/span> <span>\/* Save bus tag and map I\/O space for the device *\/<\/span> <span>sc<\/span><span>-&gt;<\/span><span>sc_iot<\/span> <span>=<\/span> <span>ia<\/span><span>-&gt;<\/span><span>ia_iot<\/span><span>;<\/span> <span>if<\/span> <span>(<\/span><span>bus_space_map<\/span><span>(<\/span><span>sc<\/span><span>-&gt;<\/span><span>sc_iot<\/span><span>,<\/span> <span>0x300<\/span><span>,<\/span> <span>8<\/span><span>,<\/span> <span>0<\/span><span>,<\/span> <span>&amp;<\/span><span>sc<\/span><span>-&gt;<\/span><span>sc_ioh<\/span><span>)<\/span> <span>!=<\/span> <span>0<\/span><span>)<\/span> <span>{<\/span> <span>printf<\/span><span>(<\/span><span>\"medieval: can't map I\/O space<\/span><span>\\n<\/span><span>\"<\/span><span>);<\/span> <span>return<\/span><span>;<\/span> <span>}<\/span> <span>\/* Set up interrupt *\/<\/span> <span>sc<\/span><span>-&gt;<\/span><span>sc_irq<\/span> <span>=<\/span> <span>ia<\/span><span>-&gt;<\/span><span>ia_irq<\/span><span>;<\/span> <span>if<\/span> <span>(<\/span><span>sc<\/span><span>-&gt;<\/span><span>sc_irq<\/span> <span>!=<\/span> <span>-<\/span><span>1<\/span><span>)<\/span> <span>{<\/span> <span>isa_intr_establish<\/span><span>(<\/span><span>ia<\/span><span>-&gt;<\/span><span>ia_ic<\/span><span>,<\/span> <span>sc<\/span><span>-&gt;<\/span><span>sc_irq<\/span><span>,<\/span> <span>IST_EDGE<\/span><span>,<\/span> <span>IPL_BIO<\/span><span>,<\/span> <span>medieval_intr<\/span><span>,<\/span> <span>sc<\/span><span>,<\/span> <span>sc<\/span><span>-&gt;<\/span><span>sc_dev<\/span><span>.<\/span><span>dv_xname<\/span><span>);<\/span> <span>}<\/span> <span>printf<\/span><span>(<\/span><span>\"medieval: found strange device at 0x300<\/span><span>\\n<\/span><span>\"<\/span><span>);<\/span> <span>}<\/span> <span>int<\/span> <span>medieval_intr<\/span><span>(<\/span><span>void<\/span> <span>*<\/span><span>arg<\/span><span>)<\/span> <span>{<\/span> <span>struct<\/span> <span>medieval_softc<\/span> <span>*<\/span><span>sc<\/span> <span>=<\/span> <span>arg<\/span><span>;<\/span> <span>\/* Handle interrupt: read status, clear, etc. *\/<\/span> <span>return<\/span> <span>1<\/span><span>;<\/span> <span>\/* handled *\/<\/span> <span>}<\/span> <\/code><\/pre>\n<div>\n<\/p><\/div>\n<\/p><\/div>\n<p><strong>Critical engineering decisions:<\/strong><\/p>\n<ul>\n<li>Using <code>bus_space_map<\/code> ensures we don&#8217;t access I\/O ports without proper mapping, which is crucial on platforms like sparc64 where I\/O is not directly addressable.<\/li>\n<li>The match function performs a minimal probe and unmaps immediately to avoid leaving resources allocated.<\/li>\n<li>Interrupt establishment uses the ISA interrupt controller abstraction, allowing the driver to work on different platforms.<\/li>\n<\/ul>\n<h3> <a name=\"performance-cost-amp-tradeoffs\" href=\"#performance-cost-amp-tradeoffs\"> <\/a> Performance, Cost &amp; Trade-offs <\/h3>\n<p>Supporting strange devices comes at a cost. Each driver adds code to the kernel, increasing memory footprint and compile time. More importantly, maintaining drivers for obsolete hardware consumes developer time that could be spent on modern features. The OpenBSD project accepts this trade-off because it aligns with its goal of running on as many platforms as possible, which is valuable for security research and embedded systems.<\/p>\n<p>Performance-wise, drivers for old devices are rarely performance-critical. However, the abstraction layers (bus_space, bus_dma) introduce a slight overhead compared to direct hardware access. In practice, this overhead is negligible for the types of workloads these devices handle.<\/p>\n<p>Security is another consideration. Legacy devices often lack proper security features, and their drivers may have vulnerabilities. OpenBSD mitigates this by rigorous code audits and by isolating drivers in userland where possible (e.g., using <code>uvisor<\/code> for some devices). However, for kernel-resident drivers, the attack surface is increased. The project&#8217;s proactive security practices help mitigate this risk.<\/p>\n<p>Benchmarks are rarely published for such devices, but the real cost is in maintenance. For example, the <code>com<\/code> driver (serial ports) has been maintained for decades, with periodic fixes for new platforms. The OpenBSD team&#8217;s commitment to clean code and documentation reduces this burden.<\/p>\n<h3> <a name=\"actionable-checklist-summary\" href=\"#actionable-checklist-summary\"> <\/a> Actionable Checklist \/ Summary <\/h3>\n<p>When adopting OpenBSD for environments with legacy or unusual hardware, consider the following:<\/p>\n<ol>\n<li> <strong>Check hardware compatibility<\/strong>: Consult the OpenBSD hardware compatibility list (HCL) for your specific device. If it&#8217;s not listed, you may need to write a driver.<\/li>\n<li> <strong>Understand the driver framework<\/strong>: Familiarize yourself with <code>bus_space<\/code>, <code>bus_dma<\/code>, and the autoconfiguration mechanism.<\/li>\n<li> <strong>Use match functions conservatively<\/strong>: Avoid risky probes that could hang the system. Prefer device IDs when available.<\/li>\n<li> <strong>Leverage userland drivers<\/strong>: For devices that can be driven from userland (e.g., via <code>uvisor<\/code>), do so to reduce kernel risk.<\/li>\n<li> <strong>Contribute back<\/strong>: If you write a driver, submit it to the OpenBSD project. Follow the style guidelines and ensure it compiles on multiple architectures.<\/li>\n<li> <strong>Monitor security<\/strong>: Keep your system updated, as drivers for old devices may receive security fixes.<\/li>\n<\/ol>\n<h3> <a name=\"references\" href=\"#references\"> <\/a> References <\/h3>\n<ul>\n<li><a href=\"https:\/\/man.openbsd.org\/autoconf\" target=\"_blank\" rel=\"noopener noreferrer\">OpenBSD Device Driver Framework<\/a><\/li>\n<li><a href=\"https:\/\/man.openbsd.org\/bus_space\" target=\"_blank\" rel=\"noopener noreferrer\">OpenBSD bus_space(9) man page<\/a><\/li>\n<li><a href=\"https:\/\/www.openbsd.org\/plat.html\" target=\"_blank\" rel=\"noopener noreferrer\">OpenBSD Hardware Compatibility List<\/a><\/li>\n<li><a href=\"https:\/\/man.openbsd.org\/style\" target=\"_blank\" rel=\"noopener noreferrer\">OpenBSD Style Guide for Kernel Code<\/a><\/li>\n<li><a href=\"https:\/\/www.openbsd.org\/faq\/faq-devices.html\" target=\"_blank\" rel=\"noopener noreferrer\">OpenBSD FAQ: Writing Device Drivers<\/a><\/li>\n<\/ul><\/div>\n<\/div>\n<\/div>\n<\/div>\n<p>Fuente: <a href=\"https:\/\/dev.to\/dzakiamriz\/openbsd-stories-strange-medieval-devices-3i8\">Art\u00edculo original<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>The Problem &amp; Industry Shift The OpenBSD project is renowned for its security focus, but its hardware support philosophy is equally distinctive: it actively supports a vast array of obscure and obsolete devices, some of which feel like relics from a medieval technological era. While mainstream OSes drop support for legacy hardware to reduce maintenance [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":4953,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":true,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2},"webixso_pending_account_ids":""},"categories":[41],"tags":[],"class_list":["post-4954","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-devto"],"jetpack_publicize_connections":[],"_links":{"self":[{"href":"https:\/\/tucumandevelopers.com\/index.php\/wp-json\/wp\/v2\/posts\/4954","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/tucumandevelopers.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/tucumandevelopers.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/tucumandevelopers.com\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/tucumandevelopers.com\/index.php\/wp-json\/wp\/v2\/comments?post=4954"}],"version-history":[{"count":0,"href":"https:\/\/tucumandevelopers.com\/index.php\/wp-json\/wp\/v2\/posts\/4954\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/tucumandevelopers.com\/index.php\/wp-json\/wp\/v2\/media\/4953"}],"wp:attachment":[{"href":"https:\/\/tucumandevelopers.com\/index.php\/wp-json\/wp\/v2\/media?parent=4954"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/tucumandevelopers.com\/index.php\/wp-json\/wp\/v2\/categories?post=4954"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/tucumandevelopers.com\/index.php\/wp-json\/wp\/v2\/tags?post=4954"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}