github.com/f-secure-foundry/tamago@v0.0.0-20220307101044-d73fcdd7f11b/soc/bcm2835/videocore.go (about)

     1  // BCM2835 SoC VideoCore support
     2  // https://github.com/f-secure-foundry/tamago
     3  //
     4  // Copyright (c) the bcm2835 package authors
     5  //
     6  // Use of this source code is governed by the license
     7  // that can be found in the LICENSE file.
     8  
     9  package bcm2835
    10  
    11  import "encoding/binary"
    12  
    13  const (
    14  	GPU_MEMORY_FLAG_DISCARDABLE      = 1 << 0
    15  	GPU_MEMORY_FLAG_NORMAL           = 0 << 2
    16  	GPU_MEMORY_FLAG_DIRECT           = 1 << 2
    17  	GPU_MEMORY_FLAG_COHERENT         = 2 << 2
    18  	GPU_MEMORY_FLAG_L1_NONALLOCATING = 3 << 2
    19  	GPU_MEMORY_FLAG_ZERO             = 1 << 4
    20  	GPU_MEMORY_FLAG_NO_INIT          = 1 << 5
    21  	GPU_MEMORY_FLAG_HINT_PERMALOCK   = 1 << 6
    22  )
    23  
    24  // FirmwareRevision gets the firmware rev of the VideoCore GPU
    25  func FirmwareRevision() uint32 {
    26  	buf := exchangeSingleTagMessage(VC_BOARD_GET_REV, make([]byte, VC_BOARD_GET_REV_LEN))
    27  
    28  	if len(buf) < 4 {
    29  		return 0
    30  	}
    31  
    32  	return binary.LittleEndian.Uint32(buf)
    33  }
    34  
    35  // BoardModel gets the board model
    36  func BoardModel() uint32 {
    37  	buf := exchangeSingleTagMessage(VC_BOARD_GET_MODEL, make([]byte, VC_BOARD_GET_MODEL_LEN))
    38  
    39  	if len(buf) < 4 {
    40  		return 0
    41  	}
    42  
    43  	return binary.LittleEndian.Uint32(buf)
    44  }
    45  
    46  // MACAddress gets the board's MAC address
    47  func MACAddress() []byte {
    48  	return exchangeSingleTagMessage(VC_BOARD_GET_MAC, make([]byte, VC_BOARD_GET_MAC_LEN))
    49  }
    50  
    51  // Serial gets the board's serial number
    52  func Serial() uint32 {
    53  	buf := exchangeSingleTagMessage(VC_BOARD_GET_SERIAL, make([]byte, VC_BOARD_GET_SERIAL_LEN))
    54  
    55  	if len(buf) < 4 {
    56  		return 0
    57  	}
    58  
    59  	return binary.LittleEndian.Uint32(buf)
    60  }
    61  
    62  // CPUMemory gets the memory ranges allocated to the ARM core(s)
    63  func CPUMemory() (start uint32, size uint32) {
    64  	buf := exchangeSingleTagMessage(VC_BOARD_GET_ARM_MEMORY, make([]byte, VC_BOARD_GET_ARM_MEMORY_LEN))
    65  
    66  	if len(buf) < 8 {
    67  		return 0, 0
    68  	}
    69  
    70  	return binary.LittleEndian.Uint32(buf[0:]), binary.LittleEndian.Uint32(buf[4:])
    71  }
    72  
    73  // GPUMemory gets the memory ranges allocated to VideoCore
    74  func GPUMemory() (start uint32, size uint32) {
    75  	buf := exchangeSingleTagMessage(VC_BOARD_GET_VC_MEMORY, make([]byte, VC_BOARD_GET_VC_MEMORY_LEN))
    76  
    77  	if len(buf) < 8 {
    78  		return 0, 0
    79  	}
    80  
    81  	return binary.LittleEndian.Uint32(buf[0:]), binary.LittleEndian.Uint32(buf[4:])
    82  }
    83  
    84  // CPUAvailableDMAChannels gets the DMA channels available to the ARM core(s)
    85  func CPUAvailableDMAChannels() (bitmask uint32) {
    86  	buf := exchangeSingleTagMessage(VC_RES_GET_DMACHANNELS, make([]byte, VC_RES_GET_DMACHANNELS_LEN))
    87  
    88  	if len(buf) < 4 {
    89  		return 0
    90  	}
    91  
    92  	return binary.LittleEndian.Uint32(buf)
    93  }
    94  
    95  // AllocateGPUMemory allocates space from the GPU address space
    96  //
    97  // The returned value is a handle, use LockMemory to convert
    98  // to an address.
    99  func AllocateGPUMemory(size uint32, alignment uint32, flags uint32) (handle uint32) {
   100  	buf := make([]byte, VC_MEM_ALLOCATE_LEN)
   101  	binary.LittleEndian.PutUint32(buf[0:], size)
   102  	binary.LittleEndian.PutUint32(buf[4:], alignment)
   103  	binary.LittleEndian.PutUint32(buf[8:], uint32(flags))
   104  
   105  	buf = exchangeSingleTagMessage(VC_MEM_ALLOCATE, buf)
   106  
   107  	if len(buf) < 4 {
   108  		return 0
   109  	}
   110  
   111  	return binary.LittleEndian.Uint32(buf)
   112  }
   113  
   114  // LockGPUMemory provides the address of previously allocated memory
   115  func LockGPUMemory(handle uint32) (addr uint32) {
   116  	buf := make([]byte, VC_MEM_LOCK_LEN)
   117  	binary.LittleEndian.PutUint32(buf[0:], handle)
   118  
   119  	buf = exchangeSingleTagMessage(VC_MEM_LOCK, buf)
   120  
   121  	if len(buf) < 4 {
   122  		return 0
   123  	}
   124  
   125  	return binary.LittleEndian.Uint32(buf)
   126  }
   127  
   128  func exchangeSingleTagMessage(code uint32, buf []byte) []byte {
   129  	msg := &MailboxMessage{
   130  		Tags: []MailboxTag{
   131  			{
   132  				ID:     code,
   133  				Buffer: buf,
   134  			},
   135  		},
   136  	}
   137  
   138  	Mailbox.Call(VC_CH_PROPERTYTAGS_A_TO_VC, msg)
   139  
   140  	tag := msg.Tag(code)
   141  
   142  	if tag == nil {
   143  		return nil
   144  	}
   145  
   146  	return tag.Buffer
   147  }