blob: 3056de6dee86fe4355d01d58aae17b29c5a23bde [file] [log] [blame]
// Copyright 2019 The Fuchsia Authors
//
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file or at
// https://opensource.org/licenses/MIT
#include "common.h"
#include "device.h"
#include <lib/zx/channel.h>
#include <string.h>
// TODO(ZX-3927): Stop depending on the types in this file.
#include <zircon/syscalls/pci.h>
#define RPC_ENTRY \
pci_tracef("[%s] %s: entry\n", cfg_->addr(), __func__)
#define RPC_UNIMPLEMENTED \
RPC_ENTRY; \
return RpcReply(ch, ZX_ERR_NOT_SUPPORTED)
namespace pci {
zx_status_t Device::DdkRxrpc(zx_handle_t channel) {
if (channel == ZX_HANDLE_INVALID) {
// A new connection has been made, there's nothing else to do.
return ZX_OK;
}
// Clear the buffers. We only servce new requests after we've finished
// previous messages, so we won't overwrite data here.
memset(&request_, 0, sizeof(request_));
memset(&response_, 0, sizeof(response_));
uint32_t bytes_in;
uint32_t handles_in;
zx_handle_t handle;
zx::unowned_channel ch(channel);
zx_status_t st = ch->read(0, &request_, &handle, sizeof(request_), 1, &bytes_in, &handles_in);
if (st != ZX_OK) {
return ZX_ERR_INTERNAL;
}
if (bytes_in != sizeof(request_)) {
return ZX_ERR_INTERNAL;
}
switch (request_.op) {
case PCI_OP_CONFIG_READ:
return RpcConfigRead(ch);
break;
case PCI_OP_CONFIG_WRITE:
return RpcConfigWrite(ch);
break;
case PCI_OP_CONNECT_SYSMEM:
return RpcConfigWrite(ch);
break;
case PCI_OP_ENABLE_BUS_MASTER:
return RpcEnableBusMaster(ch);
break;
case PCI_OP_GET_AUXDATA:
return RpcGetAuxdata(ch);
break;
case PCI_OP_GET_BAR:
return RpcGetBar(ch);
break;
case PCI_OP_GET_BTI:
return RpcGetBti(ch);
break;
case PCI_OP_GET_DEVICE_INFO:
return RpcGetDeviceInfo(ch);
break;
case PCI_OP_GET_NEXT_CAPABILITY:
return RpcGetNextCapability(ch);
break;
case PCI_OP_MAP_INTERRUPT:
return RpcMapInterrupt(ch);
break;
case PCI_OP_QUERY_IRQ_MODE:
return RpcQueryIrqMode(ch);
break;
case PCI_OP_RESET_DEVICE:
return RpcResetDevice(ch);
break;
case PCI_OP_SET_IRQ_MODE:
return RpcSetIrqMode(ch);
break;
case PCI_OP_MAX:
case PCI_OP_INVALID: {
return RpcReply(ch, ZX_ERR_INVALID_ARGS);
}
};
return ZX_OK;
}
// Utility method to handle setting up the payload to return to the proxy and common
// error situations.
zx_status_t Device::RpcReply(const zx::unowned_channel& ch, zx_status_t st,
zx_handle_t* handles, const uint32_t handle_cnt) {
response_.op = request_.op;
response_.txid = request_.txid;
response_.ret = st;
return ch->write(0, &response_, sizeof(response_), handles, handle_cnt);
}
zx_status_t Device::RpcConfigRead(const zx::unowned_channel& ch) {
RPC_UNIMPLEMENTED;
}
zx_status_t Device::RpcConfigWrite(const zx::unowned_channel& ch) {
RPC_UNIMPLEMENTED;
}
zx_status_t Device::RpcEnableBusMaster(const zx::unowned_channel& ch) {
RPC_UNIMPLEMENTED;
}
zx_status_t Device::RpcGetAuxdata(const zx::unowned_channel& ch) {
RPC_UNIMPLEMENTED;
}
zx_status_t Device::RpcGetBar(const zx::unowned_channel& ch) {
RPC_UNIMPLEMENTED;
}
zx_status_t Device::RpcGetBti(const zx::unowned_channel& ch) {
RPC_UNIMPLEMENTED;
}
zx_status_t Device::RpcGetDeviceInfo(const zx::unowned_channel& ch) {
RPC_UNIMPLEMENTED;
}
zx_status_t Device::RpcGetNextCapability(const zx::unowned_channel& ch) {
RPC_UNIMPLEMENTED;
}
zx_status_t Device::RpcMapInterrupt(const zx::unowned_channel& ch) {
RPC_UNIMPLEMENTED;
}
zx_status_t Device::RpcQueryIrqMode(const zx::unowned_channel& ch) {
RPC_UNIMPLEMENTED;
}
zx_status_t Device::RpcResetDevice(const zx::unowned_channel& ch) {
RPC_UNIMPLEMENTED;
}
zx_status_t Device::RpcSetIrqMode(const zx::unowned_channel& ch) {
RPC_UNIMPLEMENTED;
}
} // namespace pci