14ed4da16SPaolo Bonzini // Copyright 2024 Red Hat, Inc. 24ed4da16SPaolo Bonzini // Author(s): Paolo Bonzini <pbonzini@redhat.com> 34ed4da16SPaolo Bonzini // SPDX-License-Identifier: GPL-2.0-or-later 44ed4da16SPaolo Bonzini 5*7630ca2aSPaolo Bonzini use std::{ffi::CStr, ptr::addr_of_mut}; 64ed4da16SPaolo Bonzini 74ed4da16SPaolo Bonzini pub use bindings::{SysBusDevice, SysBusDeviceClass}; 84ed4da16SPaolo Bonzini 96dd818fbSPaolo Bonzini use crate::{ 10f50cd85cSPaolo Bonzini bindings, 11f50cd85cSPaolo Bonzini cell::bql_locked, 12*7630ca2aSPaolo Bonzini irq::{IRQState, InterruptSource}, 13590faa03SPaolo Bonzini memory::MemoryRegion, 14f50cd85cSPaolo Bonzini prelude::*, 15f50cd85cSPaolo Bonzini qdev::{DeviceClass, DeviceState}, 16*7630ca2aSPaolo Bonzini qom::{ClassInitImpl, Owned}, 176dd818fbSPaolo Bonzini }; 187bd8e3efSPaolo Bonzini 197bd8e3efSPaolo Bonzini unsafe impl ObjectType for SysBusDevice { 207bd8e3efSPaolo Bonzini type Class = SysBusDeviceClass; 217bd8e3efSPaolo Bonzini const TYPE_NAME: &'static CStr = 227bd8e3efSPaolo Bonzini unsafe { CStr::from_bytes_with_nul_unchecked(bindings::TYPE_SYS_BUS_DEVICE) }; 237bd8e3efSPaolo Bonzini } 24f50cd85cSPaolo Bonzini qom_isa!(SysBusDevice: DeviceState, Object); 254ed4da16SPaolo Bonzini 266dd818fbSPaolo Bonzini // TODO: add SysBusDeviceImpl 276dd818fbSPaolo Bonzini impl<T> ClassInitImpl<SysBusDeviceClass> for T 286dd818fbSPaolo Bonzini where 296dd818fbSPaolo Bonzini T: ClassInitImpl<DeviceClass>, 306dd818fbSPaolo Bonzini { 316dd818fbSPaolo Bonzini fn class_init(sdc: &mut SysBusDeviceClass) { 326dd818fbSPaolo Bonzini <T as ClassInitImpl<DeviceClass>>::class_init(&mut sdc.parent_class); 336dd818fbSPaolo Bonzini } 346dd818fbSPaolo Bonzini } 356dd818fbSPaolo Bonzini 36559a779cSPaolo Bonzini /// Trait for methods of [`SysBusDevice`] and its subclasses. 37559a779cSPaolo Bonzini pub trait SysBusDeviceMethods: ObjectDeref 38559a779cSPaolo Bonzini where 39559a779cSPaolo Bonzini Self::Target: IsA<SysBusDevice>, 40559a779cSPaolo Bonzini { 41af68b41dSPaolo Bonzini /// Expose a memory region to the board so that it can give it an address 42af68b41dSPaolo Bonzini /// in guest memory. Note that the ordering of calls to `init_mmio` is 43af68b41dSPaolo Bonzini /// important, since whoever creates the sysbus device will refer to the 44af68b41dSPaolo Bonzini /// region with a number that corresponds to the order of calls to 45af68b41dSPaolo Bonzini /// `init_mmio`. 46590faa03SPaolo Bonzini fn init_mmio(&self, iomem: &MemoryRegion) { 47af68b41dSPaolo Bonzini assert!(bql_locked()); 48af68b41dSPaolo Bonzini unsafe { 49590faa03SPaolo Bonzini bindings::sysbus_init_mmio(self.as_mut_ptr(), iomem.as_mut_ptr()); 50af68b41dSPaolo Bonzini } 51af68b41dSPaolo Bonzini } 52af68b41dSPaolo Bonzini 534ed4da16SPaolo Bonzini /// Expose an interrupt source outside the device as a qdev GPIO output. 544ed4da16SPaolo Bonzini /// Note that the ordering of calls to `init_irq` is important, since 554ed4da16SPaolo Bonzini /// whoever creates the sysbus device will refer to the interrupts with 564ed4da16SPaolo Bonzini /// a number that corresponds to the order of calls to `init_irq`. 57559a779cSPaolo Bonzini fn init_irq(&self, irq: &InterruptSource) { 584ed4da16SPaolo Bonzini assert!(bql_locked()); 594ed4da16SPaolo Bonzini unsafe { 604ed4da16SPaolo Bonzini bindings::sysbus_init_irq(self.as_mut_ptr(), irq.as_ptr()); 614ed4da16SPaolo Bonzini } 624ed4da16SPaolo Bonzini } 63*7630ca2aSPaolo Bonzini 64*7630ca2aSPaolo Bonzini // TODO: do we want a type like GuestAddress here? 65*7630ca2aSPaolo Bonzini fn mmio_map(&self, id: u32, addr: u64) { 66*7630ca2aSPaolo Bonzini assert!(bql_locked()); 67*7630ca2aSPaolo Bonzini let id: i32 = id.try_into().unwrap(); 68*7630ca2aSPaolo Bonzini unsafe { 69*7630ca2aSPaolo Bonzini bindings::sysbus_mmio_map(self.as_mut_ptr(), id, addr); 70*7630ca2aSPaolo Bonzini } 71*7630ca2aSPaolo Bonzini } 72*7630ca2aSPaolo Bonzini 73*7630ca2aSPaolo Bonzini // Owned<> is used here because sysbus_connect_irq (via 74*7630ca2aSPaolo Bonzini // object_property_set_link) adds a reference to the IRQState, 75*7630ca2aSPaolo Bonzini // which can prolong its life 76*7630ca2aSPaolo Bonzini fn connect_irq(&self, id: u32, irq: &Owned<IRQState>) { 77*7630ca2aSPaolo Bonzini assert!(bql_locked()); 78*7630ca2aSPaolo Bonzini let id: i32 = id.try_into().unwrap(); 79*7630ca2aSPaolo Bonzini unsafe { 80*7630ca2aSPaolo Bonzini bindings::sysbus_connect_irq(self.as_mut_ptr(), id, irq.as_mut_ptr()); 81*7630ca2aSPaolo Bonzini } 82*7630ca2aSPaolo Bonzini } 83*7630ca2aSPaolo Bonzini 84*7630ca2aSPaolo Bonzini fn sysbus_realize(&self) { 85*7630ca2aSPaolo Bonzini // TODO: return an Error 86*7630ca2aSPaolo Bonzini assert!(bql_locked()); 87*7630ca2aSPaolo Bonzini unsafe { 88*7630ca2aSPaolo Bonzini bindings::sysbus_realize(self.as_mut_ptr(), addr_of_mut!(bindings::error_fatal)); 89*7630ca2aSPaolo Bonzini } 90*7630ca2aSPaolo Bonzini } 914ed4da16SPaolo Bonzini } 92559a779cSPaolo Bonzini 93559a779cSPaolo Bonzini impl<R: ObjectDeref> SysBusDeviceMethods for R where R::Target: IsA<SysBusDevice> {} 94