OpenBSD's /dev/pci only permits aligned 32 bit writes.
Emulate smaller writes by doing read/modify/write.

http://marc.info/?l=openbsd-ports&m=127780030728045&w=2

Index: pciutils/lib/obsd-device.c
--- pciutils/lib/obsd-device.c.orig
+++ pciutils/lib/obsd-device.c
@@ -111,19 +111,31 @@ obsd_write(struct pci_dev *d, int pos, byte *buf, int 
   pi.pi_sel.pc_dev = d->dev;
   pi.pi_sel.pc_func = d->func;
 
-  pi.pi_reg = pos;
-  pi.pi_width = len;
+  pi.pi_reg = pos - (pos % 4);
+  pi.pi_width = 4;
+  pi.pi_data = 0xffffffff;
 
+  /* Questionable read-modify-write cycle for non-32-bit writes */
+  if (len != 4)
+    if (ioctl(d->access->fd, PCIOCREAD, &pi) < 0)
+      {
+	/* Abort on any error because the write will contain garbage */
+	d->access->error("obsd_read: ioctl(PCIOCREAD) failed");
+	return 0;
+      }
+
   switch (len)
     {
     case 1:
-      pi.pi_data = buf[0];
+      pi.pi_data &= ~(0xff << ((pos % 4) * 8));
+      pi.pi_data |= buf[0] << ((pos % 4) * 8);
       break;
     case 2:
-      pi.pi_data = ((u16 *) buf)[0];
+      pi.pi_data &= ~(0xffff << ((pos % 4) * 8));
+      pi.pi_data |= htole16(((u16 *) buf)[0]) << ((pos % 4) * 8);
       break;
     case 4:
-      pi.pi_data = ((u32 *) buf)[0];
+      pi.pi_data = htole32(((u32 *) buf)[0]);
       break;
     }
 
