blob: 5baedee912f6a73d6ce6f7c098f57bf003cd3e7f [file] [log] [blame]
// Copyright 2016 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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ddk/binding.h>
#include <ddk/device.h>
#include <ddk/driver.h>
#include <ddk/protocol/pci.h>
#include <fbl/alloc_checker.h>
#include <fbl/unique_ptr.h>
#include <magenta/compiler.h>
#include <magenta/types.h>
#include "block.h"
#include "device.h"
#include "rng.h"
#include "ethernet.h"
#include "gpu.h"
#include "trace.h"
#define LOCAL_TRACE 0
// implement driver object:
extern "C" mx_status_t virtio_bind(void* ctx, mx_device_t* device, void** cookie) {
LTRACEF("device %p\n", device);
mx_status_t status;
pci_protocol_t pci;
/* grab the pci device and configuration */
if (device_get_protocol(device, MX_PROTOCOL_PCI, &pci)) {
TRACEF("no pci protocol\n");
return -1;
}
const pci_config_t* config;
size_t config_size;
mx_handle_t config_handle = MX_HANDLE_INVALID;
status = pci_map_resource(&pci, PCI_RESOURCE_CONFIG, MX_CACHE_POLICY_UNCACHED_DEVICE,
(void**)&config, &config_size, &config_handle);
if (status != MX_OK) {
TRACEF("failed to grab config handle\n");
return status;
}
LTRACEF("pci %p\n", &pci);
LTRACEF("0x%x:0x%x\n", config->vendor_id, config->device_id);
// TODO: Make symbols for these constants and reuse in the BIND protocol.
fbl::unique_ptr<virtio::Device> vd = nullptr;
switch (config->device_id) {
case 0x1000:
LTRACEF("found net device\n");
vd.reset(new virtio::EthernetDevice(device));
break;
case 0x1001:
case 0x1042:
LTRACEF("found block device\n");
vd.reset(new virtio::BlockDevice(device));
break;
case 0x1050:
LTRACEF("found gpu device\n");
vd.reset(new virtio::GpuDevice(device));
break;
case 0x1005:
case 0x1044:
LTRACEF("found entropy device\n");
vd.reset(new virtio::RngDevice(device));
break;
default:
printf("unhandled device id, how did this happen?\n");
return -1;
}
LTRACEF("calling Bind on driver\n");
status = vd->Bind(&pci, config_handle, config);
if (status != MX_OK)
return status;
status = vd->Init();
if (status != MX_OK)
return status;
// if we're here, we're successful so drop the unique ptr ref to the object and let it live on
vd.release();
LTRACE_EXIT;
return MX_OK;
}