gitee.com/leisunstar/runtime@v0.0.0-20200521203717-5cef3e7b53f9/virtcontainers/types/bridges.go (about) 1 // Copyright (c) 2017 Intel Corporation 2 // 3 // SPDX-License-Identifier: Apache-2.0 4 // 5 6 package types 7 8 import "fmt" 9 10 // Type represents a type of bus and bridge. 11 type Type string 12 13 const PCIBridgeMaxCapacity = 30 14 15 const ( 16 // PCI represents a PCI bus and bridge 17 PCI Type = "pci" 18 19 // PCIE represents a PCIe bus and bridge 20 PCIE Type = "pcie" 21 ) 22 23 const CCWBridgeMaxCapacity = 0xffff 24 25 const ( 26 CCW Type = "ccw" 27 ) 28 29 type Bridge struct { 30 // Devices contains information about devices plugged and its address in the bridge 31 Devices map[uint32]string 32 33 // ID is used to identify the bridge in the hypervisor 34 ID string 35 36 // Addr is the slot of the bridge 37 Addr int 38 39 // Type is the type of the bridge (pci, pcie, etc) 40 Type Type 41 42 // MaxCapacity is the max capacity of the bridge 43 MaxCapacity uint32 44 } 45 46 func NewBridge(bt Type, id string, devices map[uint32]string, addr int) Bridge { 47 var maxCapacity uint32 48 switch bt { 49 case PCI: 50 fallthrough 51 case PCIE: 52 maxCapacity = PCIBridgeMaxCapacity 53 case CCW: 54 maxCapacity = CCWBridgeMaxCapacity 55 default: 56 maxCapacity = 0 57 } 58 return Bridge{ 59 Devices: devices, 60 ID: id, 61 Addr: addr, 62 Type: bt, 63 MaxCapacity: maxCapacity, 64 } 65 } 66 67 func (b *Bridge) AddDevice(ID string) (uint32, error) { 68 var addr uint32 69 70 // looking for the first available address 71 for i := uint32(1); i <= b.MaxCapacity; i++ { 72 if _, ok := b.Devices[i]; !ok { 73 addr = i 74 break 75 } 76 } 77 78 if addr == 0 { 79 return 0, fmt.Errorf("Unable to hot plug device on bridge: there are no empty slots") 80 } 81 82 // save address and device 83 b.Devices[addr] = ID 84 return addr, nil 85 } 86 87 func (b *Bridge) RemoveDevice(ID string) error { 88 // check if the device was hot plugged in the bridge 89 for addr, devID := range b.Devices { 90 if devID == ID { 91 // free address to re-use the same slot with other devices 92 delete(b.Devices, addr) 93 return nil 94 } 95 } 96 97 return fmt.Errorf("Unable to hot unplug device %s: not present on bridge", ID) 98 } 99 100 // AddressFormatCCW returns the address format for the device number. The channel subsystem-ID 0xfe is reserved to the virtual channel and the address format is in the form fe.n.dddd, where n is subchannel set ID and ddd the device number. More details at https://www.ibm.com/support/knowledgecenter/en/linuxonibm/com.ibm.linux.z.ldva/ldva_t_configuringSCSIdevices.html 101 func (b *Bridge) AddressFormatCCW(addr string) (string, error) { 102 if b.Type != CCW { 103 return "", fmt.Errorf("Expected bridge type %T, got %T (%+v)", CCW, b.Type, b) 104 } 105 106 return fmt.Sprintf("fe.%x.%s", b.Addr, addr), nil 107 } 108 109 // AddressFormatCCWForVirtServer returns the address format for the virtual server. The address format is in the form of 0.n.dddd 110 func (b *Bridge) AddressFormatCCWForVirtServer(addr string) (string, error) { 111 if b.Type != CCW { 112 return "", fmt.Errorf("Wrong bridge type") 113 } 114 return fmt.Sprintf("0.%x.%s", b.Addr, addr), nil 115 }