Re: [PATCH] Experimental vchiq and bcm2835_audio support for arm64

Marco Devesas Campos <[email protected]>
Newsgroups gmane.os.freebsd.devel.arm
Message-ID <[email protected]>
Hi Warner, and List,

(retrying as the original doesn't seem to have made it to the list)

so, quite clearly, this ended up not being a two day job...

On the other hand the vchiq code now not only works with the
bcm2835_audio driver but should be on par, feature-wise, with
the existing 32 bit code.

To wit, the patch below

   * updates vchiq and bcm2835_audio to work on 64 bit pi's

   * implements compat_freebsd32 ioctl calls so that 32 bit apps can
     be run on a 64 bit system -- including omxplayer*

   * fixes a few panics, stalls, busy waits and data corruptions

In the process of debugging things I also got the userland utilities
to work on arm64 and if this gets accepted for inclusion I'll update
the port.

On the issues that remain, audio play stalls intermittently after
a day or two of inactivity**; and running vchiq_test -p in parallel
with audio or video playing will result in stammering.

Anyway, output of git format-patch below.

Best,
Marco

* although the pi4 needs a special 32 bit version, not the one
from ports -- i'll get that out if there's interest

** workaround is to use the sysctl to change the output dest and
then change it back




 From 89f464839efca9483eabca454db0d78495e2f4ac Mon Sep 17 00:00:00 2001
From: Marco Devesas Campos <devesas.campos@gmailcom>
Date: Wed, 11 May 2022 15:19:41 +0100
Subject: [PATCH] arm64: Add support to vchiq and bcm2835_audio (plus some
  fixes)

Add 64 bit support to vchiq:
     * update fields to the appropriate fixed bit-size variants
       (everywhere [cf. e.g., ref:sizes and ref:sizes2])
     * update printfs to account for said sizes (everywhere)
     * update printfs to the different size of pointers (everywhere)
     * refer to event semaphores (that go into the very 32 bit VC) by
       offset instead of pointers [ref:sems]
     * dsb() is dsb(sy) in arm64 (vchiq_{core.c,core.h,kmod.c}) [ref:dsb]
     * comment out some unneeded code in parse_rx_slots around
       VCHIQ_MSG_BULK_RX (cf. [ref:deadcode])
     * adapt remote_event_signal to arm64 caching behaviours (vchiq_kmod.c)
     * refactor synchronization around remote_event_signal, forcing a
       wmb to be on the safe side; thereby make it look more like what linux
       does [ref:sync] (vchiq_{core,kmod}.c); and make a comment in
       vchiq_core.c true (wasn't before)
     * add a few more syncs to be on the safe side (vchiq_2835_arm.c)

     * use arm64 dcache invalidation mechanisms (vchiq_2835_arm.c)
     * explicitly invalidate pages on arm64 post bulk-read (vchiq_2835_arm.c)
     * support bulk transfers on rpi-4 (aka "long address space"
       transfers), by hard-coding their vc offset (0) and different
       bit-shift [ref:longbulk]  (vchiq_2835_arm.c)
     * refactor a loop-of-constant-test (vchiq_2835_arm.c)
     * use the correct (hard-coded) cache-line size on arm64

     * rework the handling of chipset "features" to account for the
       extra behaviours with 64 bit chipsets. (vchiq_kmod.c)
     * add compat_freebsd32 ioctls and respective datatypes.
       (vchiq_arm.c, vchiq_ioctl.h)
     * add sysctl-s (log, arm_log) to control debug (vchiq_kmod.c)

     * add example kernel config (GENERIC-VCHIQ)

Fixes:
     * Rework error handling in create_pagelist, avoiding a potential
       panic when freeing memory that had been dmamem_alloc, a potential
       null dereference, and a leak when having problems pinning pages
       (vchiq_2835_arm.c)
     * fix a confusion about the behaviour cv_wait_sig that lead to
       uninterruptible looping (vchiq_bsd.c)
     * implement detection of fatal signals (vchiq_bsd.c)
     * fix a confusion with the name of a variable introduced by
       #a0b8746 that could lead to a panic when closing the cdev file
       (vchiq_arm.c)
     * release user connection when destructing cdevpriv and avoid
       user processes sharing connection data, which lead to stalls
       and data corruption.  (vchiq_arm.c)

Update bcm2835_audio to work on 64bit systems:
     * update VC audio fields (vc_vchi_audioserv_defs.h, bcm2835_audio.c)
     * repurpose the hitherto unused `callback` field to help push a 64 bit
       pointer in (bcm2835_audio.c)
     * increase (hopefully) the robustness of the code that shifts data to
       VC (bcm2835_audio.c)
     * add a sysctl to control the amount of debugging info output by
       bcm2835_audio.c

Tested on zero, zero2 and 4+ with ping, functional, bulk
and control vchiq_test-s, and omxplayer

     [ref:dsb]: https://github.com/raspberrypi/linux/commit/35b7ebda57affcfd3616d39d5a727a4495b31123
     [ref:sems]: https://github.com/raspberrypi/linux/commit/24a4262afb10907fce3cdbc3ae336fcf4cdaece5
     [ref:sizes]: https://github.com/raspberrypi/linux/commit/e64568b8ea6c04e747e432c17ce2452652075216
     [ref:sizes2]: https://github.com/raspberrypi/linux/commit/f9bee6dd24addfa00c2c8d50c25b73efbfbb28ba
     [ref:deadcode]: https://github.com/raspberrypi/linux/commit/14f4d72fb799a9b3170a45ab80d4a3ddad541960
     [ref:sync]: https://github.com/raspberrypi/linux/commit/51c071265079319583e4c6e8c61e09660300d0bf
     [ref:longbulk]: https://github.com/raspberrypi/linux/commit/37f6f19a83722c9b866cecb5e455b2e16e5bbc6b
---
  sys/arm/broadcom/bcm2835/bcm2835_audio.c      | 248 +++++++--
  .../broadcom/bcm2835/vc_vchi_audioserv_defs.h |   8 +-
  sys/arm64/conf/GENERIC-VCHIQ                  |  23 +
  sys/contrib/vchiq/interface/compat/vchi_bsd.c |  12 +-
  .../interface/vchiq_arm/vchiq_2835_arm.c      | 159 +++++-
  .../vchiq/interface/vchiq_arm/vchiq_arm.c     | 494 +++++++++++++-----
  .../vchiq/interface/vchiq_arm/vchiq_core.c    | 285 +++++-----
  .../vchiq/interface/vchiq_arm/vchiq_core.h    |  11 +-
  .../vchiq/interface/vchiq_arm/vchiq_ioctl.h   | 121 +++++
  .../interface/vchiq_arm/vchiq_kern_lib.c      |   8 +-
  .../vchiq/interface/vchiq_arm/vchiq_kmod.c    |  76 ++-
  .../interface/vchiq_arm/vchiq_pagelist.h      |   8 +-
  .../vchiq/interface/vchiq_arm/vchiq_shim.c    |   4 +-
  13 files changed, 1100 insertions(+), 357 deletions(-)
  create mode 100644 sys/arm64/conf/GENERIC-VCHIQ

diff --git a/sys/arm/broadcom/bcm2835/bcm2835_audio.c b/sys/arm/broadcom/bcm2835/bcm2835_audio.c
index 36b1dc86535b..8d978bc20f85 100644
--- a/sys/arm/broadcom/bcm2835/bcm2835_audio.c
+++ b/sys/arm/broadcom/bcm2835/bcm2835_audio.c
@@ -27,6 +27,10 @@
  #include "opt_snd.h"
  #endif
  
+/*
+    For the PRIu64 identifier
+*/
+#include <machine/_inttypes.h>
  #include <dev/sound/pcm/sound.h>
  #include <dev/sound/chip.h>
  
@@ -116,6 +120,12 @@ struct bcm2835_audio_chinfo {
  	uint64_t retrieved_samples;
  	uint64_t underruns;
  	int starved;
+	struct bcm_log_vars {
+		unsigned int bsize ;
+		int slept_for_lack_of_space ;
+	} log_vars;
+#define DEFAULT_LOG_VALUES \
+	((struct bcm_log_vars) { .bsize = 0 , .slept_for_lack_of_space = 0 })
  };
  
  struct bcm2835_audio_info {
@@ -135,6 +145,7 @@ struct bcm2835_audio_info {
  
  	uint32_t flags_pending;
  
+	int verbose_trace;
  	/* Worker thread state */
  	int worker_state;
  };
@@ -143,6 +154,35 @@ struct bcm2835_audio_info {
  #define BCM2835_AUDIO_LOCKED(sc)	mtx_assert(&(sc)->lock, MA_OWNED)
  #define BCM2835_AUDIO_UNLOCK(sc)	mtx_unlock(&(sc)->lock)
  
+/* things that really have to be reported */
+#define REPORT_ERROR(sc,...) \
+	do{ device_printf((sc)->dev,__VA_ARGS__); }while(0)
+/* things that shouldn't clobber the output */
+#define INFORM_THAT(sc,...) \
+	do { \
+		if(sc->verbose_trace>0){ \
+			device_printf((sc)->dev,__VA_ARGS__); \
+		} \
+	}while(0)
+/* things that might clobber the output */
+#define WARN_THAT(sc,...) \
+	do { \
+		if(sc->verbose_trace>1){ \
+			device_printf((sc)->dev,__VA_ARGS__); \
+		} \
+	}while(0)
+/* things that are expected to (will) clobber the output */
+#define TRACE(sc,...) \
+	do { \
+		if(sc->verbose_trace>2){ \
+			device_printf((sc)->dev,__VA_ARGS__); \
+		} \
+	}while(0)
+
+/* Useful for circular buffer calcs */
+#define MOD_DIFF(front,rear,mod) (((mod) + (front) - (rear)) % (mod))
+
+
  static const char *
  dest_description(uint32_t dest)
  {
@@ -216,10 +256,21 @@ bcm2835_audio_callback(void *param, const VCHI_CALLBACK_REASON_T reason, void *m
  			    m.type);
  		}
  	} else if (m.type == VC_AUDIO_MSG_TYPE_COMPLETE) {
-		struct bcm2835_audio_chinfo *ch = m.u.complete.cookie;
+	  unsigned int signaled = 0;
+		struct bcm2835_audio_chinfo *ch ;
+#if defined(__aarch64__)
+		ch = (void *) ((((size_t)m.u.complete.callback) << 32)
+				| ((size_t)m.u.complete.cookie));
+#else
+		ch = (void *) (m.u.complete.cookie);
+#endif
+
  
  		int count = m.u.complete.count & 0xffff;
  		int perr = (m.u.complete.count & (1U << 30)) != 0;
+
+		TRACE(sc,"in:: count:0x%x perr:%d\n",m.u.complete.count,perr);
+
  		ch->callbacks++;
  		if (perr)
  			ch->underruns++;
@@ -239,18 +290,41 @@ bcm2835_audio_callback(void *param, const VCHI_CALLBACK_REASON_T reason, void *m
  					device_printf(sc->dev, "available_space == %d, count = %d, perr=%d\n",
  					    ch->available_space, count, perr);
  					device_printf(sc->dev,
-					    "retrieved_samples = %lld, submitted_samples = %lld\n",
+					    "retrieved_samples = %"PRIu64", submitted_samples = %"PRIu64"\n",
  					    ch->retrieved_samples, ch->submitted_samples);
  				}
-				ch->available_space += count;
-				ch->retrieved_samples += count;
  			}
-			if (perr || (ch->available_space >= VCHIQ_AUDIO_PACKET_SIZE))
-				cv_signal(&sc->worker_cv);
+			ch->available_space += count;
+			ch->retrieved_samples += count;
+			/*
+			 *  XXXMDC
+			 *  Experimental: if VC says it's empty, believe it
+			 *  Has to come after the usual adjustments
+			 */
+			if(perr){
+				ch->available_space = VCHIQ_AUDIO_BUFFER_SIZE;
+				perr = ch->retrieved_samples; // shd be != 0
+			}
+
+			if ((ch->available_space >= 1*VCHIQ_AUDIO_PACKET_SIZE)){
+					cv_signal(&sc->worker_cv);
+				signaled = 1;
+			}
  		}
  		BCM2835_AUDIO_UNLOCK(sc);
+		if(perr){
+			WARN_THAT(sc,
+				"VC starved; reported %u for a total of %u\n"
+				"worker %s\n" ,
+			 	count,perr,
+				(signaled ? "signaled": "not signaled")
+			);
+		}
  	} else
-		printf("%s: unknown m.type: %d\n", __func__, m.type);
+		WARN_THAT(sc,
+			"%s: unknown m.type: %d\n",
+			__func__, m.type
+		);
  }
  
  /* VCHIQ stuff */
@@ -262,13 +336,13 @@ bcm2835_audio_init(struct bcm2835_audio_info *sc)
  	/* Initialize and create a VCHI connection */
  	status = vchi_initialise(&sc->vchi_instance);
  	if (status != 0) {
-		printf("vchi_initialise failed: %d\n", status);
+		REPORT_ERROR(sc,"vchi_initialise failed: %d\n", status);
  		return;
  	}
  
  	status = vchi_connect(NULL, 0, sc->vchi_instance);
  	if (status != 0) {
-		printf("vchi_connect failed: %d\n", status);
+		REPORT_ERROR(sc,"vchi_connect failed: %d\n", status);
  		return;
  	}
  
@@ -300,7 +374,7 @@ bcm2835_audio_release(struct bcm2835_audio_info *sc)
  	if (sc->vchi_handle != VCHIQ_SERVICE_HANDLE_INVALID) {
  		success = vchi_service_close(sc->vchi_handle);
  		if (success != 0)
-			printf("vchi_service_close failed: %d\n", success);
+			REPORT_ERROR(sc,"vchi_service_close failed: %d\n", success);
  		vchi_service_release(sc->vchi_handle);
  		sc->vchi_handle = VCHIQ_SERVICE_HANDLE_INVALID;
  	}
@@ -330,7 +404,10 @@ bcm2835_audio_start(struct bcm2835_audio_chinfo *ch)
  		    &m, sizeof m, VCHI_FLAGS_BLOCK_UNTIL_QUEUED, NULL);
  
  		if (ret != 0)
-			printf("%s: vchi_msg_queue failed (err %d)\n", __func__, ret);
+			REPORT_ERROR(sc,
+				"%s: vchi_msg_queue failed (err %d)\n",
+				__func__, ret
+			);
  	}
  }
  
@@ -345,11 +422,15 @@ bcm2835_audio_stop(struct bcm2835_audio_chinfo *ch)
  		m.type = VC_AUDIO_MSG_TYPE_STOP;
  		m.u.stop.draining = 0;
  
+		INFORM_THAT(sc,"sending stop\n");
  		ret = vchi_msg_queue(sc->vchi_handle,
  		    &m, sizeof m, VCHI_FLAGS_BLOCK_UNTIL_QUEUED, NULL);
  
  		if (ret != 0)
-			printf("%s: vchi_msg_queue failed (err %d)\n", __func__, ret);
+			REPORT_ERROR(sc,
+				"%s: vchi_msg_queue failed (err %d)\n",
+				__func__, ret
+			);
  	}
  }
  
@@ -365,7 +446,10 @@ bcm2835_audio_open(struct bcm2835_audio_info *sc)
  		    &m, sizeof m, VCHI_FLAGS_BLOCK_UNTIL_QUEUED, NULL);
  
  		if (ret != 0)
-			printf("%s: vchi_msg_queue failed (err %d)\n", __func__, ret);
+			REPORT_ERROR(sc,
+				"%s: vchi_msg_queue failed (err %d)\n",
+				__func__, ret
+			);
  	}
  }
  
@@ -387,7 +471,10 @@ bcm2835_audio_update_controls(struct bcm2835_audio_info *sc, uint32_t volume, ui
  		    &m, sizeof m, VCHI_FLAGS_BLOCK_UNTIL_QUEUED, NULL);
  
  		if (ret != 0)
-			printf("%s: vchi_msg_queue failed (err %d)\n", __func__, ret);
+			REPORT_ERROR(sc,
+				"%s: vchi_msg_queue failed (err %d)\n",
+				__func__, ret
+			);
  	}
  }
  
@@ -407,7 +494,10 @@ bcm2835_audio_update_params(struct bcm2835_audio_info *sc, uint32_t fmt, uint32_
  		    &m, sizeof m, VCHI_FLAGS_BLOCK_UNTIL_QUEUED, NULL);
  
  		if (ret != 0)
-			printf("%s: vchi_msg_queue failed (err %d)\n", __func__, ret);
+			REPORT_ERROR(sc,
+				"%s: vchi_msg_queue failed (err %d)\n",
+				__func__, ret
+			);
  	}
  }
  
@@ -415,18 +505,25 @@ static bool
  bcm2835_audio_buffer_should_sleep(struct bcm2835_audio_chinfo *ch)
  {
  
+	ch->log_vars.slept_for_lack_of_space = 0;
  	if (ch->playback_state != PLAYBACK_PLAYING)
  		return (true);
  
  	/* Not enough data */
-	if (sndbuf_getready(ch->buffer) < VCHIQ_AUDIO_PACKET_SIZE) {
-		printf("starve\n");
+	/* XXXMDC Take unsubmitted stuff into account */
+	if (sndbuf_getready(ch->buffer)
+			- MOD_DIFF(
+				ch->unsubmittedptr,
+				sndbuf_getreadyptr(ch->buffer),
+				sndbuf_getsize(ch->buffer)
+			) < VCHIQ_AUDIO_PACKET_SIZE) {
  		ch->starved++;
  		return (true);
  	}
  
  	/* Not enough free space */
  	if (ch->available_space < VCHIQ_AUDIO_PACKET_SIZE) {
+		ch->log_vars.slept_for_lack_of_space = 1;
  		return (true);
  	}
  
@@ -447,22 +544,27 @@ bcm2835_audio_write_samples(struct bcm2835_audio_chinfo *ch, void *buf, uint32_t
  	m.type = VC_AUDIO_MSG_TYPE_WRITE;
  	m.u.write.count = count;
  	m.u.write.max_packet = VCHIQ_AUDIO_PACKET_SIZE;
-	m.u.write.callback = NULL;
-	m.u.write.cookie = ch;
+#if defined(__aarch64__)
+	m.u.write.callback = (uint32_t)(((size_t) ch) >> 32) & 0xffffffff;
+	m.u.write.cookie = (uint32_t)(((size_t) ch) & 0xffffffff);
+#else
+	m.u.write.callback = (uint32_t) NULL;
+	m.u.write.cookie = (uint32_t) ch;
+#endif
  	m.u.write.silence = 0;
  
  	ret = vchi_msg_queue(sc->vchi_handle,
  	    &m, sizeof m, VCHI_FLAGS_BLOCK_UNTIL_QUEUED, NULL);
  
  	if (ret != 0)
-		printf("%s: vchi_msg_queue failed (err %d)\n", __func__, ret);
+		REPORT_ERROR(sc,"%s: vchi_msg_queue failed (err %d)\n", __func__, ret);
  
  	while (count > 0) {
  		int bytes = MIN((int)m.u.write.max_packet, (int)count);
  		ret = vchi_msg_queue(sc->vchi_handle,
  		    buf, bytes, VCHI_FLAGS_BLOCK_UNTIL_QUEUED, NULL);
  		if (ret != 0)
-			printf("%s: vchi_msg_queue failed: %d\n",
+			REPORT_ERROR(sc,"%s: vchi_msg_queue failed: %d\n",
  			    __func__, ret);
  		buf = (char *)buf + bytes;
  		count -= bytes;
@@ -494,6 +596,10 @@ bcm2835_audio_worker(void *data)
  		while ((sc->flags_pending == 0) &&
  		    bcm2835_audio_buffer_should_sleep(ch)) {
  			cv_wait_sig(&sc->worker_cv, &sc->lock);
+			if((sc-> flags_pending == 0)
+			    && ch->log_vars.slept_for_lack_of_space) {
+				TRACE(sc,"slept for lack of space\n");
+			}
  		}
  		flags = sc->flags_pending;
  		/* Clear pending flags */
@@ -520,16 +626,32 @@ bcm2835_audio_worker(void *data)
  			BCM2835_AUDIO_LOCK(sc);
  			bcm2835_audio_reset_channel(&sc->pch);
  			ch->playback_state = PLAYBACK_IDLE;
+			long sub_total = ch->submitted_samples;
+			long retd = ch->retrieved_samples;
  			BCM2835_AUDIO_UNLOCK(sc);
+			INFORM_THAT(sc,
+				"stopped audio. submitted a total of %lu "
+				"having been acked %lu\n",
+				sub_total, retd
+			);
  			continue;
  		}
  
  		/* Requested to start playback */
  		if ((flags & AUDIO_PLAY) &&
  		    (ch->playback_state == PLAYBACK_IDLE)) {
+			INFORM_THAT(sc,
+				"starting audio\n"
+			);
+			unsigned int bsize = sndbuf_getsize(ch->buffer);
  			BCM2835_AUDIO_LOCK(sc);
  			ch->playback_state = PLAYBACK_PLAYING;
+			ch->log_vars.bsize = bsize;
  			BCM2835_AUDIO_UNLOCK(sc);
+			INFORM_THAT(sc,
+				"buffer size is %u\n",
+				bsize
+			);	
  			bcm2835_audio_start(ch);
  		}
  
@@ -538,20 +660,69 @@ bcm2835_audio_worker(void *data)
  
  		if (sndbuf_getready(ch->buffer) == 0)
  			continue;
-
-		count = sndbuf_getready(ch->buffer);
+		uint32_t i_count;
+
+		/* XXXMDC Take unsubmitted stuff into account */
+		count
+		= i_count
+		= sndbuf_getready(ch->buffer)
+			- MOD_DIFF(
+				ch->unsubmittedptr,
+				sndbuf_getreadyptr(ch->buffer),
+				sndbuf_getsize(ch->buffer)
+			);
  		size = sndbuf_getsize(ch->buffer);
-		readyptr = sndbuf_getreadyptr(ch->buffer);
+		readyptr = ch->unsubmittedptr;
  
+		int size_changed=0;
+		unsigned int available;
  		BCM2835_AUDIO_LOCK(sc);
-		if (readyptr + count > size)
+		if(size != ch->log_vars.bsize){
+			ch->log_vars.bsize = size;
+			size_changed = 1;
+		}
+		available = ch->available_space;
+		/*
+		 *  XXXMDC
+		 *
+		 *  On arm64, got into situations where 
+		 *  readyptr was less than a packet away
+		 *  from the end of the buffer, which led
+		 *  to count being set to 0 and, inexorably, starvation.
+		 *  Code below tries to take that into account.
+		 *  The problem might have been fixed with some of the
+		 *  other changes that were made in the meantime,
+		 *  but for now this works fine.
+		 */
+		if (readyptr + count > size){
  			count = size - readyptr;
-		count = min(count, ch->available_space);
-		count -= (count % VCHIQ_AUDIO_PACKET_SIZE);
+		}
+		if(count > ch->available_space){
+			count = ch->available_space;
+			count -= (count % VCHIQ_AUDIO_PACKET_SIZE);
+		}else if (count > VCHIQ_AUDIO_PACKET_SIZE){
+			count -= (count % VCHIQ_AUDIO_PACKET_SIZE);
+		}else if (size > count + readyptr) {
+			count = 0;
+		}
  		BCM2835_AUDIO_UNLOCK(sc);
-
-		if (count < VCHIQ_AUDIO_PACKET_SIZE)
+	if(count % VCHIQ_AUDIO_PACKET_SIZE != 0){
+	  WARN_THAT(sc,
+	 	"count: %u  initial count: %u  "
+	        "size: %u  readyptr: %u  available: %u"
+		"\n",
+		count,i_count,size,readyptr, available);
+	}
+	if(size_changed) INFORM_THAT(sc,"bsize changed to %u\n",size);
+		
+		if (count == 0){
+			WARN_THAT(sc,
+				"not enough room for a packet: count %d,"
+				" i_count %d, rptr %d, size %d\n",
+				count, i_count, readyptr, size
+			);
  			continue;
+		}
  
  		buf = (uint8_t*)sndbuf_getbuf(ch->buffer) + readyptr;
  
@@ -560,8 +731,17 @@ bcm2835_audio_worker(void *data)
  		ch->unsubmittedptr = (ch->unsubmittedptr + count) % sndbuf_getsize(ch->buffer);
  		ch->available_space -= count;
  		ch->submitted_samples += count;
+		long sub = count;
+		long sub_total = ch->submitted_samples;
+		long retd = ch->retrieved_samples;
  		KASSERT(ch->available_space >= 0, ("ch->available_space == %d\n", ch->available_space));
  		BCM2835_AUDIO_UNLOCK(sc);
+
+	TRACE(sc,
+		"submitted %lu for a total of %lu having been acked %lu; "
+		"rptr %d, had %u available \n",
+		sub, sub_total, retd, readyptr, available);
+
  	}
  
  	BCM2835_AUDIO_LOCK(sc);
@@ -580,7 +760,9 @@ bcm2835_audio_create_worker(struct bcm2835_audio_info *sc)
  	sc->worker_state = WORKER_RUNNING;
  	if (kproc_create(bcm2835_audio_worker, (void*)sc, &newp, 0, 0,
  	    "bcm2835_audio_worker") != 0) {
-		printf("failed to create bcm2835_audio_worker\n");
+		REPORT_ERROR(sc,
+			"failed to create bcm2835_audio_worker\n"
+		);
  	}
  }
  
@@ -613,6 +795,8 @@ bcmchan_init(kobj_t obj, void *devinfo, struct snd_dbuf *b, struct pcm_channel *
  		return NULL;
  	}
  
+	ch->log_vars = DEFAULT_LOG_VALUES;
+
  	BCM2835_AUDIO_LOCK(sc);
  	bcm2835_worker_update_params(sc);
  	BCM2835_AUDIO_UNLOCK(sc);
@@ -833,6 +1017,9 @@ vchi_audio_sysctl_init(struct bcm2835_audio_info *sc)
  	SYSCTL_ADD_INT(ctx, tree, OID_AUTO, "starved",
  			CTLFLAG_RD, &sc->pch.starved,
  			sc->pch.starved, "number of starved conditions");
+	SYSCTL_ADD_INT(ctx, tree, OID_AUTO, "trace",
+			CTLFLAG_RW, &sc->verbose_trace,
+			sc->verbose_trace, "enable tracing of transfers");
  }
  
  static void
@@ -864,6 +1051,7 @@ bcm2835_audio_delayed_init(void *xsc)
  	bcm2835_audio_open(sc);
  	sc->volume = 75;
  	sc->dest = DEST_AUTO;
+	sc->verbose_trace = 0;
  
      	if (mixer_init(sc->dev, &bcmmixer_class, sc)) {
  		device_printf(sc->dev, "mixer_init failed\n");
diff --git a/sys/arm/broadcom/bcm2835/vc_vchi_audioserv_defs.h b/sys/arm/broadcom/bcm2835/vc_vchi_audioserv_defs.h
index 143c54385916..04292df1c261 100644
--- a/sys/arm/broadcom/bcm2835/vc_vchi_audioserv_defs.h
+++ b/sys/arm/broadcom/bcm2835/vc_vchi_audioserv_defs.h
@@ -114,8 +114,8 @@ typedef struct
  typedef struct
  {
  	uint32_t count; /* in bytes */
-	void *callback;
-	void *cookie;
+	uint32_t callback;
+	uint32_t cookie;
  	uint16_t silence;
  	uint16_t max_packet;
  } VC_AUDIO_WRITE_T;
@@ -131,8 +131,8 @@ typedef struct
  typedef struct
  {
  	int32_t count;  /* Success value */
-	void *callback;
-	void *cookie;
+	uint32_t callback;
+	uint32_t cookie;
  } VC_AUDIO_COMPLETE_T;
  
  /* Message header for all messages in HOST->VC direction */
diff --git a/sys/arm64/conf/GENERIC-VCHIQ b/sys/arm64/conf/GENERIC-VCHIQ
new file mode 100644
index 000000000000..422ed425894c
--- /dev/null
+++ b/sys/arm64/conf/GENERIC-VCHIQ
@@ -0,0 +1,23 @@
+#
+# GENERIC-VCHIQ
+#
+# Custom kernel for arm64 plus VCHIQ
+#
+# $FreeBSD$
+
+#NO_UNIVERSE
+
+include		GENERIC
+ident		GENERIC-VCHIQ
+
+device vchiq
+
+# If you want to have any chance of compiling this in a RPI Zero 2
+# uncomment the stuff below
+
+# nomakeoptions DEBUG
+# nomakeoptions WITH_CTF
+# nooptions DDB_CTF
+# makeoptions MALLOC_PRODUCTION=1
+
+
diff --git a/sys/contrib/vchiq/interface/compat/vchi_bsd.c b/sys/contrib/vchiq/interface/compat/vchi_bsd.c
index f831880f5e13..e039992036aa 100644
--- a/sys/contrib/vchiq/interface/compat/vchi_bsd.c
+++ b/sys/contrib/vchiq/interface/compat/vchi_bsd.c
@@ -341,7 +341,6 @@ down_interruptible(struct semaphore *s)
  	int ret ;
  
  	ret = 0;
-
  	mtx_lock(&s->mtx);
  
  	while (s->value == 0) {
@@ -349,13 +348,11 @@ down_interruptible(struct semaphore *s)
  		ret = cv_wait_sig(&s->cv, &s->mtx);
  		s->waiters--;
  
-		if (ret == EINTR) {
+		/* XXXMDC As per its semaphore.c, linux can only return EINTR */
+		if (ret) {
  			mtx_unlock(&s->mtx);
-			return (-EINTR);
+			return -EINTR;
  		}
-
-		if (ret == ERESTART)
-			continue;
  	}
  
  	s->value--;
@@ -442,8 +439,7 @@ flush_signals(VCHIQ_THREAD_T thr)
  int
  fatal_signal_pending(VCHIQ_THREAD_T thr)
  {
-	printf("Implement ME: %s\n", __func__);
-	return (0);
+	return (curproc_sigkilled());
  }
  
  /*
diff --git a/sys/contrib/vchiq/interface/vchiq_arm/vchiq_2835_arm.c b/sys/contrib/vchiq/interface/vchiq_arm/vchiq_2835_arm.c
index 279aacd0880a..7a48ad9d21b6 100644
--- a/sys/contrib/vchiq/interface/vchiq_arm/vchiq_2835_arm.c
+++ b/sys/contrib/vchiq/interface/vchiq_arm/vchiq_2835_arm.c
@@ -65,9 +65,24 @@ MALLOC_DEFINE(M_VCPAGELIST, "vcpagelist", "VideoCore pagelist memory");
  
  #define MAX_FRAGMENTS (VCHIQ_NUM_CURRENT_BULKS * 2)
  
+/*
+ *  XXXMDC
+ * Do this less ad-hoc-y -- e.g.
+ * https://github.com/raspberrypi/linux/commit/c683db8860a80562a2bb5b451d77b3e471d24f36
+ */
+#if defined(__aarch64__)
+int g_cache_line_size = 64;
+#else
  int g_cache_line_size = 32;
+#endif
  static int g_fragment_size;
  
+unsigned int g_long_bulk_space = 0;
+#define VM_PAGE_TO_VC_BULK_PAGE(x) (\
+	g_long_bulk_space ? VM_PAGE_TO_PHYS(x)\
+		 : PHYS_TO_VCBUS(VM_PAGE_TO_PHYS(x))\
+)
+
  typedef struct vchiq_2835_state_struct {
     int inited;
     VCHIQ_ARM_STATE_T arm_state;
@@ -113,6 +128,59 @@ vchiq_dmamap_cb(void *arg, bus_dma_segment_t *segs, int nseg, int err)
  	*addr = PHYS_TO_VCBUS(segs[0].ds_addr);
  }
  
+#if defined(__aarch64__) /* See comment in free_pagelist */
+static int
+invalidate_cachelines_in_range_of_ppage(
+	vm_page_t p,
+	size_t offset,
+	size_t count
+)
+{
+	if(offset + count > PAGE_SIZE){ return EINVAL; }
+        uint8_t *dst = (uint8_t*)pmap_quick_enter_page(p);
+        if (!dst){
+                return ENOMEM;
+	}
+	cpu_dcache_inv_range((vm_offset_t)dst + offset, count);
+	pmap_quick_remove_page((vm_offset_t)dst);
+	return 0;
+}
+
+/* XXXMDC bulk instead of loading and invalidating single pages? */
+static void
+invalidate_cachelines_in_range_of_ppage_seq(
+	vm_page_t *p,
+	size_t start,
+	size_t count
+)
+{
+	if(start >= PAGE_SIZE) goto invalid_input;	
+
+#define _NEXT_AT(x,_m) (((x)+((_m)-1)) & ~((_m)-1))   /* for power of two m */
+	size_t offset = _NEXT_AT(start,g_cache_line_size);
+#undef _NEXT_AT
+	count = (offset < start + count) ? count - (offset - start) : 0;
+	offset = offset & (PAGE_SIZE - 1);
+	for(
+		size_t done = 0;
+		count > done;
+		p++, done += PAGE_SIZE - offset, offset = 0
+	){
+		size_t in_page = PAGE_SIZE - offset;
+		size_t todo = (count-done > in_page) ? in_page : count-done;
+		int e =	invalidate_cachelines_in_range_of_ppage(*p, offset, todo);
+		if(e != 0)
+			goto problem_in_loop;
+	}
+	return;
+
+problem_in_loop:
+invalid_input:
+	WARN_ON(1);
+	return;
+}
+#endif
+
  static int
  copyout_page(vm_page_t p, size_t offset, void *kaddr, size_t size)
  {
@@ -171,7 +239,7 @@ vchiq_platform_init(VCHIQ_STATE_T *state)
  		goto failed_load;
  	}
  
-	WARN_ON(((int)g_slot_mem & (PAGE_SIZE - 1)) != 0);
+	WARN_ON(((size_t)g_slot_mem & (PAGE_SIZE - 1)) != 0);
  
  	vchiq_slot_zero = vchiq_init_slots(g_slot_mem, g_slot_mem_size);
  	if (!vchiq_slot_zero) {
@@ -204,8 +272,8 @@ vchiq_platform_init(VCHIQ_STATE_T *state)
  	bcm_mbox_write(BCM2835_MBOX_CHAN_VCHIQ, (unsigned int)g_slot_phys);
  
  	vchiq_log_info(vchiq_arm_log_level,
-		"vchiq_init - done (slots %x, phys %x)",
-		(unsigned int)vchiq_slot_zero, g_slot_phys);
+		"vchiq_init - done (slots %zx, phys %zx)",
+		(size_t)vchiq_slot_zero, g_slot_phys);
  
     vchiq_call_connected_callbacks();
  
@@ -393,13 +461,14 @@ pagelist_page_free(vm_page_t pp)
  ** from increased speed as a result.
  */
  
+
  static int
  create_pagelist(char __user *buf, size_t count, unsigned short type,
  	struct proc *p, BULKINFO_T *bi)
  {
  	PAGELIST_T *pagelist;
  	vm_page_t* pages;
-	unsigned long *addrs;
+	uint32_t *addrs;
  	unsigned int num_pages, i;
  	vm_offset_t offset;
  	int pagelist_size;
@@ -436,7 +505,7 @@ create_pagelist(char __user *buf, size_t count, unsigned short type,
  
  	err = bus_dmamem_alloc(bi->pagelist_dma_tag, (void **)&pagelist,
  	    BUS_DMA_COHERENT | BUS_DMA_WAITOK, &bi->pagelist_dma_map);
-	if (err) {
+	if (err || !pagelist) {
  		vchiq_log_error(vchiq_core_log_level, "Unable to allocate pagelist memory");
  		err = -ENOMEM;
  		goto failed_alloc;
@@ -449,14 +518,12 @@ create_pagelist(char __user *buf, size_t count, unsigned short type,
  	if (err) {
  		vchiq_log_error(vchiq_core_log_level, "cannot load DMA map for pagelist memory");
  		err = -ENOMEM;
+		bi->pagelist = pagelist;
  		goto failed_load;
  	}
  
  	vchiq_log_trace(vchiq_arm_log_level,
-		"create_pagelist - %x (%d bytes @%p)", (unsigned int)pagelist, count, buf);
-
-	if (!pagelist)
-		return -ENOMEM;
+		"create_pagelist - %zx (%zu bytes @%p)", (size_t)pagelist, count, buf);
  
  	addrs = pagelist->addrs;
  	pages = (vm_page_t*)(addrs + num_pages);
@@ -467,8 +534,9 @@ create_pagelist(char __user *buf, size_t count, unsigned short type,
  
  	if (actual_pages != num_pages) {
  		vm_page_unhold_pages(pages, actual_pages);
-		free(pagelist, M_VCPAGELIST);
-		return (-ENOMEM);
+		err = -ENOMEM;
+		bi->pagelist = pagelist;
+		goto failed_hold;
  	}
  
  	pagelist->length = count;
@@ -477,27 +545,28 @@ create_pagelist(char __user *buf, size_t count, unsigned short type,
  
  	/* Group the pages into runs of contiguous pages */
  
-	base_addr = (void *)PHYS_TO_VCBUS(VM_PAGE_TO_PHYS(pages[0]));
+	size_t run_ceil = g_long_bulk_space ? 0x100 : PAGE_SIZE;
+	unsigned int pg_addr_rshift = g_long_bulk_space ? 4 : 0;
+	base_addr = (void *) VM_PAGE_TO_VC_BULK_PAGE(pages[0]);
  	next_addr = base_addr + PAGE_SIZE;
  	addridx = 0;
  	run = 0;
-
+#define _PG_BLOCK(base,run) \
+		((((size_t) (base)) >> pg_addr_rshift) & ~(run_ceil-1)) + (run)
  	for (i = 1; i < num_pages; i++) {
-		addr = (void *)PHYS_TO_VCBUS(VM_PAGE_TO_PHYS(pages[i]));
-		if ((addr == next_addr) && (run < (PAGE_SIZE - 1))) {
+		addr = (void *)VM_PAGE_TO_VC_BULK_PAGE(pages[i]);
+		if ((addr == next_addr) && (run < run_ceil - 1)) {
  			next_addr += PAGE_SIZE;
  			run++;
  		} else {
-			addrs[addridx] = (unsigned long)base_addr + run;
-			addridx++;
+			addrs[addridx++] = (uint32_t) _PG_BLOCK(base_addr,run);
  			base_addr = addr;
  			next_addr = addr + PAGE_SIZE;
  			run = 0;
  		}
  	}
-
-	addrs[addridx] = (unsigned long)base_addr + run;
-	addridx++;
+	addrs[addridx++] = _PG_BLOCK(base_addr, run);
+#undef _PG_BLOCK
  
  	/* Partial cache lines (fragments) require special measures */
  	if ((type == PAGELIST_READ) &&
@@ -519,12 +588,24 @@ create_pagelist(char __user *buf, size_t count, unsigned short type,
  		g_free_fragments = *(char **) g_free_fragments;
  		up(&g_free_fragments_mutex);
  		pagelist->type =
-			 PAGELIST_READ_WITH_FRAGMENTS + 
-			 (fragments - g_fragments_base)/g_fragment_size;
+			 PAGELIST_READ_WITH_FRAGMENTS 
+			 + (fragments - g_fragments_base)/g_fragment_size;
+#if defined(__aarch64__)
+		 bus_dmamap_sync(bcm_slots_dma_tag, bcm_slots_dma_map, BUS_DMASYNC_PREREAD);
+#endif
  	}
  
+#if defined(__aarch64__)
+	if(type == PAGELIST_READ){ 
+		cpu_dcache_wbinv_range((vm_offset_t)buf,count);
+	}else{
+		cpu_dcache_wb_range((vm_offset_t)buf,count);
+	}
+	dsb(sy);
+#else
  	pa = pmap_extract(PCPU_GET(curpmap), (vm_offset_t)buf);
  	dcache_wbinv_poc((vm_offset_t)buf, pa, count);
+#endif
  
  	bus_dmamap_sync(bi->pagelist_dma_tag, bi->pagelist_dma_map, BUS_DMASYNC_PREWRITE);
  
@@ -532,6 +613,8 @@ create_pagelist(char __user *buf, size_t count, unsigned short type,
  
  	return 0;
  
+failed_hold:
+	bus_dmamap_unload(bi->pagelist_dma_tag,bi->pagelist_dma_map);
  failed_load:
  	bus_dmamem_free(bi->pagelist_dma_tag, bi->pagelist, bi->pagelist_dma_map);
  failed_alloc:
@@ -550,7 +633,7 @@ free_pagelist(BULKINFO_T *bi, int actual)
  	pagelist = bi->pagelist;
  
  	vchiq_log_trace(vchiq_arm_log_level,
-		"free_pagelist - %x, %d (%lu bytes @%p)", (unsigned int)pagelist, actual, pagelist->length, bi->buf);
+		"free_pagelist - %zx, %d (%u bytes @%p)", (size_t)pagelist, actual, pagelist->length, bi->buf);
  
  	num_pages =
  		(pagelist->length + pagelist->offset + PAGE_SIZE - 1) /
@@ -558,6 +641,27 @@ free_pagelist(BULKINFO_T *bi, int actual)
  
  	pages = (vm_page_t*)(pagelist->addrs + num_pages);
  
+#if defined(__aarch64__)
+	/*
+         * On arm64, even if the user keeps their end of the bargain
+	 * -- do NOT touch the buffers sent to VC -- but reads around the
+	 * pagelist after the invalidation above, the arm might preemptively
+	 * load (and validate) cache lines for areas inside the page list,
+	 * so we must invalidate them again.
+	 *
+	 * The functional test does it and without this it doesn't pass.
+	 *
+	 * XXXMDC might it be enough to invalidate a couple of pages at
+	 * the ends of the page list?
+	 */
+	if(pagelist->type >= PAGELIST_READ && actual > 0)
+		invalidate_cachelines_in_range_of_ppage_seq(
+			pages,
+			pagelist->offset,
+			actual
+		);	
+#endif
+
  	/* Deal with any partial cache lines (fragments) */
  	if (pagelist->type >= PAGELIST_READ_WITH_FRAGMENTS) {
  		char *fragments = g_fragments_base +
@@ -594,13 +698,18 @@ free_pagelist(BULKINFO_T *bi, int actual)
  		up(&g_free_fragments_sema);
  	}
  
-	for (i = 0; i < num_pages; i++) {
-		if (pagelist->type != PAGELIST_WRITE) {
+	if (pagelist->type != PAGELIST_WRITE) {
+		for (i = 0; i < num_pages; i++) {
  			vm_page_dirty(pages[i]);
  			pagelist_page_free(pages[i]);
  		}
  	}
  
+#if defined(__aarch64__)
+	/* XXXMDC necessary? */
+	dsb(sy);
+#endif
+
  	bus_dmamap_unload(bi->pagelist_dma_tag, bi->pagelist_dma_map);
  	bus_dmamem_free(bi->pagelist_dma_tag, bi->pagelist, bi->pagelist_dma_map);
  	bus_dma_tag_destroy(bi->pagelist_dma_tag);
diff --git a/sys/contrib/vchiq/interface/vchiq_arm/vchiq_arm.c b/sys/contrib/vchiq/interface/vchiq_arm/vchiq_arm.c
index 763cd9ce9417..bfcff315a543 100644
--- a/sys/contrib/vchiq/interface/vchiq_arm/vchiq_arm.c
+++ b/sys/contrib/vchiq/interface/vchiq_arm/vchiq_arm.c
@@ -386,7 +386,7 @@ static void
  user_service_free(void *userdata)
  {
  	USER_SERVICE_T *user_service = userdata;
-	
+
  	_sema_destroy(&user_service->insert_event);
  	_sema_destroy(&user_service->remove_event);
  
@@ -410,7 +410,7 @@ static void close_delivered(USER_SERVICE_T *user_service)
  
  		/* Wake the user-thread blocked in close_ or remove_service */
  		up(&user_service->close_event);
- 
+
  		user_service->close_pending = 0;
  	}
  }
@@ -442,12 +442,23 @@ vchiq_ioctl(struct cdev *cdev, u_long cmd, caddr_t arg, int fflag,
  #define	_IOC_TYPE(x)	IOCGROUP(x)
  
  	vchiq_log_trace(vchiq_arm_log_level,
-		 "vchiq_ioctl - instance %x, cmd %s, arg %p",
-		(unsigned int)instance,
+		 "vchiq_ioctl - instance %zx, cmd %s, arg %p",
+		(size_t)instance,
  		((_IOC_TYPE(cmd) == VCHIQ_IOC_MAGIC) &&
  		(_IOC_NR(cmd) <= VCHIQ_IOC_MAX)) ?
  		ioctl_names[_IOC_NR(cmd)] : "<invalid>", arg);
  
+#ifdef COMPAT_FREEBSD32
+/* A fork in the road to freebsd32 compatibilty */
+#define _CF32_FORK(compat_c,native_c)\
+	{ \
+		int _____dont_call_your_vars_this = 0;\
+		switch(cmd){_CF32_CASE {_____dont_call_your_vars_this = 1;} break;} \
+		if(_____dont_call_your_vars_this) { compat_c } else { native_c } \
+	}
+#else
+#define _CF32_FORK(compat_c,native_c) { native_c }
+#endif
  	switch (cmd) {
  	case VCHIQ_IOC_SHUTDOWN:
  		if (!instance->connected)
@@ -496,13 +507,32 @@ vchiq_ioctl(struct cdev *cdev, u_long cmd, caddr_t arg, int fflag,
  				"vchiq: could not connect: %d", status);
  		break;
  
+#ifdef COMPAT_FREEBSD32
+#define _CF32_CASE \
+	case VCHIQ_IOC_CREATE_SERVICE32:
+	_CF32_CASE
+#endif
  	case VCHIQ_IOC_CREATE_SERVICE: {
  		VCHIQ_CREATE_SERVICE_T args;
  		USER_SERVICE_T *user_service = NULL;
  		void *userdata;
  		int srvstate;
  
+_CF32_FORK(
+		VCHIQ_CREATE_SERVICE32_T args32;
+		memcpy(&args32, (const void*)arg, sizeof(args32));
+		args.params.fourcc = args32.params.fourcc;
+/* XXXMDC not actually used? overwritten straight away */
+		args.params.callback = (VCHIQ_CALLBACK_T)(uintptr_t) args32.params.callback;
+		args.params.userdata = (void*)(uintptr_t)args32.params.userdata;
+		args.params.version = args32.params.version;
+		args.params.version_min = args32.params.version_min;
+		args.is_open = args32.is_open;
+		args.is_vchi = args32.is_vchi;
+		args.handle  = args32.handle;
+,
  		memcpy(&args, (const void*)arg, sizeof(args));
+)
  
  		user_service = kmalloc(sizeof(USER_SERVICE_T), GFP_KERNEL);
  		if (!user_service) {
@@ -558,15 +588,22 @@ vchiq_ioctl(struct cdev *cdev, u_long cmd, caddr_t arg, int fflag,
  					break;
  				}
  			}
-
  #ifdef VCHIQ_IOCTL_DEBUG
  			printf("%s: [CREATE SERVICE] handle = %08x\n", __func__, service->handle);
  #endif
+_CF32_FORK(
+			memcpy((void *)
+				&(((VCHIQ_CREATE_SERVICE32_T*)
+					arg)->handle),
+				(const void *)&service->handle,
+				sizeof(service->handle));
+,
  			memcpy((void *)
  				&(((VCHIQ_CREATE_SERVICE_T*)
  					arg)->handle),
  				(const void *)&service->handle,
  				sizeof(service->handle));
+);
  
  			service = NULL;
  		} else {
@@ -574,6 +611,7 @@ vchiq_ioctl(struct cdev *cdev, u_long cmd, caddr_t arg, int fflag,
  			kfree(user_service);
  		}
  	} break;
+#undef _CF32_CASE
  
  	case VCHIQ_IOC_CLOSE_SERVICE: {
  		VCHIQ_SERVICE_HANDLE_T handle;
@@ -673,9 +711,22 @@ vchiq_ioctl(struct cdev *cdev, u_long cmd, caddr_t arg, int fflag,
  			ret = -EINVAL;
  	} break;
  
+#ifdef COMPAT_FREEBSD32
+#define _CF32_CASE \
+		case VCHIQ_IOC_QUEUE_MESSAGE32:
+	_CF32_CASE
+#endif
  	case VCHIQ_IOC_QUEUE_MESSAGE: {
  		VCHIQ_QUEUE_MESSAGE_T args;
+_CF32_FORK(
+		VCHIQ_QUEUE_MESSAGE32_T args32;
+		memcpy(&args32, (const void*)arg, sizeof(args32));
+		args.handle = args32.handle;
+		args.count = args32.count;
+		args.elements = (VCHIQ_ELEMENT_T *)(uintptr_t)args32.elements;
+,
  		memcpy(&args, (const void*)arg, sizeof(args));
+)
  
  #ifdef VCHIQ_IOCTL_DEBUG
  		printf("%s: [QUEUE MESSAGE] handle = %08x\n", __func__, args.handle);
@@ -686,8 +737,22 @@ vchiq_ioctl(struct cdev *cdev, u_long cmd, caddr_t arg, int fflag,
  		if ((service != NULL) && (args.count <= MAX_ELEMENTS)) {
  			/* Copy elements into kernel space */
  			VCHIQ_ELEMENT_T elements[MAX_ELEMENTS];
-			if (copy_from_user(elements, args.elements,
-				args.count * sizeof(VCHIQ_ELEMENT_T)) == 0)
+			long cp_ret;
+_CF32_FORK(
+			VCHIQ_ELEMENT32_T elements32[MAX_ELEMENTS];
+			cp_ret = copy_from_user(elements32, args.elements,
+					args.count * sizeof(VCHIQ_ELEMENT32_T));
+			for(int i=0;cp_ret == 0 && i < args.count;++i){
+				elements[i].data =
+					(void *)(uintptr_t)elements32[i].data;
+				elements[i].size = elements32[i].size;
+			}
+
+,
+			cp_ret = copy_from_user(elements, args.elements,
+				args.count * sizeof(VCHIQ_ELEMENT_T));
+)
+			if (cp_ret == 0)
  				status = vchiq_queue_message
  					(args.handle,
  					elements, args.count);
@@ -697,16 +762,37 @@ vchiq_ioctl(struct cdev *cdev, u_long cmd, caddr_t arg, int fflag,
  			ret = -EINVAL;
  		}
  	} break;
+#undef _CF32_CASE
  
+#ifdef COMPAT_FREEBSD32
+#define _CF32_CASE \
+		case VCHIQ_IOC_QUEUE_BULK_TRANSMIT32: \
+		case VCHIQ_IOC_QUEUE_BULK_RECEIVE32:
+	_CF32_CASE
+#endif
  	case VCHIQ_IOC_QUEUE_BULK_TRANSMIT:
  	case VCHIQ_IOC_QUEUE_BULK_RECEIVE: {
  		VCHIQ_QUEUE_BULK_TRANSFER_T args;
+
  		struct bulk_waiter_node *waiter = NULL;
  		VCHIQ_BULK_DIR_T dir =
-			(cmd == VCHIQ_IOC_QUEUE_BULK_TRANSMIT) ?
+			(cmd == VCHIQ_IOC_QUEUE_BULK_TRANSMIT) || (cmd == VCHIQ_IOC_QUEUE_BULK_TRANSMIT32)?
  			VCHIQ_BULK_TRANSMIT : VCHIQ_BULK_RECEIVE;
  
+_CF32_FORK(
+		VCHIQ_QUEUE_BULK_TRANSFER32_T args32;
+		memcpy(&args32, (const void*)arg, sizeof(args32));
+		/* XXXMDC parens needed (macro parsing?) */
+		args = ((VCHIQ_QUEUE_BULK_TRANSFER_T) {
+			.handle = args32.handle,
+			.data = (void *)(uintptr_t) args32.data,
+			.size = args32.size,
+			.userdata = (void *)(uintptr_t) args32.userdata,
+			.mode = args32.mode,
+		});
+,
  		memcpy(&args, (const void*)arg, sizeof(args));
+)
  
  		service = find_service_for_instance(instance, args.handle);
  		if (!service) {
@@ -734,7 +820,6 @@ vchiq_ioctl(struct cdev *cdev, u_long cmd, caddr_t arg, int fflag,
  					list_del(pos);
  					break;
  				}
-
  			}
  			lmutex_unlock(&instance->bulk_waiter_list_mutex);
  			if (!waiter) {
@@ -745,10 +830,11 @@ vchiq_ioctl(struct cdev *cdev, u_long cmd, caddr_t arg, int fflag,
  				break;
  			}
  			vchiq_log_info(vchiq_arm_log_level,
-				"found bulk_waiter %x for pid %d",
-				(unsigned int)waiter, current->p_pid);
+				"found bulk_waiter %zx for pid %d",
+				(size_t)waiter, current->p_pid);
  			args.userdata = &waiter->bulk_waiter;
  		}
+
  		status = vchiq_bulk_transfer
  			(args.handle,
  			 VCHI_MEM_HANDLE_INVALID,
@@ -776,17 +862,31 @@ vchiq_ioctl(struct cdev *cdev, u_long cmd, caddr_t arg, int fflag,
  			list_add(&waiter->list, &instance->bulk_waiter_list);
  			lmutex_unlock(&instance->bulk_waiter_list_mutex);
  			vchiq_log_info(vchiq_arm_log_level,
-				"saved bulk_waiter %x for pid %d",
-				(unsigned int)waiter, current->p_pid);
+				"saved bulk_waiter %zx for pid %d",
+				(size_t)waiter, current->p_pid);
  
+_CF32_FORK(
+			memcpy((void *)
+				&(((VCHIQ_QUEUE_BULK_TRANSFER32_T *)
+					arg)->mode),
+				(const void *)&mode_waiting,
+				sizeof(mode_waiting));
+,
  			memcpy((void *)
  				&(((VCHIQ_QUEUE_BULK_TRANSFER_T *)
  					arg)->mode),
  				(const void *)&mode_waiting,
  				sizeof(mode_waiting));
+)
  		}
  	} break;
+#undef _CF32_CASE
  
+#ifdef COMPAT_FREEBSD32
+#define _CF32_CASE \
+		case VCHIQ_IOC_AWAIT_COMPLETION32:
+	_CF32_CASE
+#endif
  	case VCHIQ_IOC_AWAIT_COMPLETION: {
  		VCHIQ_AWAIT_COMPLETION_T args;
  		int count = 0;
@@ -797,7 +897,17 @@ vchiq_ioctl(struct cdev *cdev, u_long cmd, caddr_t arg, int fflag,
  			break;
  		}
  
+_CF32_FORK(
+		VCHIQ_AWAIT_COMPLETION32_T args32;
+                memcpy(&args32, (const void*)arg, sizeof(args32));
+		args.count = args32.count;
+		args.buf = (VCHIQ_COMPLETION_DATA_T *)(uintptr_t)args32.buf;
+		args.msgbufsize = args32.msgbufsize;
+		args.msgbufcount = args32.msgbufcount;
+		args.msgbufs = (void **)(uintptr_t)args32.msgbufs;
+,
                  memcpy(&args, (const void*)arg, sizeof(args));
+)
  
  		lmutex_lock(&instance->completion_mutex);
  
@@ -860,9 +970,9 @@ vchiq_ioctl(struct cdev *cdev, u_long cmd, caddr_t arg, int fflag,
  					if (args.msgbufsize < msglen) {
  						vchiq_log_error(
  							vchiq_arm_log_level,
-							"header %x: msgbufsize"
+							"header %zx: msgbufsize"
  							" %x < msglen %x",
-							(unsigned int)header,
+							(size_t)header,
  							args.msgbufsize,
  							msglen);
  						WARN(1, "invalid message "
@@ -877,6 +987,19 @@ vchiq_ioctl(struct cdev *cdev, u_long cmd, caddr_t arg, int fflag,
  						break;
  					/* Get the pointer from user space */
  					msgbufcount--;
+_CF32_FORK(
+					uint32_t *msgbufs32 = (uint32_t *) args.msgbufs;
+					uint32_t msgbuf32 = 0;
+					if (copy_from_user(&msgbuf32,
+						(const uint32_t __user *)
+						&msgbufs32[msgbufcount],
+						sizeof(msgbuf32)) != 0) {
+						if (count == 0)
+							ret = -EFAULT;
+						break;
+					}
+					msgbuf = (void __user *)(uintptr_t)msgbuf32;
+,
  					if (copy_from_user(&msgbuf,
  						(const void __user *)
  						&args.msgbufs[msgbufcount],
@@ -885,6 +1008,7 @@ vchiq_ioctl(struct cdev *cdev, u_long cmd, caddr_t arg, int fflag,
  							ret = -EFAULT;
  						break;
  					}
+)
  
  					/* Copy the message to user space */
  					if (copy_to_user(msgbuf, header,
@@ -908,7 +1032,26 @@ vchiq_ioctl(struct cdev *cdev, u_long cmd, caddr_t arg, int fflag,
  					VCHIQ_SERVICE_CLOSED) &&
  					!instance->use_close_delivered)
  					unlock_service(service1);
-
+_CF32_FORK(
+				VCHIQ_COMPLETION_DATA32_T comp32 = {0};
+				comp32.reason
+				= (uint32_t)(size_t) completion->reason;
+				comp32.service_userdata
+				= (uint32_t)(size_t) completion->service_userdata;
+				comp32.bulk_userdata
+				= (uint32_t)(size_t) completion->bulk_userdata;
+				comp32.header = (uint32_t)(size_t)completion->header;
+
+				VCHIQ_COMPLETION_DATA32_T __user *buf_loc;
+				buf_loc = (VCHIQ_COMPLETION_DATA32_T __user *) args.buf;
+				buf_loc += count;
+				if (copy_to_user(
+						buf_loc, &comp32, sizeof(comp32)
+				  	) != 0){
+						if (ret == 0)
+							ret = -EFAULT;
+				}
+,
  				if (copy_to_user((void __user *)(
  					(size_t)args.buf +
  					count * sizeof(VCHIQ_COMPLETION_DATA_T)),
@@ -918,6 +1061,7 @@ vchiq_ioctl(struct cdev *cdev, u_long cmd, caddr_t arg, int fflag,
  							ret = -EFAULT;
  					break;
  				}
+)
  
  				/* Ensure that the above copy has completed
  				** before advancing the remove pointer. */
@@ -927,18 +1071,33 @@ vchiq_ioctl(struct cdev *cdev, u_long cmd, caddr_t arg, int fflag,
  			}
  
  			if (msgbufcount != args.msgbufcount) {
+_CF32_FORK(
+				memcpy(
+					(void __user *)
+					&((VCHIQ_AWAIT_COMPLETION32_T *)arg)->
+						msgbufcount,
+					&msgbufcount,
+					sizeof(msgbufcount));
+,
  				memcpy((void __user *)
  					&((VCHIQ_AWAIT_COMPLETION_T *)arg)->
  						msgbufcount,
  					&msgbufcount,
  					sizeof(msgbufcount));
+)
  			}
  
  			 if (count != args.count)
  			 {
+_CF32_FORK(
+				memcpy((void __user *)
+					&((VCHIQ_AWAIT_COMPLETION32_T *)arg)->count,
+					&count, sizeof(count));
+,
  				memcpy((void __user *)
  					&((VCHIQ_AWAIT_COMPLETION_T *)arg)->count,
  					&count, sizeof(count));
+)
  			}
  		}
  
@@ -947,9 +1106,9 @@ vchiq_ioctl(struct cdev *cdev, u_long cmd, caddr_t arg, int fflag,
  
  		if ((ret == 0) && instance->closing)
  			ret = -ENOTCONN;
-		/* 
+		/*
  		 * XXXBSD: ioctl return codes are not negative as in linux, so
-		 * we can not indicate success with positive number of passed 
+		 * we can not indicate success with positive number of passed
  		 * messages
  		 */
  		if (ret > 0)
@@ -958,14 +1117,29 @@ vchiq_ioctl(struct cdev *cdev, u_long cmd, caddr_t arg, int fflag,
  		lmutex_unlock(&instance->completion_mutex);
  		DEBUG_TRACE(AWAIT_COMPLETION_LINE);
  	} break;
+#undef _CF32_CASE
  
+#ifdef COMPAT_FREEBSD32
+#define _CF32_CASE \
+		case VCHIQ_IOC_DEQUEUE_MESSAGE32:
+	_CF32_CASE
+#endif
  	case VCHIQ_IOC_DEQUEUE_MESSAGE: {
  		VCHIQ_DEQUEUE_MESSAGE_T args;
  		USER_SERVICE_T *user_service;
  		VCHIQ_HEADER_T *header;
  
  		DEBUG_TRACE(DEQUEUE_MESSAGE_LINE);
+_CF32_FORK(
+		VCHIQ_DEQUEUE_MESSAGE32_T args32;
+		memcpy(&args32, (const void*)arg, sizeof(args32));
+		args.handle = args32.handle;
+		args.blocking = args32.blocking;
+		args.bufsize = args32.bufsize;
+		args.buf = (void *)(uintptr_t)args32.buf;
+,
  		memcpy(&args, (const void*)arg, sizeof(args));
+)
  		service = find_service_for_instance(instance, args.handle);
  		if (!service) {
  			ret = -EINVAL;
@@ -1022,8 +1196,19 @@ vchiq_ioctl(struct cdev *cdev, u_long cmd, caddr_t arg, int fflag,
  				header->data,
  				header->size) == 0)) {
  				args.bufsize = header->size;
+_CF32_FORK(
+				VCHIQ_DEQUEUE_MESSAGE32_T args32;
+				args32.handle = args.handle;
+				args32.blocking = args.blocking;
+				args32.bufsize = args.bufsize;
+				args32.buf = (uintptr_t)(void *)args.buf;
+
+				memcpy((void *)arg, &args32,
+				    sizeof(args32));
+,
  				memcpy((void *)arg, &args,
  				    sizeof(args));
+)
  				vchiq_release_message(
  					service->handle,
  					header);
@@ -1031,14 +1216,15 @@ vchiq_ioctl(struct cdev *cdev, u_long cmd, caddr_t arg, int fflag,
  				ret = -EFAULT;
  		} else {
  			vchiq_log_error(vchiq_arm_log_level,
-				"header %x: bufsize %x < size %x",
-				(unsigned int)header, args.bufsize,
+				"header %zx: bufsize %x < size %x",
+				(size_t)header, args.bufsize,
  				header->size);
  			WARN(1, "invalid size\n");
  			ret = -EMSGSIZE;
  		}
  		DEBUG_TRACE(DEQUEUE_MESSAGE_LINE);
  	} break;
+#undef _CF32_CASE
  
  	case VCHIQ_IOC_GET_CLIENT_ID: {
  		VCHIQ_SERVICE_HANDLE_T handle;
@@ -1048,11 +1234,24 @@ vchiq_ioctl(struct cdev *cdev, u_long cmd, caddr_t arg, int fflag,
  		ret = vchiq_get_client_id(handle);
  	} break;
  
+#ifdef COMPAT_FREEBSD32
+#define _CF32_CASE \
+		case VCHIQ_IOC_GET_CONFIG32:
+	_CF32_CASE
+#endif
  	case VCHIQ_IOC_GET_CONFIG: {
  		VCHIQ_GET_CONFIG_T args;
  		VCHIQ_CONFIG_T config;
-
+_CF32_FORK(
+		VCHIQ_GET_CONFIG32_T args32;
+
+		memcpy(&args32, (const void*)arg, sizeof(args32));
+		args.config_size = args32.config_size;
+		args.pconfig = (VCHIQ_CONFIG_T *)
+			(uintptr_t)args32.pconfig;
+,
  		memcpy(&args, (const void*)arg, sizeof(args));
+)
  		if (args.config_size > sizeof(config)) {
  			ret = -EINVAL;
  			break;
@@ -1066,6 +1265,7 @@ vchiq_ioctl(struct cdev *cdev, u_long cmd, caddr_t arg, int fflag,
  			}
  		}
  	} break;
+#undef _CF32_CASE
  
  	case VCHIQ_IOC_SET_SERVICE_OPTION: {
  		VCHIQ_SET_SERVICE_OPTION_T args;
@@ -1082,18 +1282,31 @@ vchiq_ioctl(struct cdev *cdev, u_long cmd, caddr_t arg, int fflag,
  				args.handle, args.option, args.value);
  	} break;
  
+#ifdef COMPAT_FREEBSD32
+#define _CF32_CASE \
+		case VCHIQ_IOC_DUMP_PHYS_MEM32:
+	_CF32_CASE
+#endif
  	case VCHIQ_IOC_DUMP_PHYS_MEM: {
  		VCHIQ_DUMP_MEM_T  args;
  
+_CF32_FORK(
+		VCHIQ_DUMP_MEM32_T args32;
+		memcpy(&args32, (const void*)arg, sizeof(args32));
+		args.virt_addr = (void *)(uintptr_t)args32.virt_addr;
+		args.num_bytes = (size_t)args32.num_bytes;
+,
  		memcpy(&args, (const void*)arg, sizeof(args));
+)
  		printf("IMPLEMENT ME: %s:%d\n", __FILE__, __LINE__);
  #if 0
  		dump_phys_mem(args.virt_addr, args.num_bytes);
  #endif
  	} break;
+#undef _CF32_CASE
  
  	case VCHIQ_IOC_LIB_VERSION: {
-		unsigned int lib_version = (unsigned int)arg;
+		size_t lib_version = (size_t)arg;
  
  		if (lib_version < VCHIQ_VERSION_MIN)
  			ret = -EINVAL;
@@ -1119,6 +1332,7 @@ vchiq_ioctl(struct cdev *cdev, u_long cmd, caddr_t arg, int fflag,
  		ret = -ENOTTY;
  		break;
  	}
+#undef _CF32_FORK
  
  	if (service)
  		unlock_service(service);
@@ -1155,18 +1369,14 @@ vchiq_ioctl(struct cdev *cdev, u_long cmd, caddr_t arg, int fflag,
  	return ret;
  }
  
-static void
-instance_dtr(void *data)
-{
  
-	kfree(data);
-}
  
  /****************************************************************************
  *
  *   vchiq_open
  *
  ***************************************************************************/
+static void instance_dtr(void *data);
  
  static int
  vchiq_open(struct cdev *dev, int flags, int fmt __unused, struct thread *td)
@@ -1206,7 +1416,7 @@ vchiq_open(struct cdev *dev, int flags, int fmt __unused, struct thread *td)
  		INIT_LIST_HEAD(&instance->bulk_waiter_list);
  
  		devfs_set_cdevpriv(instance, instance_dtr);
-	} 
+	}
  	else {
  		vchiq_log_error(vchiq_arm_log_level,
  			"Unknown minor device");
@@ -1222,143 +1432,151 @@ vchiq_open(struct cdev *dev, int flags, int fmt __unused, struct thread *td)
  *
  ***************************************************************************/
  
+
  static int
-vchiq_close(struct cdev *dev, int flags __unused, int fmt __unused,
-                struct thread *td)
+_vchiq_close_instance(VCHIQ_INSTANCE_T instance)
  {
  	int ret = 0;
-	if (1) {
-		VCHIQ_INSTANCE_T instance;
-		VCHIQ_STATE_T *state = vchiq_get_state();
-		VCHIQ_SERVICE_T *service;
-		int i;
-
-		if ((ret = devfs_get_cdevpriv((void**)&instance))) {
-			printf("devfs_get_cdevpriv failed: error %d\n", ret);
-			return (ret);
-		}
-
-		vchiq_log_info(vchiq_arm_log_level,
-			"vchiq_release: instance=%lx",
-			(unsigned long)instance);
-
-		if (!state) {
-			ret = -EPERM;
-			goto out;
-		}
+	VCHIQ_STATE_T *state = vchiq_get_state();
+	VCHIQ_SERVICE_T *service;
+	int i;
  
-		/* Ensure videocore is awake to allow termination. */
-		vchiq_use_internal(instance->state, NULL,
-				USE_TYPE_VCHIQ);
+	vchiq_log_info(vchiq_arm_log_level,
+		"vchiq_release: instance=%lx",
+		(unsigned long)instance);
  
-		lmutex_lock(&instance->completion_mutex);
+	if (!state) {
+		ret = -EPERM;
+		goto out;
+	}
  
-		/* Wake the completion thread and ask it to exit */
-		instance->closing = 1;
-		up(&instance->insert_event);
+	/* Ensure videocore is awake to allow termination. */
+	vchiq_use_internal(instance->state, NULL,
+			USE_TYPE_VCHIQ);
  
-		lmutex_unlock(&instance->completion_mutex);
+	lmutex_lock(&instance->completion_mutex);
  
-		/* Wake the slot handler if the completion queue is full. */
-		up(&instance->remove_event);
+	/* Wake the completion thread and ask it to exit */
+	instance->closing = 1;
+	up(&instance->insert_event);
  
-		/* Mark all services for termination... */
-		i = 0;
-		while ((service = next_service_by_instance(state, instance,
-			&i)) !=	NULL) {
-			USER_SERVICE_T *user_service = service->base.userdata;
+	lmutex_unlock(&instance->completion_mutex);
  
-			/* Wake the slot handler if the msg queue is full. */
-			up(&user_service->remove_event);
+	/* Wake the slot handler if the completion queue is full. */
+	up(&instance->remove_event);
  
-			vchiq_terminate_service_internal(service);
-			unlock_service(service);
-		}
+	/* Mark all services for termination... */
+	i = 0;
+	while ((service = next_service_by_instance(state, instance,
+		&i)) !=	NULL) {
+		USER_SERVICE_T *user_service = service->base.userdata;
  
-		/* ...and wait for them to die */
-		i = 0;
-		while ((service = next_service_by_instance(state, instance, &i))
-			!= NULL) {
-			USER_SERVICE_T *user_service = service->base.userdata;
+		/* Wake the slot handler if the msg queue is full. */
+		up(&user_service->remove_event);
  
-			down(&service->remove_event);
+		vchiq_terminate_service_internal(service);
+		unlock_service(service);
+	}
  
-			BUG_ON(service->srvstate != VCHIQ_SRVSTATE_FREE);
+	/* ...and wait for them to die */
+	i = 0;
+	while ((service = next_service_by_instance(state, instance, &i))
+		!= NULL) {
+		USER_SERVICE_T *user_service = service->base.userdata;
  
-			spin_lock(&msg_queue_spinlock);
+		down(&service->remove_event);
  
-			while (user_service->msg_remove !=
-				user_service->msg_insert) {
-				VCHIQ_HEADER_T *header = user_service->
-					msg_queue[user_service->msg_remove &
-						(MSG_QUEUE_SIZE - 1)];
-				user_service->msg_remove++;
-				spin_unlock(&msg_queue_spinlock);
+		BUG_ON(service->srvstate != VCHIQ_SRVSTATE_FREE);
  
-				if (header)
-					vchiq_release_message(
-						service->handle,
-						header);
-				spin_lock(&msg_queue_spinlock);
-			}
+		spin_lock(&msg_queue_spinlock);
  
+		while (user_service->msg_remove !=
+			user_service->msg_insert) {
+			VCHIQ_HEADER_T *header = user_service->
+				msg_queue[user_service->msg_remove &
+					(MSG_QUEUE_SIZE - 1)];
+			user_service->msg_remove++;
  			spin_unlock(&msg_queue_spinlock);
  
-			unlock_service(service);
+			if (header)
+				vchiq_release_message(
+					service->handle,
+					header);
+			spin_lock(&msg_queue_spinlock);
  		}
  
-		/* Release any closed services */
-		while (instance->completion_remove !=
-			instance->completion_insert) {
-			VCHIQ_COMPLETION_DATA_T *completion;
-			VCHIQ_SERVICE_T *service1;
-			completion = &instance->completions[
-				instance->completion_remove &
-				(MAX_COMPLETIONS - 1)];
-			service1 = completion->service_userdata;
-			if (completion->reason == VCHIQ_SERVICE_CLOSED)
-			{
-				USER_SERVICE_T *user_service =
-					service->base.userdata;
-
-				/* Wake any blocked user-thread */
-				if (instance->use_close_delivered)
-					up(&user_service->close_event);
-				unlock_service(service1);
-			}
-			instance->completion_remove++;
-		}
+		spin_unlock(&msg_queue_spinlock);
  
-		/* Release the PEER service count. */
-		vchiq_release_internal(instance->state, NULL);
+		unlock_service(service);
+	}
  
+	/* Release any closed services */
+	while (instance->completion_remove !=
+		instance->completion_insert) {
+		VCHIQ_COMPLETION_DATA_T *completion;
+		VCHIQ_SERVICE_T *service;
+		completion = &instance->completions[
+			instance->completion_remove &
+			(MAX_COMPLETIONS - 1)];
+		service = completion->service_userdata;
+		if (completion->reason == VCHIQ_SERVICE_CLOSED)
  		{
-			struct list_head *pos, *next;
-			list_for_each_safe(pos, next,
-				&instance->bulk_waiter_list) {
-				struct bulk_waiter_node *waiter;
-				waiter = list_entry(pos,
-					struct bulk_waiter_node,
-					list);
-				list_del(pos);
-				vchiq_log_info(vchiq_arm_log_level,
-					"bulk_waiter - cleaned up %x "
-					"for pid %d",
-					(unsigned int)waiter, waiter->pid);
-		                _sema_destroy(&waiter->bulk_waiter.event);
-				kfree(waiter);
-			}
-		}
+			USER_SERVICE_T *user_service =
+				service->base.userdata;
  
+			/* Wake any blocked user-thread */
+			if (instance->use_close_delivered)
+				up(&user_service->close_event);
+
+			unlock_service(service);
+		}
+		instance->completion_remove++;
  	}
-	else {
-		vchiq_log_error(vchiq_arm_log_level,
-			"Unknown minor device");
-		ret = -ENXIO;
+
+	/* Release the PEER service count. */
+	vchiq_release_internal(instance->state, NULL);
+
+	{
+		struct list_head *pos, *next;
+		list_for_each_safe(pos, next,
+			&instance->bulk_waiter_list) {
+			struct bulk_waiter_node *waiter;
+			waiter = list_entry(pos,
+				struct bulk_waiter_node,
+				list);
+			list_del(pos);
+			vchiq_log_info(vchiq_arm_log_level,
+				"bulk_waiter - cleaned up %zx "
+				"for pid %d",
+				(size_t)waiter, waiter->pid);
+			_sema_destroy(&waiter->bulk_waiter.event);
+			kfree(waiter);
+		}
  	}
  
  out:
  	return ret;
+
+}
+
+static void
+instance_dtr(void *data)
+{
+	VCHIQ_INSTANCE_T instance =  data;
+	_vchiq_close_instance(instance);
+	kfree(data);
+}
+
+static int
+vchiq_close(struct cdev *dev, int flags __unused, int fmt __unused,
+                struct thread *td)
+{
+
+	/* XXXMDC it's privdata that tracks opens */
+	/* XXXMDC only get closes when there are no more open fds on a vnode */
+
+	return(0);
+
  }
  
  /****************************************************************************
@@ -1435,9 +1653,9 @@ vchiq_dump_platform_instances(void *dump_context)
  			instance = service->instance;
  			if (instance && !instance->mark) {
  				len = snprintf(buf, sizeof(buf),
-					"Instance %x: pid %d,%s completions "
+					"Instance %zx: pid %d,%s completions "
  						"%d/%d",
-					(unsigned int)instance, instance->pid,
+					(size_t)instance, instance->pid,
  					instance->connected ? " connected, " :
  						"",
  					instance->completion_insert -
@@ -1465,8 +1683,8 @@ vchiq_dump_platform_service_state(void *dump_context, VCHIQ_SERVICE_T *service)
  	char buf[80];
  	int len;
  
-	len = snprintf(buf, sizeof(buf), "  instance %x",
-		(unsigned int)service->instance);
+	len = snprintf(buf, sizeof(buf), "  instance %zx",
+		(size_t)service->instance);
  
  	if ((service->base.callback == service_callback) &&
  		user_service->is_vchi) {
diff --git a/sys/contrib/vchiq/interface/vchiq_arm/vchiq_core.c b/sys/contrib/vchiq/interface/vchiq_arm/vchiq_core.c
index 2e30dd7dc3de..80a3a531e8b5 100644
--- a/sys/contrib/vchiq/interface/vchiq_arm/vchiq_core.c
+++ b/sys/contrib/vchiq/interface/vchiq_arm/vchiq_core.c
@@ -31,6 +31,9 @@
   * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   */
  
+/* For the PRIu64 format identifier */
+#include <machine/_inttypes.h>
+
  #include "vchiq_core.h"
  #include "vchiq_killable.h"
  
@@ -392,9 +395,9 @@ make_service_callback(VCHIQ_SERVICE_T *service, VCHIQ_REASON_T reason,
  	VCHIQ_HEADER_T *header, void *bulk_userdata)
  {
  	VCHIQ_STATUS_T status;
-	vchiq_log_trace(vchiq_core_log_level, "%d: callback:%d (%s, %x, %x)",
+	vchiq_log_trace(vchiq_core_log_level, "%d: callback:%d (%s, %tx, %tx)",
  		service->state->id, service->localport, reason_names[reason],
-		(unsigned int)header, (unsigned int)bulk_userdata);
+		(size_t)header, (size_t)bulk_userdata);
  	status = service->base.callback(reason, header, service->handle,
  		bulk_userdata);
  	if (status == VCHIQ_ERROR) {
@@ -417,13 +420,15 @@ vchiq_set_conn_state(VCHIQ_STATE_T *state, VCHIQ_CONNSTATE_T newstate)
  	vchiq_platform_conn_state_changed(state, oldstate, newstate);
  }
  
+#define ACTUAL_EVENT_SEM_ADDR(ref,offset)\
+	((struct semaphore *)(((size_t) ref) + ((size_t) offset)))
  static inline void
-remote_event_create(REMOTE_EVENT_T *event)
+remote_event_create(VCHIQ_STATE_T *ref, REMOTE_EVENT_T *event)
  {
  	event->armed = 0;
  	/* Don't clear the 'fired' flag because it may already have been set
  	** by the other side. */
-	_sema_init(event->event, 0);
+	_sema_init(ACTUAL_EVENT_SEM_ADDR(ref,event->event), 0);
  }
  
  __unused static inline void
@@ -433,13 +438,18 @@ remote_event_destroy(REMOTE_EVENT_T *event)
  }
  
  static inline int
-remote_event_wait(REMOTE_EVENT_T *event)
+remote_event_wait(VCHIQ_STATE_T *ref, REMOTE_EVENT_T *event)
  {
  	if (!event->fired) {
  		event->armed = 1;
+#if defined(__aarch64__)
+		dsb(sy);
+#else
  		dsb();
+#endif
+
  		if (!event->fired) {
-			if (down_interruptible(event->event) != 0) {
+			if (down_interruptible(ACTUAL_EVENT_SEM_ADDR(ref,event->event)) != 0) {
  				event->armed = 0;
  				return 0;
  			}
@@ -453,26 +463,32 @@ remote_event_wait(REMOTE_EVENT_T *event)
  }
  
  static inline void
-remote_event_signal_local(REMOTE_EVENT_T *event)
+remote_event_signal_local(VCHIQ_STATE_T *ref, REMOTE_EVENT_T *event)
  {
+/*
+ * Mirror
+ * https://github.com/raspberrypi/linux/commit/a50c4c9a65779ca835746b5fd79d3d5278afbdbe
+ * for extra safety
+ */
+	event->fired = 1;
  	event->armed = 0;
-	up(event->event);
+	up(ACTUAL_EVENT_SEM_ADDR(ref,event->event));
  }
  
  static inline void
-remote_event_poll(REMOTE_EVENT_T *event)
+remote_event_poll(VCHIQ_STATE_T *ref, REMOTE_EVENT_T *event)
  {
  	if (event->fired && event->armed)
-		remote_event_signal_local(event);
+		remote_event_signal_local(ref,event);
  }
  
  void
  remote_event_pollall(VCHIQ_STATE_T *state)
  {
-	remote_event_poll(&state->local->sync_trigger);
-	remote_event_poll(&state->local->sync_release);
-	remote_event_poll(&state->local->trigger);
-	remote_event_poll(&state->local->recycle);
+	remote_event_poll(state , &state->local->sync_trigger);
+	remote_event_poll(state , &state->local->sync_release);
+	remote_event_poll(state , &state->local->trigger);
+	remote_event_poll(state , &state->local->recycle);
  }
  
  /* Round up message sizes so that any space at the end of a slot is always big
@@ -553,7 +569,7 @@ request_poll(VCHIQ_STATE_T *state, VCHIQ_SERVICE_T *service, int poll_type)
  	wmb();
  
  	/* ... and ensure the slot handler runs. */
-	remote_event_signal_local(&state->local->trigger);
+	remote_event_signal_local(state, &state->local->trigger);
  }
  
  /* Called from queue_message, by the slot handler and application threads,
@@ -640,8 +656,8 @@ process_free_queue(VCHIQ_STATE_T *state)
  
  		rmb();
  
-		vchiq_log_trace(vchiq_core_log_level, "%d: pfq %d=%x %x %x",
-			state->id, slot_index, (unsigned int)data,
+		vchiq_log_trace(vchiq_core_log_level, "%d: pfq %d=%tx %x %x",
+			state->id, slot_index, (size_t)data,
  			local->slot_queue_recycle, slot_queue_available);
  
  		/* Initialise the bitmask for services which have used this
@@ -675,13 +691,13 @@ process_free_queue(VCHIQ_STATE_T *state)
  					vchiq_log_error(vchiq_core_log_level,
  						"service %d "
  						"message_use_count=%d "
-						"(header %x, msgid %x, "
+						"(header %tx, msgid %x, "
  						"header->msgid %x, "
  						"header->size %x)",
  						port,
  						service_quota->
  							message_use_count,
-						(unsigned int)header, msgid,
+						(size_t)header, msgid,
  						header->msgid,
  						header->size);
  					WARN(1, "invalid message use count\n");
@@ -704,24 +720,24 @@ process_free_queue(VCHIQ_STATE_T *state)
  						up(&service_quota->quota_event);
  						vchiq_log_trace(
  							vchiq_core_log_level,
-							"%d: pfq:%d %x@%x - "
+							"%d: pfq:%d %x@%tx - "
  							"slot_use->%d",
  							state->id, port,
  							header->size,
-							(unsigned int)header,
+							(size_t)header,
  							count - 1);
  					} else {
  						vchiq_log_error(
  							vchiq_core_log_level,
  								"service %d "
  								"slot_use_count"
-								"=%d (header %x"
+								"=%d (header %tx"
  								", msgid %x, "
  								"header->msgid"
  								" %x, header->"
  								"size %x)",
  							port, count,
-							(unsigned int)header,
+							(size_t)header,
  							msgid,
  							header->msgid,
  							header->size);
@@ -735,9 +751,9 @@ process_free_queue(VCHIQ_STATE_T *state)
  			pos += calc_stride(header->size);
  			if (pos > VCHIQ_SLOT_SIZE) {
  				vchiq_log_error(vchiq_core_log_level,
-					"pfq - pos %x: header %x, msgid %x, "
+					"pfq - pos %x: header %tx, msgid %x, "
  					"header->msgid %x, header->size %x",
-					pos, (unsigned int)header, msgid,
+					pos, (size_t)header, msgid,
  					header->msgid, header->size);
  				WARN(1, "invalid slot position\n");
  			}
@@ -885,17 +901,16 @@ queue_message(VCHIQ_STATE_T *state, VCHIQ_SERVICE_T *service,
  		int slot_use_count;
  
  		vchiq_log_info(vchiq_core_log_level,
-			"%d: qm %s@%x,%x (%d->%d)",
+			"%d: qm %s@%tx,%x (%d->%d)",
  			state->id,
  			msg_type_str(VCHIQ_MSG_TYPE(msgid)),
-			(unsigned int)header, size,
+			(size_t)header, size,
  			VCHIQ_MSG_SRCPORT(msgid),
  			VCHIQ_MSG_DSTPORT(msgid));
  
  		BUG_ON(!service);
  		BUG_ON((flags & (QMFLAGS_NO_MUTEX_LOCK |
  				 QMFLAGS_NO_MUTEX_UNLOCK)) != 0);
-
  		for (i = 0, pos = 0; i < (unsigned int)count;
  			pos += elements[i++].size)
  			if (elements[i].size) {
@@ -951,9 +966,9 @@ queue_message(VCHIQ_STATE_T *state, VCHIQ_SERVICE_T *service,
  		VCHIQ_SERVICE_STATS_ADD(service, ctrl_tx_bytes, size);
  	} else {
  		vchiq_log_info(vchiq_core_log_level,
-			"%d: qm %s@%x,%x (%d->%d)", state->id,
+			"%d: qm %s@%tx,%x (%d->%d)", state->id,
  			msg_type_str(VCHIQ_MSG_TYPE(msgid)),
-			(unsigned int)header, size,
+			(size_t)header, size,
  			VCHIQ_MSG_SRCPORT(msgid),
  			VCHIQ_MSG_DSTPORT(msgid));
  		if (size != 0) {
@@ -1017,7 +1032,7 @@ queue_message_sync(VCHIQ_STATE_T *state, VCHIQ_SERVICE_T *service,
  		(lmutex_lock_interruptible(&state->sync_mutex) != 0))
  		return VCHIQ_RETRY;
  
-	remote_event_wait(&local->sync_release);
+	remote_event_wait(state, &local->sync_release);
  
  	rmb();
  
@@ -1036,9 +1051,9 @@ queue_message_sync(VCHIQ_STATE_T *state, VCHIQ_SERVICE_T *service,
  		int i, pos;
  
  		vchiq_log_info(vchiq_sync_log_level,
-			"%d: qms %s@%x,%x (%d->%d)", state->id,
+			"%d: qms %s@%tx,%x (%d->%d)", state->id,
  			msg_type_str(VCHIQ_MSG_TYPE(msgid)),
-			(unsigned int)header, size,
+			(size_t)header, size,
  			VCHIQ_MSG_SRCPORT(msgid),
  			VCHIQ_MSG_DSTPORT(msgid));
  
@@ -1065,9 +1080,9 @@ queue_message_sync(VCHIQ_STATE_T *state, VCHIQ_SERVICE_T *service,
  		VCHIQ_SERVICE_STATS_ADD(service, ctrl_tx_bytes, size);
  	} else {
  		vchiq_log_info(vchiq_sync_log_level,
-			"%d: qms %s@%x,%x (%d->%d)", state->id,
+			"%d: qms %s@%tx,%x (%d->%d)", state->id,
  			msg_type_str(VCHIQ_MSG_TYPE(msgid)),
-			(unsigned int)header, size,
+			(size_t)header, size,
  			VCHIQ_MSG_SRCPORT(msgid),
  			VCHIQ_MSG_DSTPORT(msgid));
  		if (size != 0) {
@@ -1098,9 +1113,6 @@ queue_message_sync(VCHIQ_STATE_T *state, VCHIQ_SERVICE_T *service,
  			size);
  	}
  
-	/* Make sure the new header is visible to the peer. */
-	wmb();
-
  	remote_event_signal(&state->remote->sync_trigger);
  
  	if (VCHIQ_MSG_TYPE(msgid) != VCHIQ_MSG_PAUSE)
@@ -1368,26 +1380,26 @@ resolve_bulks(VCHIQ_SERVICE_T *service, VCHIQ_BULK_QUEUE_T *queue)
  				"Send Bulk to" : "Recv Bulk from";
  			if (bulk->actual != VCHIQ_BULK_ACTUAL_ABORTED)
  				vchiq_log_info(SRVTRACE_LEVEL(service),
-					"%s %c%c%c%c d:%d len:%d %x<->%x",
+					"%s %c%c%c%c d:%d len:%d %tx<->%tx",
  					header,
  					VCHIQ_FOURCC_AS_4CHARS(
  						service->base.fourcc),
  					service->remoteport,
  					bulk->size,
-					(unsigned int)bulk->data,
-					(unsigned int)bulk->remote_data);
+					(size_t)bulk->data,
+					(size_t)bulk->remote_data);
  			else
  				vchiq_log_info(SRVTRACE_LEVEL(service),
  					"%s %c%c%c%c d:%d ABORTED - tx len:%d,"
-					" rx len:%d %x<->%x",
+					" rx len:%d %tx<->%tx",
  					header,
  					VCHIQ_FOURCC_AS_4CHARS(
  						service->base.fourcc),
  					service->remoteport,
  					bulk->size,
  					bulk->remote_size,
-					(unsigned int)bulk->data,
-					(unsigned int)bulk->remote_data);
+					(size_t)bulk->data,
+					(size_t)bulk->remote_data);
  		}
  
  		vchiq_complete_bulk(bulk);
@@ -1522,8 +1534,8 @@ parse_open(VCHIQ_STATE_T *state, VCHIQ_HEADER_T *header)
  
  		fourcc = payload->fourcc;
  		vchiq_log_info(vchiq_core_log_level,
-			"%d: prs OPEN@%x (%d->'%c%c%c%c')",
-			state->id, (unsigned int)header,
+			"%d: prs OPEN@%tx (%d->'%c%c%c%c')",
+			state->id, (size_t)header,
  			localport,
  			VCHIQ_FOURCC_AS_4CHARS(fourcc));
  
@@ -1661,7 +1673,7 @@ parse_rx_slots(VCHIQ_STATE_T *state)
  
  		header = (VCHIQ_HEADER_T *)(state->rx_data +
  			(state->rx_pos & VCHIQ_SLOT_MASK));
-		DEBUG_VALUE(PARSE_HEADER, (int)header);
+		DEBUG_VALUE(PARSE_HEADER, (size_t)header);
  		msgid = header->msgid;
  		DEBUG_VALUE(PARSE_MSGID, msgid);
  		size = header->size;
@@ -1695,20 +1707,20 @@ parse_rx_slots(VCHIQ_STATE_T *state)
  					remoteport);
  				if (service)
  					vchiq_log_warning(vchiq_core_log_level,
-						"%d: prs %s@%x (%d->%d) - "
+						"%d: prs %s@%tx (%d->%d) - "
  						"found connected service %d",
  						state->id, msg_type_str(type),
-						(unsigned int)header,
+						(size_t)header,
  						remoteport, localport,
  						service->localport);
  			}
  
  			if (!service) {
  				vchiq_log_error(vchiq_core_log_level,
-					"%d: prs %s@%x (%d->%d) - "
+					"%d: prs %s@%zx (%d->%d) - "
  					"invalid/closed service %d",
  					state->id, msg_type_str(type),
-					(unsigned int)header,
+					(size_t)header,
  					remoteport, localport, localport);
  				goto skip_message;
  			}
@@ -1734,12 +1746,12 @@ parse_rx_slots(VCHIQ_STATE_T *state)
  					min(16, size));
  		}
  
-		if (((unsigned int)header & VCHIQ_SLOT_MASK) + calc_stride(size)
+		if (((size_t)header & VCHIQ_SLOT_MASK) + calc_stride(size)
  			> VCHIQ_SLOT_SIZE) {
  			vchiq_log_error(vchiq_core_log_level,
-				"header %x (msgid %x) - size %x too big for "
+				"header %tx (msgid %x) - size %x too big for "
  				"slot",
-				(unsigned int)header, (unsigned int)msgid,
+				(size_t)header, (unsigned int)msgid,
  				(unsigned int)size);
  			WARN(1, "oversized for slot\n");
  		}
@@ -1758,8 +1770,8 @@ parse_rx_slots(VCHIQ_STATE_T *state)
  				service->peer_version = payload->version;
  			}
  			vchiq_log_info(vchiq_core_log_level,
-				"%d: prs OPENACK@%x,%x (%d->%d) v:%d",
-				state->id, (unsigned int)header, size,
+				"%d: prs OPENACK@%tx,%x (%d->%d) v:%d",
+				state->id, (size_t)header, size,
  				remoteport, localport, service->peer_version);
  			if (service->srvstate ==
  				VCHIQ_SRVSTATE_OPENING) {
@@ -1776,8 +1788,8 @@ parse_rx_slots(VCHIQ_STATE_T *state)
  			WARN_ON(size != 0); /* There should be no data */
  
  			vchiq_log_info(vchiq_core_log_level,
-				"%d: prs CLOSE@%x (%d->%d)",
-				state->id, (unsigned int)header,
+				"%d: prs CLOSE@%tx (%d->%d)",
+				state->id, (size_t)header,
  				remoteport, localport);
  
  			mark_service_closing_internal(service, 1);
@@ -1794,8 +1806,8 @@ parse_rx_slots(VCHIQ_STATE_T *state)
  			break;
  		case VCHIQ_MSG_DATA:
  			vchiq_log_info(vchiq_core_log_level,
-				"%d: prs DATA@%x,%x (%d->%d)",
-				state->id, (unsigned int)header, size,
+				"%d: prs DATA@%tx,%x (%d->%d)",
+				state->id, (size_t)header, size,
  				remoteport, localport);
  
  			if ((service->remoteport == remoteport)
@@ -1819,14 +1831,23 @@ parse_rx_slots(VCHIQ_STATE_T *state)
  			break;
  		case VCHIQ_MSG_CONNECT:
  			vchiq_log_info(vchiq_core_log_level,
-				"%d: prs CONNECT@%x",
-				state->id, (unsigned int)header);
+				"%d: prs CONNECT@%tx",
+				state->id, (size_t)header);
  			state->version_common = ((VCHIQ_SLOT_ZERO_T *)
  						 state->slot_data)->version;
  			up(&state->connect);
  			break;
+/* 
+ * XXXMDC Apparently nothing uses this 
+ * https://github.com/raspberrypi/linux/commit/14f4d72fb799a9b3170a45ab80d4a3ddad541960
+ * but taking out the master bits is a whole new job
+ */
  		case VCHIQ_MSG_BULK_RX:
-		case VCHIQ_MSG_BULK_TX: {
+		case VCHIQ_MSG_BULK_TX:
+			WARN_ON(1);
+			break;
+#if 0
+		{
  			VCHIQ_BULK_QUEUE_T *queue;
  			WARN_ON(!state->is_master);
  			queue = (type == VCHIQ_MSG_BULK_RX) ?
@@ -1854,12 +1875,12 @@ parse_rx_slots(VCHIQ_STATE_T *state)
  				wmb();
  
  				vchiq_log_info(vchiq_core_log_level,
-					"%d: prs %s@%x (%d->%d) %x@%x",
+					"%d: prs %s@%tx (%d->%d) %x@%tx",
  					state->id, msg_type_str(type),
-					(unsigned int)header,
+					(size_t)header,
  					remoteport, localport,
  					bulk->remote_size,
-					(unsigned int)bulk->remote_data);
+					(size_t)bulk->remote_data);
  
  				queue->remote_insert++;
  
@@ -1888,9 +1909,11 @@ parse_rx_slots(VCHIQ_STATE_T *state)
  				lmutex_unlock(&service->bulk_mutex);
  				if (resolved)
  					notify_bulks(service, queue,
-						1/*retry_poll*/);
+						1//retry_poll
+						);
  			}
-		} break;
+		}
+#endif
  		case VCHIQ_MSG_BULK_RX_DONE:
  		case VCHIQ_MSG_BULK_TX_DONE:
  			WARN_ON(state->is_master);
@@ -1912,10 +1935,10 @@ parse_rx_slots(VCHIQ_STATE_T *state)
  				if ((int)(queue->remote_insert -
  					queue->local_insert) >= 0) {
  					vchiq_log_error(vchiq_core_log_level,
-						"%d: prs %s@%x (%d->%d) "
+						"%d: prs %s@%tx (%d->%d) "
  						"unexpected (ri=%d,li=%d)",
  						state->id, msg_type_str(type),
-						(unsigned int)header,
+						(size_t)header,
  						remoteport, localport,
  						queue->remote_insert,
  						queue->local_insert);
@@ -1932,11 +1955,11 @@ parse_rx_slots(VCHIQ_STATE_T *state)
  				queue->remote_insert++;
  
  				vchiq_log_info(vchiq_core_log_level,
-					"%d: prs %s@%x (%d->%d) %x@%x",
+					"%d: prs %s@%tx (%d->%d) %x@%tx",
  					state->id, msg_type_str(type),
-					(unsigned int)header,
+					(size_t)header,
  					remoteport, localport,
-					bulk->actual, (unsigned int)bulk->data);
+					bulk->actual, (size_t)bulk->data);
  
  				vchiq_log_trace(vchiq_core_log_level,
  					"%d: prs:%d %cx li=%x ri=%x p=%x",
@@ -1958,14 +1981,14 @@ parse_rx_slots(VCHIQ_STATE_T *state)
  			break;
  		case VCHIQ_MSG_PADDING:
  			vchiq_log_trace(vchiq_core_log_level,
-				"%d: prs PADDING@%x,%x",
-				state->id, (unsigned int)header, size);
+				"%d: prs PADDING@%tx,%x",
+				state->id, (size_t)header, size);
  			break;
  		case VCHIQ_MSG_PAUSE:
  			/* If initiated, signal the application thread */
  			vchiq_log_trace(vchiq_core_log_level,
-				"%d: prs PAUSE@%x,%x",
-				state->id, (unsigned int)header, size);
+				"%d: prs PAUSE@%tx,%x",
+				state->id, (size_t)header, size);
  			if (state->conn_state == VCHIQ_CONNSTATE_PAUSED) {
  				vchiq_log_error(vchiq_core_log_level,
  					"%d: PAUSE received in state PAUSED",
@@ -1988,8 +2011,8 @@ parse_rx_slots(VCHIQ_STATE_T *state)
  			break;
  		case VCHIQ_MSG_RESUME:
  			vchiq_log_trace(vchiq_core_log_level,
-				"%d: prs RESUME@%x,%x",
-				state->id, (unsigned int)header, size);
+				"%d: prs RESUME@%tx,%x",
+				state->id, (size_t)header, size);
  			/* Release the slot mutex */
  			lmutex_unlock(&state->slot_mutex);
  			if (state->is_master)
@@ -2010,8 +2033,8 @@ parse_rx_slots(VCHIQ_STATE_T *state)
  
  		default:
  			vchiq_log_error(vchiq_core_log_level,
-				"%d: prs invalid msgid %x@%x,%x",
-				state->id, msgid, (unsigned int)header, size);
+				"%d: prs invalid msgid %x@%tx,%x",
+				state->id, msgid, (size_t)header, size);
  			WARN(1, "invalid message\n");
  			break;
  		}
@@ -2051,7 +2074,7 @@ slot_handler_func(void *v)
  	while (1) {
  		DEBUG_COUNT(SLOT_HANDLER_COUNT);
  		DEBUG_TRACE(SLOT_HANDLER_LINE);
-		remote_event_wait(&local->trigger);
+		remote_event_wait(state, &local->trigger);
  
  		rmb();
  
@@ -2141,8 +2164,7 @@ recycle_func(void *v)
  	VCHIQ_SHARED_STATE_T *local = state->local;
  
  	while (1) {
-		remote_event_wait(&local->recycle);
-
+		remote_event_wait(state, &local->recycle);
  		process_free_queue(state);
  	}
  	return 0;
@@ -2165,7 +2187,7 @@ sync_func(void *v)
  		int type;
  		unsigned int localport, remoteport;
  
-		remote_event_wait(&local->sync_trigger);
+		remote_event_wait(state, &local->sync_trigger);
  
  		rmb();
  
@@ -2179,10 +2201,10 @@ sync_func(void *v)
  
  		if (!service) {
  			vchiq_log_error(vchiq_sync_log_level,
-				"%d: sf %s@%x (%d->%d) - "
+				"%d: sf %s@%tx (%d->%d) - "
  				"invalid/closed service %d",
  				state->id, msg_type_str(type),
-				(unsigned int)header,
+				(size_t)header,
  				remoteport, localport, localport);
  			release_message_sync(state, header);
  			continue;
@@ -2213,8 +2235,8 @@ sync_func(void *v)
  				service->peer_version = payload->version;
  			}
  			vchiq_log_info(vchiq_sync_log_level,
-				"%d: sf OPENACK@%x,%x (%d->%d) v:%d",
-				state->id, (unsigned int)header, size,
+				"%d: sf OPENACK@%tx,%x (%d->%d) v:%d",
+				state->id, (size_t)header, size,
  				remoteport, localport, service->peer_version);
  			if (service->srvstate == VCHIQ_SRVSTATE_OPENING) {
  				service->remoteport = remoteport;
@@ -2228,8 +2250,8 @@ sync_func(void *v)
  
  		case VCHIQ_MSG_DATA:
  			vchiq_log_trace(vchiq_sync_log_level,
-				"%d: sf DATA@%x,%x (%d->%d)",
-				state->id, (unsigned int)header, size,
+				"%d: sf DATA@%tx,%x (%d->%d)",
+				state->id, (size_t)header, size,
  				remoteport, localport);
  
  			if ((service->remoteport == remoteport) &&
@@ -2248,8 +2270,8 @@ sync_func(void *v)
  
  		default:
  			vchiq_log_error(vchiq_sync_log_level,
-				"%d: sf unexpected msgid %x@%x,%x",
-				state->id, msgid, (unsigned int)header, size);
+				"%d: sf unexpected msgid %x@%tx,%x",
+				state->id, msgid, (size_t)header, size);
  			release_message_sync(state, header);
  			break;
  		}
@@ -2282,7 +2304,7 @@ get_conn_state_name(VCHIQ_CONNSTATE_T conn_state)
  VCHIQ_SLOT_ZERO_T *
  vchiq_init_slots(void *mem_base, int mem_size)
  {
-	int mem_align = (VCHIQ_SLOT_SIZE - (int)mem_base) & VCHIQ_SLOT_MASK;
+	int mem_align = (int)((VCHIQ_SLOT_SIZE - (long)mem_base) & VCHIQ_SLOT_MASK);
  	VCHIQ_SLOT_ZERO_T *slot_zero =
  		(VCHIQ_SLOT_ZERO_T *)((char *)mem_base + mem_align);
  	int num_slots = (mem_size - mem_align)/VCHIQ_SLOT_SIZE;
@@ -2334,8 +2356,8 @@ vchiq_init_state(VCHIQ_STATE_T *state, VCHIQ_SLOT_ZERO_T *slot_zero,
  	if (slot_zero->magic != VCHIQ_MAGIC) {
  		vchiq_loud_error_header();
  		vchiq_loud_error("Invalid VCHIQ magic value found.");
-		vchiq_loud_error("slot_zero=%x: magic=%x (expected %x)",
-			(unsigned int)slot_zero, slot_zero->magic, VCHIQ_MAGIC);
+		vchiq_loud_error("slot_zero=%tx: magic=%x (expected %x)",
+			(size_t)slot_zero, slot_zero->magic, VCHIQ_MAGIC);
  		vchiq_loud_error_footer();
  		return VCHIQ_ERROR;
  	}
@@ -2348,9 +2370,9 @@ vchiq_init_state(VCHIQ_STATE_T *state, VCHIQ_SLOT_ZERO_T *slot_zero,
  	if (slot_zero->version < VCHIQ_VERSION_MIN) {
  		vchiq_loud_error_header();
  		vchiq_loud_error("Incompatible VCHIQ versions found.");
-		vchiq_loud_error("slot_zero=%x: VideoCore version=%d "
+		vchiq_loud_error("slot_zero=%tx: VideoCore version=%d "
  			"(minimum %d)",
-			(unsigned int)slot_zero, slot_zero->version,
+			(size_t)slot_zero, slot_zero->version,
  			VCHIQ_VERSION_MIN);
  		vchiq_loud_error("Restart with a newer VideoCore image.");
  		vchiq_loud_error_footer();
@@ -2360,9 +2382,9 @@ vchiq_init_state(VCHIQ_STATE_T *state, VCHIQ_SLOT_ZERO_T *slot_zero,
  	if (VCHIQ_VERSION < slot_zero->version_min) {
  		vchiq_loud_error_header();
  		vchiq_loud_error("Incompatible VCHIQ versions found.");
-		vchiq_loud_error("slot_zero=%x: version=%d (VideoCore "
+		vchiq_loud_error("slot_zero=%tx: version=%d (VideoCore "
  			"minimum %d)",
-			(unsigned int)slot_zero, VCHIQ_VERSION,
+			(size_t)slot_zero, VCHIQ_VERSION,
  			slot_zero->version_min);
  		vchiq_loud_error("Restart with a newer kernel.");
  		vchiq_loud_error_footer();
@@ -2375,25 +2397,25 @@ vchiq_init_state(VCHIQ_STATE_T *state, VCHIQ_SLOT_ZERO_T *slot_zero,
  		 (slot_zero->max_slots_per_side != VCHIQ_MAX_SLOTS_PER_SIDE)) {
  		vchiq_loud_error_header();
  		if (slot_zero->slot_zero_size != sizeof(VCHIQ_SLOT_ZERO_T))
-			vchiq_loud_error("slot_zero=%x: slot_zero_size=%x "
+			vchiq_loud_error("slot_zero=%tx: slot_zero_size=%x "
  				"(expected %zx)",
-				(unsigned int)slot_zero,
+				(size_t)slot_zero,
  				slot_zero->slot_zero_size,
  				sizeof(VCHIQ_SLOT_ZERO_T));
  		if (slot_zero->slot_size != VCHIQ_SLOT_SIZE)
-			vchiq_loud_error("slot_zero=%x: slot_size=%d "
+			vchiq_loud_error("slot_zero=%tx: slot_size=%d "
  				"(expected %d",
-				(unsigned int)slot_zero, slot_zero->slot_size,
+				(size_t)slot_zero, slot_zero->slot_size,
  				VCHIQ_SLOT_SIZE);
  		if (slot_zero->max_slots != VCHIQ_MAX_SLOTS)
-			vchiq_loud_error("slot_zero=%x: max_slots=%d "
+			vchiq_loud_error("slot_zero=%tx: max_slots=%d "
  				"(expected %d)",
-				(unsigned int)slot_zero, slot_zero->max_slots,
+				(size_t)slot_zero, slot_zero->max_slots,
  				VCHIQ_MAX_SLOTS);
  		if (slot_zero->max_slots_per_side != VCHIQ_MAX_SLOTS_PER_SIDE)
-			vchiq_loud_error("slot_zero=%x: max_slots_per_side=%d "
+			vchiq_loud_error("slot_zero=%tx: max_slots_per_side=%d "
  				"(expected %d)",
-				(unsigned int)slot_zero,
+				(size_t)slot_zero,
  				slot_zero->max_slots_per_side,
  				VCHIQ_MAX_SLOTS_PER_SIDE);
  		vchiq_loud_error_footer();
@@ -2478,24 +2500,24 @@ vchiq_init_state(VCHIQ_STATE_T *state, VCHIQ_SLOT_ZERO_T *slot_zero,
  	state->data_use_count = 0;
  	state->data_quota = state->slot_queue_available - 1;
  
-	local->trigger.event = &state->trigger_event;
-	remote_event_create(&local->trigger);
+	local->trigger.event = offsetof(VCHIQ_STATE_T, trigger_event);
+	remote_event_create(state, &local->trigger);
  	local->tx_pos = 0;
  
-	local->recycle.event = &state->recycle_event;
-	remote_event_create(&local->recycle);
+	local->recycle.event = offsetof(VCHIQ_STATE_T, recycle_event);
+	remote_event_create(state, &local->recycle);
  	local->slot_queue_recycle = state->slot_queue_available;
  
-	local->sync_trigger.event = &state->sync_trigger_event;
-	remote_event_create(&local->sync_trigger);
+	local->sync_trigger.event = offsetof(VCHIQ_STATE_T, sync_trigger_event);
+	remote_event_create(state, &local->sync_trigger);
  
-	local->sync_release.event = &state->sync_release_event;
-	remote_event_create(&local->sync_release);
+	local->sync_release.event = offsetof(VCHIQ_STATE_T, sync_release_event);
+	remote_event_create(state, &local->sync_release);
  
  	/* At start-of-day, the slot is empty and available */
  	((VCHIQ_HEADER_T *)SLOT_DATA_FROM_INDEX(state, local->slot_sync))->msgid
  		= VCHIQ_MSGID_PADDING;
-	remote_event_signal_local(&local->sync_release);
+	remote_event_signal_local(state, &local->sync_release);
  
  	local->debug[DEBUG_ENTRIES] = DEBUG_MAX;
  
@@ -2775,18 +2797,18 @@ release_service_messages(VCHIQ_SERVICE_T *service)
  				if ((port == service->localport) &&
  					(msgid & VCHIQ_MSGID_CLAIMED)) {
  					vchiq_log_info(vchiq_core_log_level,
-						"  fsi - hdr %x",
-						(unsigned int)header);
+						"  fsi - hdr %tx",
+						(size_t)header);
  					release_slot(state, slot_info, header,
  						NULL);
  				}
  				pos += calc_stride(header->size);
  				if (pos > VCHIQ_SLOT_SIZE) {
  					vchiq_log_error(vchiq_core_log_level,
-						"fsi - pos %x: header %x, "
+						"fsi - pos %x: header %tx, "
  						"msgid %x, header->msgid %x, "
  						"header->size %x",
-						pos, (unsigned int)header,
+						pos, (size_t)header,
  						msgid, header->msgid,
  						header->size);
  					WARN(1, "invalid slot position\n");
@@ -3360,10 +3382,10 @@ vchiq_bulk_transfer(VCHIQ_SERVICE_HANDLE_T handle,
  	wmb();
  
  	vchiq_log_info(vchiq_core_log_level,
-		"%d: bt (%d->%d) %cx %x@%x %x",
+		"%d: bt (%d->%d) %cx %x@%tx %tx",
  		state->id,
  		service->localport, service->remoteport, dir_char,
-		size, (unsigned int)bulk->data, (unsigned int)userdata);
+		size, (size_t)bulk->data, (size_t)userdata);
  
  	/* The slot mutex must be held when the service is being closed, so
  	   claim it here to ensure that isn't happening */
@@ -3382,7 +3404,7 @@ vchiq_bulk_transfer(VCHIQ_SERVICE_HANDLE_T handle,
  				(dir == VCHIQ_BULK_TRANSMIT) ?
  				VCHIQ_POLL_TXNOTIFY : VCHIQ_POLL_RXNOTIFY);
  	} else {
-		int payload[2] = { (int)bulk->data, bulk->size };
+		uint32_t payload[2] = { (uint32_t)(uintptr_t)bulk->data, bulk->size };
  		VCHIQ_ELEMENT_T element = { payload, sizeof(payload) };
  
  		status = queue_message(state, NULL,
@@ -3526,7 +3548,6 @@ static void
  release_message_sync(VCHIQ_STATE_T *state, VCHIQ_HEADER_T *header)
  {
  	header->msgid = VCHIQ_MSGID_PADDING;
-	wmb();
  	remote_event_signal(&state->remote->sync_release);
  }
  
@@ -3710,12 +3731,12 @@ vchiq_dump_state(void *dump_context, VCHIQ_STATE_T *state)
  	vchiq_dump(dump_context, buf, len + 1);
  
  	len = snprintf(buf, sizeof(buf),
-		"  tx_pos=%x(@%x), rx_pos=%x(@%x)",
+		"  tx_pos=%x(@%tx), rx_pos=%x(@%tx)",
  		state->local->tx_pos,
-		(uint32_t)state->tx_data +
+		(size_t)state->tx_data +
  			(state->local_tx_pos & VCHIQ_SLOT_MASK),
  		state->rx_pos,
-		(uint32_t)state->rx_data +
+		(size_t)state->rx_data +
  			(state->rx_pos & VCHIQ_SLOT_MASK));
  	vchiq_dump(dump_context, buf, len + 1);
  
@@ -3817,8 +3838,8 @@ vchiq_dump_service_state(void *dump_context, VCHIQ_SERVICE_T *service)
  			vchiq_dump(dump_context, buf, len + 1);
  
  			len = snprintf(buf, sizeof(buf),
-				"  Ctrl: tx_count=%d, tx_bytes=%llu, "
-				"rx_count=%d, rx_bytes=%llu",
+				"  Ctrl: tx_count=%d, tx_bytes=%"PRIu64", "
+				"rx_count=%d, rx_bytes=%"PRIu64"",
  				service->stats.ctrl_tx_count,
  				service->stats.ctrl_tx_bytes,
  				service->stats.ctrl_rx_count,
@@ -3826,8 +3847,8 @@ vchiq_dump_service_state(void *dump_context, VCHIQ_SERVICE_T *service)
  			vchiq_dump(dump_context, buf, len + 1);
  
  			len = snprintf(buf, sizeof(buf),
-				"  Bulk: tx_count=%d, tx_bytes=%llu, "
-				"rx_count=%d, rx_bytes=%llu",
+				"  Bulk: tx_count=%d, tx_bytes=%"PRIu64", "
+				"rx_count=%d, rx_bytes=%"PRIu64"",
  				service->stats.bulk_tx_count,
  				service->stats.bulk_tx_bytes,
  				service->stats.bulk_rx_count,
diff --git a/sys/contrib/vchiq/interface/vchiq_arm/vchiq_core.h b/sys/contrib/vchiq/interface/vchiq_arm/vchiq_core.h
index 38ede407f4f4..4e3f41203bc4 100644
--- a/sys/contrib/vchiq/interface/vchiq_arm/vchiq_core.h
+++ b/sys/contrib/vchiq/interface/vchiq_arm/vchiq_core.h
@@ -184,12 +184,21 @@ enum {
  #if VCHIQ_ENABLE_DEBUG
  
  #define DEBUG_INITIALISE(local) int *debug_ptr = (local)->debug;
+#if defined(__aarch64__)
+#define DEBUG_TRACE(d) \
+	do { debug_ptr[DEBUG_ ## d] = __LINE__; dsb(sy); } while (0)
+#define DEBUG_VALUE(d, v) \
+	do { debug_ptr[DEBUG_ ## d] = (v); dsb(sy); } while (0)
+#define DEBUG_COUNT(d) \
+	do { debug_ptr[DEBUG_ ## d]++; dsb(sy); } while (0)
+#else
  #define DEBUG_TRACE(d) \
  	do { debug_ptr[DEBUG_ ## d] = __LINE__; dsb(); } while (0)
  #define DEBUG_VALUE(d, v) \
  	do { debug_ptr[DEBUG_ ## d] = (v); dsb(); } while (0)
  #define DEBUG_COUNT(d) \
  	do { debug_ptr[DEBUG_ ## d]++; dsb(); } while (0)
+#endif
  
  #else /* VCHIQ_ENABLE_DEBUG */
  
@@ -265,7 +274,7 @@ typedef struct vchiq_bulk_queue_struct {
  typedef struct remote_event_struct {
  	int armed;
  	int fired;
-	struct semaphore *event;
+	uint32_t event;
  } REMOTE_EVENT_T;
  
  typedef struct opaque_platform_state_t *VCHIQ_PLATFORM_STATE_T;
diff --git a/sys/contrib/vchiq/interface/vchiq_arm/vchiq_ioctl.h b/sys/contrib/vchiq/interface/vchiq_arm/vchiq_ioctl.h
index 617479eff136..90348ca4b0d0 100644
--- a/sys/contrib/vchiq/interface/vchiq_arm/vchiq_ioctl.h
+++ b/sys/contrib/vchiq/interface/vchiq_arm/vchiq_ioctl.h
@@ -127,4 +127,125 @@ typedef struct {
  #define VCHIQ_IOC_CLOSE_DELIVERED      _IO(VCHIQ_IOC_MAGIC,   17)
  #define VCHIQ_IOC_MAX                  17
  
+
+/*
+ * COMPAT_FREEBSD32
+ */
+
+typedef struct {
+	unsigned int config_size;
+	/*VCHIQ_CONFIG_T * */ uint32_t pconfig;
+} VCHIQ_GET_CONFIG32_T;
+
+typedef struct {
+	unsigned int handle;
+	/*void * */ uint32_t data;
+	unsigned int size;
+	/*void * */ uint32_t userdata;
+	VCHIQ_BULK_MODE_T mode;
+} VCHIQ_QUEUE_BULK_TRANSFER32_T;
+
+typedef struct {
+	unsigned int handle;
+	unsigned int count;
+	const /*VCHIQ_ELEMENT_T * */ uint32_t elements;
+} VCHIQ_QUEUE_MESSAGE32_T;
+
+typedef struct {
+	unsigned int handle;
+	int blocking;
+	unsigned int bufsize;
+	/*void * */ uint32_t buf;
+} VCHIQ_DEQUEUE_MESSAGE32_T;
+
+typedef struct {
+	/*void * */ uint32_t virt_addr;
+	/*size_t*/  uint32_t num_bytes;
+} VCHIQ_DUMP_MEM32_T;
+
+typedef struct {
+	VCHIQ_REASON_T reason;
+	/* VCHIQ_HEADER_T * */ uint32_t header;
+	/* void * */ uint32_t service_userdata;
+	/* void * */ uint32_t bulk_userdata;
+} VCHIQ_COMPLETION_DATA32_T;
+
+typedef struct {
+	unsigned int count;
+	/* VCHIQ_COMPLETION_DATA32_T * */ uint32_t buf;
+	unsigned int msgbufsize;
+	unsigned int msgbufcount; /* IN/OUT */
+	/* void ** */ uint32_t msgbufs;
+} VCHIQ_AWAIT_COMPLETION32_T;
+
+typedef struct vchiq_service_params32_struct {
+	int fourcc;
+	/* VCHIQ_CALLBACK_T */ uint32_t  callback;
+	/*void * */ uint32_t userdata;
+	short version;       /* Increment for non-trivial changes */
+	short version_min;   /* Update for incompatible changes */
+} VCHIQ_SERVICE_PARAMS32_T;
+
+typedef struct {
+	VCHIQ_SERVICE_PARAMS32_T params;
+	int is_open;
+	int is_vchi;
+	unsigned int handle;       /* OUT */
+} VCHIQ_CREATE_SERVICE32_T;
+
+typedef struct {
+	const /*void */ uint32_t data;
+	unsigned int size;
+} VCHIQ_ELEMENT32_T;
+
+
+#define VCHIQ_IOC_GET_CONFIG32 \
+	_IOC_NEWTYPE( \
+		VCHIQ_IOC_GET_CONFIG, \
+		VCHIQ_GET_CONFIG32_T \
+	)
+
+#define VCHIQ_IOC_QUEUE_BULK_TRANSMIT32 \
+	_IOC_NEWTYPE( \
+		VCHIQ_IOC_QUEUE_BULK_TRANSMIT, \
+		VCHIQ_QUEUE_BULK_TRANSFER32_T \
+	)
+
+#define VCHIQ_IOC_QUEUE_BULK_RECEIVE32 \
+	_IOC_NEWTYPE( \
+		VCHIQ_IOC_QUEUE_BULK_RECEIVE, \
+		VCHIQ_QUEUE_BULK_TRANSFER32_T \
+	)
+
+#define VCHIQ_IOC_QUEUE_MESSAGE32 \
+	_IOC_NEWTYPE( \
+		VCHIQ_IOC_QUEUE_MESSAGE, \
+		VCHIQ_QUEUE_MESSAGE32_T \
+	)
+
+#define VCHIQ_IOC_DEQUEUE_MESSAGE32 \
+	_IOC_NEWTYPE( \
+		VCHIQ_IOC_DEQUEUE_MESSAGE, \
+		VCHIQ_DEQUEUE_MESSAGE32_T \
+	)
+
+#define VCHIQ_IOC_DUMP_PHYS_MEM32 \
+	_IOC_NEWTYPE( \
+		VCHIQ_IOC_DUMP_PHYS_MEM, \
+		VCHIQ_DUMP_MEM32_T \
+	)
+
+#define VCHIQ_IOC_AWAIT_COMPLETION32 \
+	_IOC_NEWTYPE( \
+		VCHIQ_IOC_AWAIT_COMPLETION, \
+		VCHIQ_AWAIT_COMPLETION32_T \
+	)
+
+#define VCHIQ_IOC_CREATE_SERVICE32 \
+	_IOC_NEWTYPE( \
+		VCHIQ_IOC_CREATE_SERVICE, \
+		VCHIQ_CREATE_SERVICE32_T \
+	)
+
+
  #endif
diff --git a/sys/contrib/vchiq/interface/vchiq_arm/vchiq_kern_lib.c b/sys/contrib/vchiq/interface/vchiq_arm/vchiq_kern_lib.c
index 1f849a09d854..22b988dcf436 100644
--- a/sys/contrib/vchiq/interface/vchiq_arm/vchiq_kern_lib.c
+++ b/sys/contrib/vchiq/interface/vchiq_arm/vchiq_kern_lib.c
@@ -151,9 +151,9 @@ VCHIQ_STATUS_T vchiq_shutdown(VCHIQ_INSTANCE_T instance)
  					list);
  			list_del(pos);
  			vchiq_log_info(vchiq_arm_log_level,
-					"bulk_waiter - cleaned up %x "
+					"bulk_waiter - cleaned up %tx "
  					"for pid %d",
-					(unsigned int)waiter, waiter->pid);
+					(size_t)waiter, waiter->pid);
  			_sema_destroy(&waiter->bulk_waiter.event);
  
  			kfree(waiter);
@@ -454,8 +454,8 @@ vchiq_blocking_bulk_transfer(VCHIQ_SERVICE_HANDLE_T handle, void *data,
  		list_add(&waiter->list, &instance->bulk_waiter_list);
  		lmutex_unlock(&instance->bulk_waiter_list_mutex);
  		vchiq_log_info(vchiq_arm_log_level,
-				"saved bulk_waiter %x for pid %d",
-				(unsigned int)waiter, current->p_pid);
+				"saved bulk_waiter %tx for pid %d",
+				(size_t)waiter, current->p_pid);
  	}
  
  	return status;
diff --git a/sys/contrib/vchiq/interface/vchiq_arm/vchiq_kmod.c b/sys/contrib/vchiq/interface/vchiq_arm/vchiq_kmod.c
index 5b47377735f1..5c7cf9035413 100644
--- a/sys/contrib/vchiq/interface/vchiq_arm/vchiq_kmod.c
+++ b/sys/contrib/vchiq/interface/vchiq_arm/vchiq_kmod.c
@@ -47,7 +47,11 @@ __FBSDID("$FreeBSD$");
  #include <dev/ofw/ofw_bus_subr.h>
  
  #include <machine/bus.h>
+/* XXXMDC Is this necessary at all? */
+#if defined(__aarch64__)
+#else
  #include <machine/fdt.h>
+#endif
  
  #include "vchiq_arm.h"
  #include "vchiq_2835.h"
@@ -78,13 +82,31 @@ struct bcm_vchiq_softc {
  
  static struct bcm_vchiq_softc *bcm_vchiq_sc = NULL;
  
-#define	BSD_DTB			1
-#define	UPSTREAM_DTB		2
+
+#define CONFIG_INVALID 0
+#define CONFIG_VALID 1 << 0
+#define BSD_REG_ADDRS 1 << 1
+#define LONG_BULK_SPACE 1 << 2
+
+/*
+ * Also controls the use of the standard VC address offset for bulk data DMA
+ * (normal bulks use that offset; bulks for long address spaces use physical
+ * page addresses)
+ */
+extern unsigned int g_long_bulk_space;
+
+
+/*
+ * XXXMDC
+ * The man page for ofw_bus_is_compatible describes ``features''
+ * as ``can be used''. Here we use understand them as ``must be used''
+ */ 
+
  static struct ofw_compat_data compat_data[] = {
-	{"broadcom,bcm2835-vchiq",	BSD_DTB},
-	{"brcm,bcm2835-vchiq",		UPSTREAM_DTB},
-	{"brcm,bcm2711-vchiq",		UPSTREAM_DTB},
-	{NULL,				0}
+	{"broadcom,bcm2835-vchiq",	BSD_REG_ADDRS | CONFIG_VALID},
+	{"brcm,bcm2835-vchiq",		CONFIG_VALID},
+	{"brcm,bcm2711-vchiq",		LONG_BULK_SPACE | CONFIG_VALID},
+	{NULL,				CONFIG_INVALID}
  };
  
  #define	vchiq_read_4(reg)		\
@@ -119,13 +141,23 @@ bcm_vchiq_intr(void *arg)
  void
  remote_event_signal(REMOTE_EVENT_T *event)
  {
-	event->fired = 1;
  
+	wmb();
+
+	event->fired = 1;
  	/* The test on the next line also ensures the write on the previous line
  		has completed */
+	/* UPDATE: not on arm64, it would seem... */
+#if defined(__aarch64__)
+	dsb(sy);
+#endif
  	if (event->armed) {
  		/* trigger vc interrupt */
+#if defined(__aarch64__)
+		dsb(sy);
+#else
  		dsb();
+#endif
  		vchiq_write_4(0x48, 0);
  	}
  }
@@ -134,13 +166,17 @@ static int
  bcm_vchiq_probe(device_t dev)
  {
  
-	if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0)
+	if ((ofw_bus_search_compatible(dev, compat_data)->ocd_data & CONFIG_VALID) == 0)
  		return (ENXIO);
  
  	device_set_desc(dev, "BCM2835 VCHIQ");
  	return (BUS_PROBE_DEFAULT);
  }
  
+/* debug_sysctl */
+extern int vchiq_core_log_level;
+extern int vchiq_arm_log_level;
+
  static int
  bcm_vchiq_attach(device_t dev)
  {
@@ -168,14 +204,36 @@ bcm_vchiq_attach(device_t dev)
  		return (ENXIO);
  	}
  
-	if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == UPSTREAM_DTB)
+	uintptr_t dev_compat_d = ofw_bus_search_compatible(dev, compat_data)->ocd_data;
+	/* XXXMDC: shouldn't happen (checked for in probe)--but, for symmetry */
+	if ((dev_compat_d & CONFIG_VALID) == 0){
+		device_printf(dev, "attempting to attach using invalid config.\n");
+		bus_release_resource(dev, SYS_RES_IRQ, rid, sc->irq_res);
+		return (EINVAL);
+	}
+	if ((dev_compat_d & BSD_REG_ADDRS) == 0)
  		sc->regs_offset = -0x40;
+	if(dev_compat_d & LONG_BULK_SPACE)
+		g_long_bulk_space = 1;
  
  	node = ofw_bus_get_node(dev);
  	if ((OF_getencprop(node, "cache-line-size", &cell, sizeof(cell))) > 0)
  		g_cache_line_size = cell;
  
  	vchiq_core_initialize();
+	
+	/* debug_sysctl */
+        struct sysctl_ctx_list *ctx_l = device_get_sysctl_ctx(dev);
+        struct sysctl_oid *tree_node = device_get_sysctl_tree(dev);
+        struct sysctl_oid_list *tree = SYSCTL_CHILDREN(tree_node);  
+	SYSCTL_ADD_INT(
+		ctx_l, tree, OID_AUTO, "log", CTLFLAG_RW,
+		&vchiq_core_log_level, vchiq_core_log_level, "log level"
+	);
+	SYSCTL_ADD_INT(
+		ctx_l, tree, OID_AUTO, "arm_log", CTLFLAG_RW,
+		&vchiq_arm_log_level, vchiq_arm_log_level, "arm log level"
+	);
  
  	/* Setup and enable the timer */
  	if (bus_setup_intr(dev, sc->irq_res, INTR_TYPE_MISC | INTR_MPSAFE,
diff --git a/sys/contrib/vchiq/interface/vchiq_arm/vchiq_pagelist.h b/sys/contrib/vchiq/interface/vchiq_arm/vchiq_pagelist.h
index 72c362464cc2..d1cb9f1e1658 100644
--- a/sys/contrib/vchiq/interface/vchiq_arm/vchiq_pagelist.h
+++ b/sys/contrib/vchiq/interface/vchiq_arm/vchiq_pagelist.h
@@ -42,10 +42,10 @@
  #define PAGELIST_READ_WITH_FRAGMENTS 2
  
  typedef struct pagelist_struct {
-	unsigned long length;
-	unsigned short type;
-	unsigned short offset;
-	unsigned long addrs[1];	/* N.B. 12 LSBs hold the number of following
+	uint32_t length;
+	uint16_t type;
+	uint16_t offset;
+	uint32_t addrs[1];	/* N.B. 12 LSBs hold the number of following
  				   pages at consecutive addresses. */
  } PAGELIST_T;
  
diff --git a/sys/contrib/vchiq/interface/vchiq_arm/vchiq_shim.c b/sys/contrib/vchiq/interface/vchiq_arm/vchiq_shim.c
index cc8ef2e071f8..f33c545cea45 100644
--- a/sys/contrib/vchiq/interface/vchiq_arm/vchiq_shim.c
+++ b/sys/contrib/vchiq/interface/vchiq_arm/vchiq_shim.c
@@ -398,7 +398,7 @@ EXPORT_SYMBOL(vchi_msg_queuev);
   ***********************************************************/
  int32_t vchi_held_msg_release(VCHI_HELD_MSG_T *message)
  {
-	vchiq_release_message((VCHIQ_SERVICE_HANDLE_T)message->service,
+	vchiq_release_message((VCHIQ_SERVICE_HANDLE_T)(size_t)message->service,
  		(VCHIQ_HEADER_T *)message->message);
  
  	return 0;
@@ -444,7 +444,7 @@ int32_t vchi_msg_hold(VCHI_SERVICE_HANDLE_T handle,
  	*msg_size = header->size;
  
  	message_handle->service =
-		(struct opaque_vchi_service_t *)service->handle;
+		(struct opaque_vchi_service_t *)(unsigned long)service->handle;
  	message_handle->message = header;
  
  	return 0;
-- 
2.32.0




On Mon, Feb 28, 2022 at 12:42:24PM -0700, Warner Losh wrote:
>On Mon, Feb 28, 2022, 12:36 PM Marco Devesas Campos <
>[email protected]> wrote:
>
>> Entirely right, Ronald — thanks for catching it!
>>
>
>Oops
>
>Warner, can I send you a consolidated patch later in the week? What’s the
>> best way to submit it?
>>
>
>Git format-patch is likely best.
>
>Warner
>
>
>> Best,
>> Marco
>>
>> On 28 Feb 2022, at 19:26, Ronald Klop <[email protected]> wrote:
>>
>> On Sun, 27 Feb 2022 17:41:25 +0100, Warner Losh <[email protected]> wrote:
>>
>>
>>
>> On Sun, Feb 27, 2022 at 8:44 AM Marco Devesas Campos <
>> [email protected]> wrote:
>>
>>> Hi, List
>>>
>>> On the back of Ronald Klop's comments (thanks!), I went and got myself an
>>> RPI 4 and it turns out all that was need was adding the right dtb
>>> reference and it all works (seemingly) fine (incremental patch attached).
>>>
>>
>> I've committed the patch below. If it turns out we need more, we can
>> always augment.
>>
>>
>>
>> Hi Marco, Warner,
>>
>> Isn't the patch from
>> https://lists.freebsd.org/archives/freebsd-arm/2022-February/000949.html
>> needed also?
>> As you mention the patch below is an incremental patch?
>>
>> Regards,
>> Ronald.
>>
>>
>>
>>
>>
>>
>>
>> Warner
>>
>>
>>> One of the potential projects highlighted in the latest call for proposals
>>> was exactly to get hdmi audio output in 64 bit Pis, viz. the 400-s. If
>>> anyone who voted for that reads this list, wd be nice to get some input on
>>> the patches.
>>>
>>> Best,
>>> Marco
>>>
>>>
>>>
>>> diff --git a/sys/contrib/vchiq/interface/vchiq_arm/vchiq_kmod.c
>>> b/sys/contrib/vchiq/interface/vchiq_arm/vchiq_kmod.c
>>> index dc18678b99a3..344267ff0c1c 100644
>>> --- a/sys/contrib/vchiq/interface/vchiq_arm/vchiq_kmod.c
>>> +++ b/sys/contrib/vchiq/interface/vchiq_arm/vchiq_kmod.c
>>> @@ -83,6 +83,7 @@ static struct bcm_vchiq_softc *bcm_vchiq_sc = NULL;
>>>  static struct ofw_compat_data compat_data[] = {
>>>         {"broadcom,bcm2835-vchiq",      BSD_DTB},
>>>         {"brcm,bcm2835-vchiq",          UPSTREAM_DTB},
>>> +       {"brcm,bcm2711-vchiq",          UPSTREAM_DTB},
>>>         {NULL,                          0}
>>>  };
>>>
>>>
>>>
>>> > On 8 Feb 2022, at 08:49, Ronald Klop <[email protected]> wrote:
>>> >
>>> > Van: Ronald Klop <[email protected]>
>>> > Datum: maandag, 7 februari 2022 21:05
>>> > Aan: Marco Devesas Campos <[email protected]>,
>>> [email protected]
>>> > Onderwerp: Re: [PATCH] Experimental vchiq and bcm2835_audio support for
>>> arm64
>>> >
>>> > On 2/6/22 14:46, Marco Devesas Campos wrote:
>>> > > Hi Ronald,
>>> > >
>>> > > Thanks so much for trying out the patch out.
>>> > >
>>> > >> On 6 Feb 2022, at 13:05, Ronald Klop <[email protected]> wrote:
>>> > >>
>>> > >> Hi,
>>> > >>
>>> > >> I compiled this on a RPI4 + 14-CURRENT. It boots, but I see no
>>> difference in available devices.
>>> > >> I can try to boot it on a RPI3B+ on another time.
>>> > >
>>> > > I *think* the GPU/VC in RPI-4 is a very different beast from the
>>> others. I'll
>>> > > look into it, but if you could give it a try on the 3+ I'd be much
>>> obliged.
>>> > >
>>> > >>
>>> > >> What would be the expected outcome? Where should I look at (or
>>> listen to)?
>>> > >>
>>> > >
>>> > > You should see something like
>>> > >
>>> > >    vchiq0: <BCM2835 VCHIQ> mem 0x7e00b840-0x7e00b87b irq 54 on
>>> simplebus0
>>> > >    vchiq: local ver 8 (min 3), remote ver 8.
>>> > >    pcm0: <VCHIQ audio> on vchiq0
>>> > >
>>> > > in your dmesg output.
>>> > >
>>> > > The file /dev/vchiq should exist, as well as the following sysctl-s
>>> (I'm
>>> > > assuming no other audio devices are attached)
>>> > >
>>> > >    % sysctl dev.pcm
>>> > >    dev.pcm.0.trace: 0
>>> > >    ...
>>> > >    dev.pcm.0.dest: 0
>>> > >    ...
>>> > >    dev.pcm.0.%parent: vchiq0
>>> > >    ...
>>> > >    dev.pcm.0.%driver: pcm
>>> > >    dev.pcm.0.%desc: VCHIQ audio
>>> > >    …
>>> > >
>>> > > Then if you `cat < /dev/random > /dev/dsp` you should hear some
>>> static coming
>>> > > out of whatever is connected to hdmi (maybe headphones too? otherwise
>>> try
>>> > > setting `sysctl dev.pcm.0.dest=1`)
>>> > >
>>> > > Best,
>>> > > Marco
>>> >
>>> >
>>> > Hi,
>>> >
>>> > Booted the patched 14-CURRENT on the RPI3B+.
>>> >
>>> > dmesg diff:
>>> > +vchiq0: <BCM2835 VCHIQ> mem 0x7e00b840-0x7e00b87b irq 54 on simplebus0
>>> > +vchiq: local ver 8 (min 3), remote ver 8.
>>> > +pcm0: <VCHIQ audio> on vchiq0
>>> >
>>> > [root@rpi3 ~]# cat /dev/sndstat
>>> > Installed devices:
>>> > pcm0: <VCHIQ audio> (play) default
>>> > No devices installed from userspace.
>>> >
>>> > [root@rpi3 ~]# sysctl dev.pcm
>>> > dev.pcm.0.trace: 0
>>> > dev.pcm.0.starved: 0
>>> > dev.pcm.0.freebuffer: 40000
>>> > dev.pcm.0.underruns: 0
>>> > dev.pcm.0.retrieved: 0
>>> > dev.pcm.0.submitted: 0
>>> > dev.pcm.0.callbacks: 0
>>> > dev.pcm.0.dest: 0
>>> > dev.pcm.0.mode: 3
>>> > dev.pcm.0.bitperfect: 0
>>> > dev.pcm.0.buffersize: 0
>>> > dev.pcm.0.play.vchanformat: s16le:2.0
>>> > dev.pcm.0.play.vchanrate: 48000
>>> > dev.pcm.0.play.vchanmode: fixed
>>> > dev.pcm.0.play.vchans: 1
>>> > dev.pcm.0.%parent: vchiq0
>>> > dev.pcm.0.%pnpinfo:
>>> > dev.pcm.0.%location:
>>> > dev.pcm.0.%driver: pcm
>>> > dev.pcm.0.%desc: VCHIQ audio
>>> > dev.pcm.%parent:
>>> >
>>> >
>>> > To play some audio I need to search some headphones first. :-)
>>> >
>>> > Ronald.
>>> >
>>> >
>>> >
>>> > Good morning,
>>> >
>>> > Found headphones with a cable on the attic. Plugged it into the audio
>>> jack and played an mp3. Amazing!
>>> >
>>> > Regards,
>>> > Ronald.
>>> >
>>>
>>>
>>>
>>
>>
>>
>>
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.