func (pcidevice *PciDevice) Attach(vm *platform.Vm, model *Model) error { // Find our pcibus. var ok bool var pcibus *PciBus for _, device := range model.devices { pcibus, ok = device.(*PciBus) if pcibus != nil && ok { break } } if pcibus == nil { return PciBusNotFound } // Rebuild our capabilities. pcidevice.RebuildCapabilities() // FIXME: Everything uses interrupt 1. // This is gross, but we hard-coded the line to 1 // unless you're using MSI. This really should be // fixed (if we actually plan on using PCI devices). pcidevice.Config.Set8(PciConfigOffsetInterruptLine, 1) pcidevice.Config.Set8(PciConfigOffsetInterruptPin, 1) pcidevice.std_interrupt = func() error { vm.Interrupt(platform.Irq(1), true) vm.Interrupt(platform.Irq(1), false) return nil } // Attach to the PciBus. return pcibus.AddDevice(pcidevice) }
func (mmio *MmioDevice) Attach(vm *platform.Vm, model *Model) error { // Build our IO Handlers. mmio.IoHandlers = make(IoHandlers) for region, ops := range mmio.IoMap { new_region := MemoryRegion{region.Start + mmio.Offset, region.Size} mmio.IoHandlers[new_region] = NewIoHandler(mmio, new_region.Start, ops) } // Reserve memory regions. if mmio.reservations != nil { for _, region := range mmio.reservations { err := model.Reserve( vm, mmio, MemoryTypeReserved, region.Start+mmio.Offset, region.Size, nil) if err != nil { return err } } } if mmio.InterruptNumber != 0 { // Reserve our interrupt. _, ok := model.InterruptMap[mmio.InterruptNumber] if ok { // Already a device there. return InterruptConflict } model.InterruptMap[mmio.InterruptNumber] = mmio } else { // Find an interrupt. for irq := platform.Irq(16); ; irq += 1 { if _, ok := model.InterruptMap[irq]; !ok { model.InterruptMap[irq] = mmio mmio.InterruptNumber = irq } } } return mmio.BaseDevice.Attach(vm, model) }