blob: 9171fc28ffc8f50fc57a91e81be9962daf3cec94 [file] [log] [blame]
// Copyright 2021 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "third_party/iwlwifi/platform/module.h"
#include <lib/ddk/driver.h>
#include <stdarg.h>
#include <stdio.h>
#include <zircon/process.h>
#include <zircon/status.h>
#include <zircon/syscalls.h>
#include <zircon/types.h>
#include <string>
#include "third_party/iwlwifi/platform/device.h"
static const size_t kModuleNameMax = 256;
// Forward-declare the individual module entry points here. We will only link them below if they
// are enabled by configuration.
extern "C" {
zx_status_t iwl_mvm_init();
}
zx_status_t iwl_module_request(const char* name, ...) {
va_list ap;
va_start(ap, name);
char module_name[kModuleNameMax];
vsnprintf(module_name, sizeof(module_name), name, ap);
va_end(ap);
// Link in the module initializers that are enabled by configuration.
#if defined(CPTCFG_IWLMVM)
if (std::strcmp("iwlmvm", module_name) == 0) {
return iwl_mvm_init();
}
#endif // defined(CPTCFG_IWLMVM)
return ZX_ERR_NOT_SUPPORTED;
}
zx_status_t iwl_firmware_request(struct device* dev, const char* name, struct firmware* firmware) {
zx_status_t status = ZX_OK;
zx_handle_t vmo = ZX_HANDLE_INVALID;
size_t size = 0;
if ((status = load_firmware(dev->zxdev, name, &vmo, &size)) != ZX_OK) {
return status;
}
uintptr_t vaddr = 0;
if ((status = zx_vmar_map(zx_vmar_root_self(), ZX_VM_PERM_READ, 0, vmo, 0, size, &vaddr)) !=
ZX_OK) {
zx_handle_close(vmo);
return status;
}
firmware->vmo = vmo;
firmware->data = (uint8_t*)vaddr;
firmware->size = size;
return ZX_OK;
}
zx_status_t iwl_firmware_request_nowait(struct device* dev, const char* name,
void (*cont)(struct firmware* firmware, void* context),
void* context) {
// Fuchsia does support asynchronous firmware loading, but it makes for a rather complicated
// threading model when the reply to ddk::Bind (where firmware typically loading occurs) can also
// be threaded. To simplify things then we'll just do this synchronously, and rely on threading
// the entire ddk::Bind call if asynchronous loading is desired.
zx_status_t status = ZX_OK;
struct firmware fw = {};
if ((status = iwl_firmware_request(dev, name, &fw)) != ZX_OK) {
return status;
}
(*cont)(&fw, context);
return ZX_OK;
}
zx_status_t iwl_firmware_release(struct firmware* firmware) {
zx_status_t status = ZX_OK;
if (firmware->vmo != ZX_HANDLE_INVALID) {
if ((status = zx_vmar_unmap(zx_vmar_root_self(), (uintptr_t)firmware->data, firmware->size)) !=
ZX_OK) {
return status;
}
zx_handle_close(firmware->vmo);
firmware->vmo = ZX_HANDLE_INVALID;
firmware->data = NULL;
firmware->size = 0;
}
return ZX_OK;
}