mirror of
https://github.com/DragonOS-Community/DragonOS.git
synced 2025-06-11 09:06:47 +00:00
230 lines
7.5 KiB
C
230 lines
7.5 KiB
C
#include "msi.h"
|
||
#include "pci.h"
|
||
|
||
/**
|
||
* @brief 生成架构相关的msi的message address
|
||
*
|
||
*/
|
||
#define pci_get_arch_msi_message_address(processor) ((uint64_t)(0xfee00000UL | (processor << 12)))
|
||
|
||
/**
|
||
* @brief 生成架构相关的message data
|
||
*
|
||
*/
|
||
#define pci_get_arch_msi_message_data(vector, processor, edge_trigger, assert) ((uint32_t)((vector & 0xff) | (edge_trigger == 1 ? 0 : (1 << 15)) | ((assert == 0) ? 0 : (1 << 14))))
|
||
|
||
/**
|
||
* @brief 启用 Message Signaled Interrupts
|
||
*
|
||
* @param header 设备header
|
||
* @param vector 中断向量号
|
||
* @param processor 要投递到的处理器
|
||
* @param edge_trigger 是否边缘触发
|
||
* @param assert 是否高电平触发
|
||
*
|
||
* @return 返回码
|
||
*/
|
||
// int pci_enable_msi(void *header, uint8_t vector, uint32_t processor, uint8_t edge_trigger, uint8_t assert)
|
||
int pci_enable_msi(struct msi_desc_t *msi_desc)
|
||
{
|
||
struct pci_device_structure_header_t *ptr = msi_desc->pci_dev;
|
||
uint32_t cap_ptr;
|
||
uint32_t tmp;
|
||
uint16_t message_control;
|
||
uint64_t message_addr;
|
||
switch (ptr->HeaderType)
|
||
{
|
||
case 0x00: // general device
|
||
if (!(ptr->Status & 0x10))
|
||
return E_NOT_SUPPORT_MSI;
|
||
|
||
cap_ptr = ((struct pci_device_structure_general_device_t *)ptr)->Capabilities_Pointer;
|
||
|
||
tmp = pci_read_config(ptr->bus, ptr->device, ptr->func, cap_ptr); // 读取cap+0x0处的值
|
||
message_control = (tmp >> 16) & 0xffff;
|
||
|
||
if (tmp & 0xff != 0x5)
|
||
return E_NOT_SUPPORT_MSI;
|
||
|
||
// 写入message address
|
||
message_addr = pci_get_arch_msi_message_address(msi_desc->processor); // 获取message address
|
||
pci_write_config(ptr->bus, ptr->device, ptr->func, cap_ptr + 0x4, (uint32_t)(message_addr & 0xffffffff));
|
||
|
||
if (message_control & (1 << 7)) // 64位
|
||
pci_write_config(ptr->bus, ptr->device, ptr->func, cap_ptr + 0x8, (uint32_t)((message_addr >> 32) & 0xffffffff));
|
||
|
||
// 写入message data
|
||
|
||
tmp = pci_get_arch_msi_message_data(msi_desc->irq_num, msi_desc->processor, msi_desc->edge_trigger, msi_desc->assert);
|
||
if (message_control & (1 << 7)) // 64位
|
||
pci_write_config(ptr->bus, ptr->device, ptr->func, cap_ptr + 0xc, tmp);
|
||
else
|
||
pci_write_config(ptr->bus, ptr->device, ptr->func, cap_ptr + 0x8, tmp);
|
||
|
||
// 使能msi
|
||
tmp = pci_read_config(ptr->bus, ptr->device, ptr->func, cap_ptr); // 读取cap+0x0处的值
|
||
tmp |= (1 << 16);
|
||
pci_write_config(ptr->bus, ptr->device, ptr->func, cap_ptr, tmp);
|
||
|
||
break;
|
||
|
||
case 0x01: // pci to pci bridge
|
||
if (!(ptr->Status & 0x10))
|
||
return E_NOT_SUPPORT_MSI;
|
||
cap_ptr = ((struct pci_device_structure_pci_to_pci_bridge_t *)ptr)->Capability_Pointer;
|
||
|
||
tmp = pci_read_config(ptr->bus, ptr->device, ptr->func, cap_ptr); // 读取cap+0x0处的值
|
||
|
||
message_control = (tmp >> 16) & 0xffff;
|
||
|
||
if (tmp & 0xff != 0x5)
|
||
return E_NOT_SUPPORT_MSI;
|
||
|
||
// 写入message address
|
||
message_addr = pci_get_arch_msi_message_address(msi_desc->processor); // 获取message address
|
||
pci_write_config(ptr->bus, ptr->device, ptr->func, cap_ptr + 0x4, (uint32_t)(message_addr & 0xffffffff));
|
||
|
||
if (message_control & (1 << 7)) // 64位
|
||
pci_write_config(ptr->bus, ptr->device, ptr->func, cap_ptr + 0x8, (uint32_t)((message_addr >> 32) & 0xffffffff));
|
||
|
||
// 写入message data
|
||
tmp = pci_get_arch_msi_message_data(msi_desc->irq_num, msi_desc->processor, msi_desc->edge_trigger, msi_desc->assert);
|
||
if (message_control & (1 << 7)) // 64位
|
||
pci_write_config(ptr->bus, ptr->device, ptr->func, cap_ptr + 0xc, tmp);
|
||
else
|
||
pci_write_config(ptr->bus, ptr->device, ptr->func, cap_ptr + 0x8, tmp);
|
||
|
||
// 使能msi
|
||
tmp = pci_read_config(ptr->bus, ptr->device, ptr->func, cap_ptr); // 读取cap+0x0处的值
|
||
tmp |= (1 << 16);
|
||
pci_write_config(ptr->bus, ptr->device, ptr->func, cap_ptr, tmp);
|
||
|
||
break;
|
||
case 0x02: // pci to card bus bridge
|
||
return E_NOT_SUPPORT_MSI;
|
||
break;
|
||
|
||
default: // 不应该到达这里
|
||
return E_WRONG_HEADER_TYPE;
|
||
break;
|
||
}
|
||
|
||
return 0;
|
||
}
|
||
|
||
/**
|
||
* @brief 在已配置好msi寄存器的设备上,使能msi
|
||
*
|
||
* @param header 设备头部
|
||
* @return int 返回码
|
||
*/
|
||
int pci_start_msi(void *header)
|
||
{
|
||
struct pci_device_structure_header_t *ptr = (struct pci_device_structure_header_t *)header;
|
||
uint32_t cap_ptr;
|
||
uint32_t tmp;
|
||
|
||
switch (ptr->HeaderType)
|
||
{
|
||
case 0x00: // general device
|
||
if (!(ptr->Status & 0x10))
|
||
return E_NOT_SUPPORT_MSI;
|
||
cap_ptr = ((struct pci_device_structure_general_device_t *)ptr)->Capabilities_Pointer;
|
||
|
||
tmp = pci_read_config(ptr->bus, ptr->device, ptr->func, cap_ptr); // 读取cap+0x0处的值
|
||
|
||
if (tmp & 0xff != 0x5)
|
||
return E_NOT_SUPPORT_MSI;
|
||
|
||
// 使能msi
|
||
tmp = pci_read_config(ptr->bus, ptr->device, ptr->func, cap_ptr); // 读取cap+0x0处的值
|
||
tmp |= (1 << 16);
|
||
pci_write_config(ptr->bus, ptr->device, ptr->func, cap_ptr, tmp);
|
||
|
||
break;
|
||
|
||
case 0x01: // pci to pci bridge
|
||
if (!(ptr->Status & 0x10))
|
||
return E_NOT_SUPPORT_MSI;
|
||
cap_ptr = ((struct pci_device_structure_pci_to_pci_bridge_t *)ptr)->Capability_Pointer;
|
||
|
||
tmp = pci_read_config(ptr->bus, ptr->device, ptr->func, cap_ptr); // 读取cap+0x0处的值
|
||
|
||
if (tmp & 0xff != 0x5)
|
||
return E_NOT_SUPPORT_MSI;
|
||
|
||
//使能msi
|
||
tmp = pci_read_config(ptr->bus, ptr->device, ptr->func, cap_ptr); // 读取cap+0x0处的值
|
||
tmp |= (1 << 16);
|
||
pci_write_config(ptr->bus, ptr->device, ptr->func, cap_ptr, tmp);
|
||
|
||
break;
|
||
case 0x02: // pci to card bus bridge
|
||
return E_NOT_SUPPORT_MSI;
|
||
break;
|
||
|
||
default: // 不应该到达这里
|
||
return E_WRONG_HEADER_TYPE;
|
||
break;
|
||
}
|
||
|
||
return 0;
|
||
}
|
||
/**
|
||
* @brief 禁用指定设备的msi
|
||
*
|
||
* @param header pci header
|
||
* @return int
|
||
*/
|
||
int pci_disable_msi(void *header)
|
||
{
|
||
struct pci_device_structure_header_t *ptr = (struct pci_device_structure_header_t *)header;
|
||
uint32_t cap_ptr;
|
||
uint32_t tmp;
|
||
|
||
switch (ptr->HeaderType)
|
||
{
|
||
case 0x00: // general device
|
||
if (!(ptr->Status & 0x10))
|
||
return E_NOT_SUPPORT_MSI;
|
||
cap_ptr = ((struct pci_device_structure_general_device_t *)ptr)->Capabilities_Pointer;
|
||
|
||
tmp = pci_read_config(ptr->bus, ptr->device, ptr->func, cap_ptr); // 读取cap+0x0处的值
|
||
|
||
if (tmp & 0xff != 0x5)
|
||
return E_NOT_SUPPORT_MSI;
|
||
|
||
// 禁用msi
|
||
tmp = pci_read_config(ptr->bus, ptr->device, ptr->func, cap_ptr); // 读取cap+0x0处的值
|
||
tmp &= (~(1 << 16));
|
||
pci_write_config(ptr->bus, ptr->device, ptr->func, cap_ptr, tmp);
|
||
|
||
break;
|
||
|
||
case 0x01: // pci to pci bridge
|
||
if (!(ptr->Status & 0x10))
|
||
return E_NOT_SUPPORT_MSI;
|
||
cap_ptr = ((struct pci_device_structure_pci_to_pci_bridge_t *)ptr)->Capability_Pointer;
|
||
|
||
tmp = pci_read_config(ptr->bus, ptr->device, ptr->func, cap_ptr); // 读取cap+0x0处的值
|
||
|
||
if (tmp & 0xff != 0x5)
|
||
return E_NOT_SUPPORT_MSI;
|
||
|
||
//禁用msi
|
||
tmp = pci_read_config(ptr->bus, ptr->device, ptr->func, cap_ptr); // 读取cap+0x0处的值
|
||
tmp &= (~(1 << 16));
|
||
pci_write_config(ptr->bus, ptr->device, ptr->func, cap_ptr, tmp);
|
||
|
||
break;
|
||
case 0x02: // pci to card bus bridge
|
||
return E_NOT_SUPPORT_MSI;
|
||
break;
|
||
|
||
default: // 不应该到达这里
|
||
return E_WRONG_HEADER_TYPE;
|
||
break;
|
||
}
|
||
|
||
return 0;
|
||
} |