blob: 319a41db868d008a44f84036dd045079aac1d913 [file] [log] [blame]
#!/usr/bin/env python3
#
# Copyright (c) 2019 Intel Corporation
#
# SPDX-License-Identifier: Apache-2.0
import logging
from ctypes import Structure, c_uint64, c_uint32, c_uint16, \
c_uint8, addressof, sizeof
import lib.platforms as plat_def
# Global Message - Generic
IPC_GLB_TYPE_OFFSET = 28
IPC_GLB_TYPE_MASK = (0xF << IPC_GLB_TYPE_OFFSET)
# Command Message
IPC_CMD_TYPE_OFFSET = 16
IPC_CMD_TYPE_MASK = (0xFFF << IPC_CMD_TYPE_OFFSET)
# Message Type
IPC_FW_READY = 0x07 << IPC_GLB_TYPE_OFFSET
# Extended data types that can be appended onto end of IpCFwReady message
IpcExtData = {
0: 'IPC_EXT_DMA_BUFFER',
1: 'IPC_EXT_WINDOW'
}
# Extended Firmware Data
IpcRegion = {
0: 'IPC_REGION_DOWNBOX',
1: 'IPC_REGION_UPBOX',
2: 'IPC_REGION_TRACE',
3: 'IPC_REGION_DEBUG',
4: 'IPC_REGION_STREAM',
5: 'IPC_REGION_REGS',
6: 'IPC_REGION_EXCEPTION'
}
class IpcHdr(Structure):
""" Data structure for IPC Header """
_pack_ = 1
_fields_ = [
("size", c_uint32)
]
def __str__(self):
output = ("Size: 0x%08X" % self.size)
return output
class IpcCmdHdr(Structure):
""" Data structure for IPC Command Header """
_pack_ = 1
_fields_ = [
("size", c_uint32),
("cmd", c_uint32)
]
def __str__(self):
output = (
"IPC Command Hdr:\n"
" Command: {cmd:>10} (0x{cmd:0>8X})\n"
" Size: {size:>10} (0x{size:0>4X})"
).format(
size = self.size,
cmd = self.cmd
)
return output
class IpcFwVersion(Structure):
""" Data structure for IPC FwVersion message """
_pack_ = 1
_fields_ = [
("hdr", IpcHdr),
("major", c_uint16),
("minor", c_uint16),
("micro", c_uint16),
("build", c_uint16),
("date", c_uint8 * 12),
("time", c_uint8 * 10),
("tag", c_uint8 * 6),
("abi_version", c_uint32),
("reserved", c_uint32 * 4)
]
def __str__(self):
output = (
"Firmware Version:\n"
" Major version: {major: >5} (0x{major:0>4X})\n"
" Minor version: {minor: >5} (0x{minor:0>4X})\n"
" Micro number: {micro: >5} (0x{micro:0>4X})\n"
" Build number: {build: >5} (0x{build:0>4X})\n"
" Date: {date: >24}\n"
" Time: {time: >24}\n"
" Tag: {tag: >24}\n"
" Abi version: {abi_version: >5} (0x{abi_version:0>4X})"
).format(
major = self.major,
minor = self.minor,
micro = self.micro,
build = self.build,
date=''.join([chr(i) for i in list(self.date)]),
time=''.join([chr(i) for i in list(self.time)]),
tag=''.join([chr(i) for i in list(self.tag)]),
abi_version = self.abi_version)
return output
class IpcFwReady(Structure):
""" Data structure for IpcFwReady message """
_pack_ = 1
_fields_ = [
("hdr", IpcCmdHdr),
("dspbox_offset", c_uint32),
("hostbox_offset", c_uint32),
("dspbox_size", c_uint32),
("hostbox_size", c_uint32),
("version", IpcFwVersion),
("flags", c_uint64),
("reserved", c_uint32 * 4)
]
def __str__(self):
output = (
"IPC Firmware Ready Message: (0x{cmd:0>8X}) (0x{size:0>8X})\n"
" DSP box offset: {dsp_offset: >5} (0x{dsp_offset:0>4X})\n"
" Host box offset:{host_offset: >5} (0x{host_offset:0>4X})\n"
" DSP box size: {dsp_size: >5} (0x{dsp_size:0>4X})\n"
" Host box size: {host_size: >5} (0x{host_size:0>4X})\n\n"
"{version}\n\n"
"Flags:"
" 0x{flags:0>8X}"
).format(
cmd = self.hdr.cmd,
size = self.hdr.size,
dsp_offset = self.dspbox_offset,
host_offset = self.hostbox_offset,
dsp_size = self.dspbox_size,
host_size = self.hostbox_size,
version = str(self.version),
flags = self.flags
)
return output
class IpcExtDataHdr(Structure):
""" Data structure for IPC extended data header """
_pack_ = 1
_fields_ = [
("hdr", IpcCmdHdr),
("type", c_uint32)
]
class IpcWindowElem(Structure):
""" Data structure for Window Element message """
_pack_ = 1
_fields_ = [
("hdr", IpcHdr),
("type", c_uint32),
("id", c_uint32),
("flags", c_uint32),
("size", c_uint32),
("offset", c_uint32)
]
def __str__(self):
output = (
"Window type: {type_str:>20} ({type:d})\n"
"Window id: {id: >5}\n"
"Window flags: {flags: >5} (0x{flags:0>4X})\n"
"Window size: {size: >5} (0x{size:0>4X})\n"
"Window offset: {offset: >5} (0x{offset:0>4X})\n"
).format(
type_str = IpcRegion[self.type],
type = self.type,
id = self.id,
flags = self.flags,
size = self.size,
offset = self.offset
)
return output
class IpcWindow(Structure):
""" Data structure for extended data memory windows """
_pack_ = 1
_fields_ = [
("ext_hdr", IpcExtDataHdr),
("num_windows", c_uint32),
]
def __str__(self):
output = ("\n"
"IPC Firmware Ready Extended Message: (0x{cmd:0>8X}) (0x{size:0>8X})\n"
"Message Type: {ext_type: >5d} ({ext_type_str})\n\n"
"Number of Windows: {num_windows: >2d}\n"
).format(
cmd = self.ext_hdr.hdr.cmd,
size = self.ext_hdr.hdr.size,
ext_type = self.ext_hdr.type,
ext_type_str = IpcExtData[self.ext_hdr.type],
num_windows = int(self.num_windows)
)
return output
class Ipc:
""" Class for IPC handle """
def __init__(self, dev):
self.drv = dev.drv
self.dsp_base_p = dev.dev_info.dsp_bar.base_p
# memory map MBOX UPLINK
self.mmap = self.drv.mmap(self.dsp_base_p + (plat_def.FW_MBOX_UPLINK),
plat_def.FW_MBOX_SIZE)
self.mmap_addr = addressof(self.mmap)
def read_fw_ready(self):
""" FwReady message consist of two messages:
1. FwReady
2. ExtendedData
"""
msg = IpcFwReady.from_address(self.mmap_addr)
logging.info(str(msg))
self.read_fw_ready_ext()
def read_fw_ready_ext(self):
addr_offset = self.mmap_addr + sizeof(IpcFwReady())
msg = IpcWindow.from_address(addr_offset)
logging.info(str(msg))
# Extended Windows data type
if msg.ext_hdr.type != 1:
raise RuntimeError("Not Implemented: ext_hdr.type != 1")
win_elem_list = []
addr_offset += sizeof(IpcWindow())
num_win = int(msg.num_windows)
for _ in range(num_win):
win_elem = IpcWindowElem.from_address(addr_offset)
win_elem_list.append(win_elem)
addr_offset += sizeof(IpcWindowElem())
for elem in win_elem_list:
logging.info(str(elem))