Allow allocating contiguous memory

This is used for page tables, the trampoline, and some other random
allocations.

Change-Id: I3528f83675e096fbb09045e91d8529e5ce0fe2ca
diff --git a/fuchsia/msd_img_device.cc b/fuchsia/msd_img_device.cc
index e47c0c1..2cf401e 100644
--- a/fuchsia/msd_img_device.cc
+++ b/fuchsia/msd_img_device.cc
@@ -43,8 +43,8 @@
 bool
 MsdImgDevice::Init()
 {
-	bti_ = platform_device_->GetBusTransactionInitiator();
-	if (!bti_)
+	bus_mapper_ = magma::PlatformBusMapper::Create(platform_device_->GetBusTransactionInitiator());
+	if (!bus_mapper_)
 	{
 		return DRETF(false, "Failed to create bus transaction initiator");
 	}
diff --git a/fuchsia/msd_img_device.h b/fuchsia/msd_img_device.h
index 2d0a8aa..f008b6b 100644
--- a/fuchsia/msd_img_device.h
+++ b/fuchsia/msd_img_device.h
@@ -9,6 +9,7 @@
 
 #include "magma_util/macros.h"
 #include "msd.h"
+#include "platform_bus_mapper.h"
 #include "platform_device.h"
 
 typedef struct _PVRSRV_DEVICE_NODE_ PVRSRV_DEVICE_NODE;
@@ -42,7 +43,7 @@
 	}
 
 	magma::PlatformDevice* platform_device() { return platform_device_.get(); }
-	magma::PlatformHandle* bti() { return bti_.get(); }
+	magma::PlatformBusMapper* bus_mapper() { return bus_mapper_.get(); }
 
 	magma::PlatformMmio* mmio() { return mmio_.get(); }
 
@@ -60,7 +61,7 @@
 	static const uint32_t kMagic = 'idev';
 
 	std::unique_ptr<magma::PlatformDevice> platform_device_;
-	std::unique_ptr<magma::PlatformHandle> bti_;
+	std::unique_ptr<magma::PlatformBusMapper> bus_mapper_;
 	std::unique_ptr<magma::PlatformMmio> mmio_;
 	PVRSRV_DEVICE_NODE* device_node_ = nullptr;
 
diff --git a/services/server/env/fuchsia/osfunc.cc b/services/server/env/fuchsia/osfunc.cc
index 0c714fe..c901f7e 100644
--- a/services/server/env/fuchsia/osfunc.cc
+++ b/services/server/env/fuchsia/osfunc.cc
@@ -30,12 +30,14 @@
 
 #include <shared_mutex>
 #include <thread>
+#include <vector>
 
 #include <lib/zx/event.h>
 #include <zircon/syscalls.h>
 
 #include "fuchsia/msd_img_device.h"
 #include "magma_util/macros.h"
+#include "platform_bus_mapper.h"
 
 extern "C" {
 #include "log2.h"
@@ -83,6 +85,21 @@
 	}
 };
 
+struct PageWrapper
+{
+	static constexpr uint32_t kMagic = 'hPGS';
+	uint32_t magic = kMagic;
+	std::unique_ptr<magma::PlatformBuffer> buffer;
+	std::unique_ptr<magma::PlatformBusMapper::BusMapping> mapping;
+
+	static PageWrapper *FromHandle(PG_HANDLE *psMemHandle)
+	{
+		auto object = reinterpret_cast<PageWrapper *>(psMemHandle->u.pvHandle);
+		DASSERT(object->magic == kMagic);
+		return object;
+	}
+};
+
 
 } // namespace msd_img
 
@@ -117,13 +134,28 @@
 PVRSRV_ERROR
 OSPhyContigPagesAlloc(PVRSRV_DEVICE_NODE *psDevNode, size_t uiSize, PG_HANDLE *psMemHandle, IMG_DEV_PHYADDR *psDevPAddr)
 {
-	NOT_IMPLEMENTED();
-	return PVRSRV_ERROR_NOT_SUPPORTED;
+	MsdImgDevice *device = MsdImgDevice::cast(psDevNode->psDevConfig->pvOSDevice);
+	auto page_struct = std::make_unique<msd_img::PageWrapper>();
+	page_struct->buffer = device->bus_mapper()->CreateContiguousBuffer(uiSize, magma::page_shift(), "IMG contig");
+	if (!page_struct->buffer)
+	{
+		return DRET(PVRSRV_ERROR_OUT_OF_MEMORY);
+	}
+	page_struct->mapping = device->bus_mapper()->MapPageRangeBus(page_struct->buffer.get(), 0,
+								     page_struct->buffer->size() / magma::page_size());
+	if (!page_struct->mapping)
+	{
+		return DRET(PVRSRV_ERROR_OUT_OF_MEMORY);
+	}
+	psDevPAddr->uiAddr = page_struct->mapping->Get()[0];
+	psMemHandle->u.pvHandle = page_struct.release();
+	return PVRSRV_OK;
 }
 void
 OSPhyContigPagesFree(PVRSRV_DEVICE_NODE *psDevNode, PG_HANDLE *psMemHandle)
 {
-	NOT_IMPLEMENTED();
+	auto page_struct = msd_img::PageWrapper::FromHandle(psMemHandle);
+	delete page_struct;
 }
 
 PVRSRV_ERROR
@@ -133,19 +165,31 @@
 		    IMG_DEV_PHYADDR *psDevPAddr,
 		    void **pvPtr)
 {
-	NOT_IMPLEMENTED();
-	return PVRSRV_ERROR_NOT_SUPPORTED;
+	auto page_struct = msd_img::PageWrapper::FromHandle(psMemHandle);
+
+	if (!page_struct->buffer->MapCpu(pvPtr, 0))
+	{
+		return DRET(PVRSRV_ERROR_OUT_OF_MEMORY);
+	}
+	return PVRSRV_OK;
 }
+
 void
 OSPhyContigPagesUnmap(PVRSRV_DEVICE_NODE *psDevNode, PG_HANDLE *psMemHandle, void *pvPtr)
 {
-	NOT_IMPLEMENTED();
+	auto page_struct = msd_img::PageWrapper::FromHandle(psMemHandle);
+	page_struct->buffer->UnmapCpu();
 }
+
 PVRSRV_ERROR
 OSPhyContigPagesClean(PVRSRV_DEVICE_NODE *psDevNode, PG_HANDLE *psMemHandle, IMG_UINT32 uiOffset, IMG_UINT32 uiLength)
 {
-	NOT_IMPLEMENTED();
-	return PVRSRV_ERROR_NOT_SUPPORTED;
+	auto page_struct = msd_img::PageWrapper::FromHandle(psMemHandle);
+	if (!page_struct->buffer->CleanCache(uiOffset, uiLength, false))
+	{
+		return DRET(PVRSRV_ERROR_INVALID_PARAMS);
+	}
+	return PVRSRV_OK;
 }
 
 IMG_UINT32