1 // Copyright 2016 The Fuchsia Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 #pragma once 5 6 #include "device.h" 7 #include "ring.h" 8 9 #include <ddk/device.h> 10 #include <fbl/array.h> 11 #include <fbl/intrusive_double_list.h> 12 #include <zircon/thread_annotations.h> 13 14 namespace virtio { 15 16 // Describes a chunk of memory used for data transfers between the device and the driver, 17 // points to the memory inside TransferBuffer below 18 struct TransferDescriptor : fbl::DoublyLinkedListable<TransferDescriptor*> { 19 uint8_t* virt; 20 uintptr_t phys; 21 uint32_t total_len; 22 uint32_t used_len; 23 uint32_t processed_len; 24 }; 25 26 // Manages memory we use for transfers, TransferDescriptor points to the memory inside the class 27 class TransferBuffer { 28 public: 29 TransferBuffer(); 30 ~TransferBuffer(); 31 32 zx_status_t Init(const zx::bti& bti, size_t count, uint32_t chunk_size); 33 34 TransferDescriptor* GetDescriptor(size_t index); 35 TransferDescriptor* PhysicalToDescriptor(uintptr_t phys); 36 37 private: 38 size_t count_ = 0; 39 size_t size_ = 0; 40 uint32_t chunk_size_ = 0; 41 42 io_buffer_t buf_; 43 fbl::Array<TransferDescriptor> descriptor_; 44 }; 45 46 // Just a list of descriptors 47 class TransferQueue { 48 public: 49 void Add(TransferDescriptor* desc); 50 TransferDescriptor* Peek(); 51 TransferDescriptor* Dequeue(); 52 bool IsEmpty() const; 53 54 private: 55 fbl::DoublyLinkedList<TransferDescriptor*> queue_; 56 }; 57 58 // Actual virtio console implementation 59 class ConsoleDevice : public Device { 60 public: 61 explicit ConsoleDevice(zx_device_t* device, zx::bti bti, fbl::unique_ptr<Backend> backend); 62 virtual ~ConsoleDevice(); 63 64 virtual zx_status_t Init() override; 65 66 virtual void IrqRingUpdate() override; IrqConfigChange()67 virtual void IrqConfigChange() override {}; // No need to handle configuration changes tag()68 const char* tag() const override { return "virtio-console"; }; 69 70 private: 71 // For two queues it sums up to 32KiB, we probably don't need that much 72 constexpr static size_t kDescriptors = 32; 73 constexpr static uint32_t kChunkSize = 512; 74 75 static zx_status_t virtio_console_read(void* ctx, void* buf, size_t len, zx_off_t off, size_t* actual); 76 static zx_status_t virtio_console_write(void* ctx, const void* buf, size_t len, zx_off_t off, size_t* actual); 77 78 zx_status_t Read(void* buf, size_t len, zx_off_t off, size_t* actual); 79 zx_status_t Write(const void* buf, size_t len, zx_off_t off, size_t* actual); 80 81 fbl::Mutex request_lock_; 82 83 TransferBuffer port0_receive_buffer_ TA_GUARDED(request_lock_); 84 TransferQueue port0_receive_descriptors_ TA_GUARDED(request_lock_); 85 Ring port0_receive_queue_ TA_GUARDED(request_lock_) = {this}; 86 87 TransferBuffer port0_transmit_buffer_ TA_GUARDED(request_lock_); 88 TransferQueue port0_transmit_descriptors_ TA_GUARDED(request_lock_); 89 Ring port0_transmit_queue_ TA_GUARDED(request_lock_) = {this}; 90 }; 91 92 } // namespace virtio 93