pyrite: Add support for flashing via PCIe VSEC

Signed-off-by: Alex Forencich <alex@alexforencich.com>
This commit is contained in:
Alex Forencich
2026-02-24 12:33:55 -08:00
parent 5d3aff95cc
commit 8b925954ef
5 changed files with 607 additions and 11 deletions

View File

@@ -0,0 +1,3 @@
pyrite_pcie_us_vsec_bpi.sv
../lib/taxi/src/pcie/rtl/taxi_pcie_us_vsec_apb.sv
../lib/taxi/src/apb/rtl/taxi_apb_if.sv

View File

@@ -0,0 +1,250 @@
// SPDX-License-Identifier: CERN-OHL-S-2.0
/*
Copyright (c) 2026 FPGA Ninja, LLC
Authors:
- Alex Forencich
*/
`resetall
`timescale 1ns / 1ps
`default_nettype none
/*
* Pyrite flashing support for UltraScale+ PCIe VSEC and BPI flash
*/
module pyrite_pcie_us_vsec_bpi #
(
parameter logic [15:0] EXT_CAP_ID = 16'h000B,
parameter logic [3:0] EXT_CAP_VERSION = 4'h1,
parameter logic [11:0] EXT_CAP_OFFSET = 12'h480,
parameter logic [11:0] EXT_CAP_NEXT = 12'h000,
parameter logic [15:0] EXT_CAP_VSEC_ID = 16'h00DB,
parameter logic [3:0] EXT_CAP_VSEC_REV = 4'h1,
// FW ID
parameter FPGA_ID = 32'hDEADBEEF,
parameter FW_ID = 32'h00000000,
parameter FW_VER = 32'h000_01_000,
parameter BOARD_ID = 32'h1234_0000,
parameter BOARD_VER = 32'h001_00_000,
parameter BUILD_DATE = 32'd602976000,
parameter GIT_HASH = 32'h5f87c2e8,
parameter RELEASE_INFO = 32'h00000000,
// Flash
parameter logic [3:0] FLASH_SEG_COUNT = 2,
parameter logic [3:0] FLASH_SEG_DEFAULT = 1,
parameter logic [3:0] FLASH_SEG_FALLBACK = 0,
parameter logic [31:0] FLASH_SEG0_SIZE = 32'h00000000,
parameter FLASH_DATA_W = 16,
parameter FLASH_ADDR_W = 23,
parameter FLASH_RGN_W = 1
)
(
input wire logic clk,
input wire logic rst,
/*
* PCIe
*/
input wire logic cfg_ext_read_received,
input wire logic cfg_ext_write_received,
input wire logic [9:0] cfg_ext_register_number,
input wire logic [7:0] cfg_ext_function_number,
input wire logic [31:0] cfg_ext_write_data,
input wire logic [3:0] cfg_ext_write_byte_enable,
output wire logic [31:0] cfg_ext_read_data,
output wire logic cfg_ext_read_data_valid,
/*
* BPI flash
*/
output wire logic fpga_boot,
input wire logic [FLASH_DATA_W-1:0] flash_dq_i,
output wire logic [FLASH_DATA_W-1:0] flash_dq_o,
output wire logic flash_dq_oe,
output wire logic [FLASH_ADDR_W-1:0] flash_addr,
output wire logic [FLASH_RGN_W-1:0] flash_region,
output wire logic flash_region_oe,
output wire logic flash_ce_n,
output wire logic flash_oe_n,
output wire logic flash_we_n,
output wire logic flash_adv_n
);
taxi_apb_if #(
.DATA_W(32),
.ADDR_W(16)
) vsec_apb();
taxi_pcie_us_vsec_apb #(
.EXT_CAP_ID(EXT_CAP_ID),
.EXT_CAP_VERSION(EXT_CAP_VERSION),
.EXT_CAP_OFFSET(EXT_CAP_OFFSET),
.EXT_CAP_NEXT(EXT_CAP_NEXT),
.EXT_CAP_VSEC_ID(EXT_CAP_VSEC_ID),
.EXT_CAP_VSEC_REV(EXT_CAP_VSEC_REV)
)
vsec_cap_inst (
.clk(clk),
.rst(rst),
/*
* APB interface for register space
*/
.m_apb(vsec_apb),
/*
* Interface to Ultrascale PCIe IP core
*/
.cfg_ext_read_received(cfg_ext_read_received),
.cfg_ext_write_received(cfg_ext_write_received),
.cfg_ext_register_number(cfg_ext_register_number),
.cfg_ext_function_number(cfg_ext_function_number),
.cfg_ext_write_data(cfg_ext_write_data),
.cfg_ext_write_byte_enable(cfg_ext_write_byte_enable),
.cfg_ext_read_data(cfg_ext_read_data),
.cfg_ext_read_data_valid(cfg_ext_read_data_valid)
);
logic vsec_apb_pready_reg = 1'b0;
logic [31:0] vsec_apb_prdata_reg = '0;
logic fpga_boot_reg = 1'b0;
logic [FLASH_DATA_W-1:0] flash_dq_o_reg = '0;
logic flash_dq_oe_reg = 1'b0;
logic [FLASH_ADDR_W-1:0] flash_addr_reg = '0;
logic [FLASH_RGN_W-1:0] flash_region_reg = '0;
logic flash_region_oe_reg = 1'b0;
logic flash_ce_n_reg = 1'b1;
logic flash_oe_n_reg = 1'b1;
logic flash_we_n_reg = 1'b1;
logic flash_adv_n_reg = 1'b1;
assign vsec_apb.pready = vsec_apb_pready_reg;
assign vsec_apb.prdata = vsec_apb_prdata_reg;
assign vsec_apb.pslverr = 1'b0;
assign vsec_apb.pruser = '0;
assign vsec_apb.pbuser = '0;
assign fpga_boot = fpga_boot_reg;
assign flash_dq_o = flash_dq_o_reg;
assign flash_dq_oe = flash_dq_oe_reg;
assign flash_addr = flash_addr_reg;
assign flash_region = flash_region_reg;
assign flash_region_oe = flash_region_oe_reg;
assign flash_ce_n = flash_ce_n_reg;
assign flash_oe_n = flash_oe_n_reg;
assign flash_we_n = flash_we_n_reg;
assign flash_adv_n = flash_adv_n_reg;
always_ff @(posedge clk) begin
vsec_apb_pready_reg <= 1'b0;
if (vsec_apb.penable && vsec_apb.psel && !vsec_apb_pready_reg) begin
vsec_apb_pready_reg <= 1'b1;
vsec_apb_prdata_reg <= '0;
if (vsec_apb.pwrite) begin
case (8'({vsec_apb.paddr >> 2, 2'b00}))
// FW ID
8'h0C: begin
// FW ID: FPGA JTAG ID
fpga_boot_reg <= vsec_apb.pwdata == 32'hFEE1DEAD;
end
// BPI flash
8'h4C: begin
// BPI flash ctrl: format
fpga_boot_reg <= vsec_apb.pwdata == 32'hFEE1DEAD;
end
8'h50: begin
// BPI flash ctrl: control
if (vsec_apb.pstrb[0]) begin
flash_ce_n_reg <= vsec_apb.pwdata[0];
flash_oe_n_reg <= vsec_apb.pwdata[1];
flash_we_n_reg <= vsec_apb.pwdata[2];
flash_adv_n_reg <= vsec_apb.pwdata[3];
end
if (vsec_apb.pstrb[1]) begin
flash_dq_oe_reg <= vsec_apb.pwdata[8];
end
if (vsec_apb.pstrb[2]) begin
flash_region_oe_reg <= vsec_apb.pwdata[16];
end
end
8'h54: begin
// BPI flash ctrl: address
{flash_region_reg, flash_addr_reg} <= (FLASH_ADDR_W+FLASH_RGN_W)'(vsec_apb.pwdata);
end
8'h58: flash_dq_o_reg <= FLASH_DATA_W'(vsec_apb.pwdata); // BPI flash ctrl: data
default: begin end
endcase
end
case (8'({vsec_apb.paddr >> 2, 2'b00}))
// FW ID
8'h00: vsec_apb_prdata_reg <= 32'hffffffff; // FW ID: Type
8'h04: vsec_apb_prdata_reg <= 32'h000_01_000; // FW ID: Version
8'h08: vsec_apb_prdata_reg <= 32'h40; // FW ID: Next header
8'h0C: vsec_apb_prdata_reg <= FPGA_ID; // FW ID: FPGA JTAG ID
8'h10: vsec_apb_prdata_reg <= FW_ID; // FW ID: Firmware ID
8'h14: vsec_apb_prdata_reg <= FW_VER; // FW ID: Firmware version
8'h18: vsec_apb_prdata_reg <= BOARD_ID; // FW ID: Board ID
8'h1C: vsec_apb_prdata_reg <= BOARD_VER; // FW ID: Board version
8'h20: vsec_apb_prdata_reg <= BUILD_DATE; // FW ID: Build date
8'h24: vsec_apb_prdata_reg <= GIT_HASH; // FW ID: Git commit hash
8'h28: vsec_apb_prdata_reg <= RELEASE_INFO; // FW ID: Release info
// BPI flash
8'h40: vsec_apb_prdata_reg <= 32'h0000C121; // BPI flash ctrl: Type
8'h44: vsec_apb_prdata_reg <= 32'h000_01_000; // BPI flash ctrl: Version
8'h48: vsec_apb_prdata_reg <= 0; // BPI flash ctrl: Next header
8'h4C: begin
// BPI flash ctrl: format
vsec_apb_prdata_reg[3:0] <= FLASH_SEG_COUNT; // configuration
vsec_apb_prdata_reg[7:4] <= FLASH_SEG_DEFAULT; // default segment
vsec_apb_prdata_reg[11:8] <= FLASH_SEG_FALLBACK; // fallback segment
vsec_apb_prdata_reg[31:12] <= 20'(FLASH_SEG0_SIZE >> 12); // first segment size
end
8'h50: begin
// BPI flash ctrl: control
vsec_apb_prdata_reg[0] <= flash_ce_n_reg; // chip enable (inverted)
vsec_apb_prdata_reg[1] <= flash_oe_n_reg; // output enable (inverted)
vsec_apb_prdata_reg[2] <= flash_we_n_reg; // write enable (inverted)
vsec_apb_prdata_reg[3] <= flash_adv_n_reg; // address valid (inverted)
vsec_apb_prdata_reg[8] <= flash_dq_oe_reg; // data output enable
vsec_apb_prdata_reg[16] <= flash_region_oe_reg; // region output enable (addr bit 25)
end
8'h54: begin
// BPI flash ctrl: address
vsec_apb_prdata_reg <= 32'({flash_region_reg, flash_addr_reg});
end
8'h58: vsec_apb_prdata_reg <= 32'(flash_dq_i); // BPI flash ctrl: data
default: begin end
endcase
end
if (rst) begin
vsec_apb_pready_reg <= 1'b0;
fpga_boot_reg <= 1'b0;
flash_dq_o_reg <= '0;
flash_dq_oe_reg <= 1'b0;
flash_addr_reg <= '0;
flash_region_reg <= '0;
flash_region_oe_reg <= 1'b0;
flash_ce_n_reg <= 1'b1;
flash_oe_n_reg <= 1'b1;
flash_we_n_reg <= 1'b1;
flash_adv_n_reg <= 1'b1;
end
end
endmodule
`resetall

View File

@@ -0,0 +1,3 @@
pyrite_pcie_us_vsec_qspi.sv
../lib/taxi/src/pcie/rtl/taxi_pcie_us_vsec_apb.sv
../lib/taxi/src/apb/rtl/taxi_apb_if.sv

View File

@@ -0,0 +1,252 @@
// SPDX-License-Identifier: CERN-OHL-S-2.0
/*
Copyright (c) 2026 FPGA Ninja, LLC
Authors:
- Alex Forencich
*/
`resetall
`timescale 1ns / 1ps
`default_nettype none
/*
* Pyrite flashing support for UltraScale+ PCIe VSEC and QSPI flash
*/
module pyrite_pcie_us_vsec_qspi #
(
parameter logic [15:0] EXT_CAP_ID = 16'h000B,
parameter logic [3:0] EXT_CAP_VERSION = 4'h1,
parameter logic [11:0] EXT_CAP_OFFSET = 12'h480,
parameter logic [11:0] EXT_CAP_NEXT = 12'h000,
parameter logic [15:0] EXT_CAP_VSEC_ID = 16'h00DB,
parameter logic [3:0] EXT_CAP_VSEC_REV = 4'h1,
// FW ID
parameter FPGA_ID = 32'hDEADBEEF,
parameter FW_ID = 32'h00000000,
parameter FW_VER = 32'h000_01_000,
parameter BOARD_ID = 32'h1234_0000,
parameter BOARD_VER = 32'h001_00_000,
parameter BUILD_DATE = 32'd602976000,
parameter GIT_HASH = 32'h5f87c2e8,
parameter RELEASE_INFO = 32'h00000000,
// Flash
parameter logic [3:0] FLASH_SEG_COUNT = 2,
parameter logic [3:0] FLASH_SEG_DEFAULT = 1,
parameter logic [3:0] FLASH_SEG_FALLBACK = 0,
parameter logic [31:0] FLASH_SEG0_SIZE = 32'h00000000,
parameter FLASH_DATA_W = 4,
parameter logic FLASH_DUAL_QSPI = 1'b1
)
(
input wire logic clk,
input wire logic rst,
/*
* PCIe
*/
input wire logic cfg_ext_read_received,
input wire logic cfg_ext_write_received,
input wire logic [9:0] cfg_ext_register_number,
input wire logic [7:0] cfg_ext_function_number,
input wire logic [31:0] cfg_ext_write_data,
input wire logic [3:0] cfg_ext_write_byte_enable,
output wire logic [31:0] cfg_ext_read_data,
output wire logic cfg_ext_read_data_valid,
/*
* QSPI flash
*/
output wire logic fpga_boot,
output wire logic qspi_clk,
input wire logic [FLASH_DATA_W-1:0] qspi_0_dq_i,
output wire logic [FLASH_DATA_W-1:0] qspi_0_dq_o,
output wire logic [FLASH_DATA_W-1:0] qspi_0_dq_oe,
output wire logic qspi_0_cs,
input wire logic [FLASH_DATA_W-1:0] qspi_1_dq_i,
output wire logic [FLASH_DATA_W-1:0] qspi_1_dq_o,
output wire logic [FLASH_DATA_W-1:0] qspi_1_dq_oe,
output wire logic qspi_1_cs
);
taxi_apb_if #(
.DATA_W(32),
.ADDR_W(16)
) vsec_apb();
taxi_pcie_us_vsec_apb #(
.EXT_CAP_ID(EXT_CAP_ID),
.EXT_CAP_VERSION(EXT_CAP_VERSION),
.EXT_CAP_OFFSET(EXT_CAP_OFFSET),
.EXT_CAP_NEXT(EXT_CAP_NEXT),
.EXT_CAP_VSEC_ID(EXT_CAP_VSEC_ID),
.EXT_CAP_VSEC_REV(EXT_CAP_VSEC_REV)
)
vsec_cap_inst (
.clk(clk),
.rst(rst),
/*
* APB interface for register space
*/
.m_apb(vsec_apb),
/*
* Interface to Ultrascale PCIe IP core
*/
.cfg_ext_read_received(cfg_ext_read_received),
.cfg_ext_write_received(cfg_ext_write_received),
.cfg_ext_register_number(cfg_ext_register_number),
.cfg_ext_function_number(cfg_ext_function_number),
.cfg_ext_write_data(cfg_ext_write_data),
.cfg_ext_write_byte_enable(cfg_ext_write_byte_enable),
.cfg_ext_read_data(cfg_ext_read_data),
.cfg_ext_read_data_valid(cfg_ext_read_data_valid)
);
logic vsec_apb_pready_reg = 1'b0;
logic [31:0] vsec_apb_prdata_reg = '0;
logic fpga_boot_reg = 1'b0;
logic qspi_clk_reg = 1'b0;
logic qspi_0_cs_reg = 1'b1;
logic [FLASH_DATA_W-1:0] qspi_0_dq_o_reg = '0;
logic [FLASH_DATA_W-1:0] qspi_0_dq_oe_reg = '0;
logic qspi_1_cs_reg = 1'b1;
logic [FLASH_DATA_W-1:0] qspi_1_dq_o_reg = '0;
logic [FLASH_DATA_W-1:0] qspi_1_dq_oe_reg = '0;
assign vsec_apb.pready = vsec_apb_pready_reg;
assign vsec_apb.prdata = vsec_apb_prdata_reg;
assign vsec_apb.pslverr = 1'b0;
assign vsec_apb.pruser = '0;
assign vsec_apb.pbuser = '0;
assign fpga_boot = fpga_boot_reg;
assign qspi_clk = qspi_clk_reg;
assign qspi_0_cs = qspi_0_cs_reg;
assign qspi_0_dq_o = qspi_0_dq_o_reg;
assign qspi_0_dq_oe = qspi_0_dq_oe_reg;
assign qspi_1_cs = FLASH_DUAL_QSPI ? qspi_1_cs_reg : 1'b1;
assign qspi_1_dq_o = FLASH_DUAL_QSPI ? qspi_1_dq_o_reg : '0;
assign qspi_1_dq_oe = FLASH_DUAL_QSPI ? qspi_1_dq_oe_reg : '0;
always_ff @(posedge clk) begin
vsec_apb_pready_reg <= 1'b0;
if (vsec_apb.penable && vsec_apb.psel && !vsec_apb_pready_reg) begin
vsec_apb_pready_reg <= 1'b1;
vsec_apb_prdata_reg <= '0;
if (vsec_apb.pwrite) begin
case (8'({vsec_apb.paddr >> 2, 2'b00}))
// FW ID
8'h0C: begin
// FW ID: FPGA JTAG ID
fpga_boot_reg <= vsec_apb.pwdata == 32'hFEE1DEAD;
end
// QSPI flash
8'h4C: begin
// SPI flash ctrl: format
fpga_boot_reg <= vsec_apb.pwdata == 32'hFEE1DEAD;
end
8'h50: begin
// SPI flash ctrl: control 0
if (vsec_apb.pstrb[0]) begin
qspi_0_dq_o_reg <= vsec_apb.pwdata[3:0];
end
if (vsec_apb.pstrb[1]) begin
qspi_0_dq_oe_reg <= vsec_apb.pwdata[11:8];
end
if (vsec_apb.pstrb[2]) begin
qspi_clk_reg <= vsec_apb.pwdata[16];
qspi_0_cs_reg <= vsec_apb.pwdata[17];
end
end
8'h54: begin
// SPI flash ctrl: control 1
if (FLASH_DUAL_QSPI) begin
if (vsec_apb.pstrb[0]) begin
qspi_1_dq_o_reg <= vsec_apb.pwdata[3:0];
end
if (vsec_apb.pstrb[1]) begin
qspi_1_dq_oe_reg <= vsec_apb.pwdata[11:8];
end
if (vsec_apb.pstrb[2]) begin
qspi_clk_reg <= vsec_apb.pwdata[16];
qspi_1_cs_reg <= vsec_apb.pwdata[17];
end
end
end
default: begin end
endcase
end
case (8'({vsec_apb.paddr >> 2, 2'b00}))
// FW ID
8'h00: vsec_apb_prdata_reg <= 32'hffffffff; // FW ID: Type
8'h04: vsec_apb_prdata_reg <= 32'h000_01_000; // FW ID: Version
8'h08: vsec_apb_prdata_reg <= 32'h40; // FW ID: Next header
8'h0C: vsec_apb_prdata_reg <= FPGA_ID; // FW ID: FPGA JTAG ID
8'h10: vsec_apb_prdata_reg <= FW_ID; // FW ID: Firmware ID
8'h14: vsec_apb_prdata_reg <= FW_VER; // FW ID: Firmware version
8'h18: vsec_apb_prdata_reg <= BOARD_ID; // FW ID: Board ID
8'h1C: vsec_apb_prdata_reg <= BOARD_VER; // FW ID: Board version
8'h20: vsec_apb_prdata_reg <= BUILD_DATE; // FW ID: Build date
8'h24: vsec_apb_prdata_reg <= GIT_HASH; // FW ID: Git commit hash
8'h28: vsec_apb_prdata_reg <= RELEASE_INFO; // FW ID: Release info
// QSPI flash
8'h40: vsec_apb_prdata_reg <= 32'h0000C120; // SPI flash ctrl: Type
8'h44: vsec_apb_prdata_reg <= 32'h000_01_000; // SPI flash ctrl: Version
8'h48: vsec_apb_prdata_reg <= 0; // SPI flash ctrl: Next header
8'h4C: begin
// SPI flash ctrl: format
vsec_apb_prdata_reg[3:0] <= FLASH_SEG_COUNT; // configuration
vsec_apb_prdata_reg[7:4] <= FLASH_SEG_DEFAULT; // default segment
vsec_apb_prdata_reg[11:8] <= FLASH_SEG_FALLBACK; // fallback segment
vsec_apb_prdata_reg[31:12] <= 20'(FLASH_SEG0_SIZE >> 12); // first segment size
end
8'h50: begin
// SPI flash ctrl: control 0
vsec_apb_prdata_reg[3:0] <= qspi_0_dq_i;
vsec_apb_prdata_reg[11:8] <= qspi_0_dq_oe;
vsec_apb_prdata_reg[16] <= qspi_clk;
vsec_apb_prdata_reg[17] <= qspi_0_cs;
end
8'h54: begin
// SPI flash ctrl: control 1
if (FLASH_DUAL_QSPI) begin
vsec_apb_prdata_reg[3:0] <= qspi_1_dq_i;
vsec_apb_prdata_reg[11:8] <= qspi_1_dq_oe;
vsec_apb_prdata_reg[16] <= qspi_clk;
vsec_apb_prdata_reg[17] <= qspi_1_cs;
end
end
default: begin end
endcase
end
if (rst) begin
vsec_apb_pready_reg <= 1'b0;
fpga_boot_reg <= 1'b0;
qspi_clk_reg <= 1'b0;
qspi_0_cs_reg <= 1'b1;
qspi_0_dq_o_reg <= '0;
qspi_0_dq_oe_reg <= '0;
qspi_1_cs_reg <= 1'b1;
qspi_1_dq_o_reg <= '0;
qspi_1_dq_oe_reg <= '0;
end
end
endmodule
`resetall

View File

@@ -506,6 +506,7 @@ struct reg_if *reg_if_open_vpd(int fd)
{ {
char buf[32]; char buf[32];
int offset; int offset;
bool found = false;
struct reg_if *reg = calloc(sizeof(struct reg_if), 1); struct reg_if *reg = calloc(sizeof(struct reg_if), 1);
@@ -530,14 +531,98 @@ struct reg_if *reg_if_open_vpd(int fd)
while (offset > 0) { while (offset > 0) {
pread(fd, buf, 2, offset); pread(fd, buf, 2, offset);
if (buf[0] == PCI_CAP_ID_VPD) if (buf[0] == PCI_CAP_ID_VPD) {
found = true;
break; break;
}
offset = buf[1] & 0xfc; offset = buf[1] & 0xfc;
} }
if (!offset || buf[0] != PCI_CAP_ID_VPD) { if (!found) {
perror("Failed to locate VPD capability"); reg_if_close(reg);
return NULL;
}
priv->fd = fd;
priv->offset = offset;
return reg;
}
struct vsec_reg_priv {
int fd;
int offset;
};
static int reg_if_vsec_read32(const struct reg_if *reg, size_t offset, uint32_t *value)
{
const struct vsec_reg_priv *priv = reg->priv;
uint32_t offs = offset & 0x7fffffff; // clear F
pwrite(priv->fd, &offs, 4, priv->offset+0x08);
pread(priv->fd, value, 4, priv->offset+0x0c);
return 0;
}
static int reg_if_vsec_write32(const struct reg_if *reg, size_t offset, uint32_t value)
{
const struct vsec_reg_priv *priv = reg->priv;
uint32_t offs = offset | 0x80000000; // set F
pwrite(priv->fd, &value, 4, priv->offset+0x0c);
pwrite(priv->fd, &offs, 4, priv->offset+0x08);
return 0;
}
static void reg_if_vsec_close(const struct reg_if *reg)
{
free(reg->priv);
}
static const struct reg_if_ops reg_if_vsec_ops = {
.read32 = reg_if_vsec_read32,
.write32 = reg_if_vsec_write32,
.close = reg_if_vsec_close,
};
struct reg_if *reg_if_open_vsec(int fd)
{
uint32_t cap_hdr, vsec_hdr;
int offset;
bool found = false;
struct reg_if *reg = calloc(sizeof(struct reg_if), 1);
if (!reg)
return NULL;
struct vsec_reg_priv *priv = calloc(sizeof(struct vsec_reg_priv), 1);
if (!priv) {
free(reg);
return NULL;
}
reg->priv = priv;
reg->ops = &reg_if_vsec_ops;
// find VSEC extended capability (ID 0x000b, VSEC ID 0x00db)
offset = 0x100;
while (offset > 0) {
pread(fd, &cap_hdr, 4, offset);
if ((cap_hdr & 0xfffff) == 0x1000b) {
pread(fd, &vsec_hdr, 4, offset+4);
if ((vsec_hdr & 0xfffff) == 0x100db) {
found = true;
break;
}
}
offset = cap_hdr >> 20;
}
if (!found) {
reg_if_close(reg); reg_if_close(reg);
return NULL; return NULL;
} }
@@ -554,7 +639,7 @@ int main(int argc, char *argv[])
int opt; int opt;
int ret = 0; int ret = 0;
struct reg_if *vpd_regs; struct reg_if *ctrl_regs;
char dev_name[32] = ""; char dev_name[32] = "";
char *read_file_name = NULL; char *read_file_name = NULL;
@@ -683,9 +768,12 @@ int main(int argc, char *argv[])
return -1; return -1;
} }
vpd_regs = reg_if_open_vpd(config_fd); if ((ctrl_regs = reg_if_open_vsec(config_fd))) {
if (!vpd_regs) { // found VSEC
perror("Failed to initialize VPD capability"); } else if ((ctrl_regs = reg_if_open_vpd(config_fd))) {
// found VPD
} else {
fprintf(stderr, "Failed to locate capability structure\n");
ret = -1; ret = -1;
goto err; goto err;
} }
@@ -699,7 +787,7 @@ int main(int argc, char *argv[])
printf("PCIe ID (device): %s\n", strrchr(pci_device_path, '/')+1); printf("PCIe ID (device): %s\n", strrchr(pci_device_path, '/')+1);
printf("PCIe ID (upstream port): %s\n", strrchr(pci_port_path, '/')+1); printf("PCIe ID (upstream port): %s\n", strrchr(pci_port_path, '/')+1);
rb_list = enumerate_reg_block_list(vpd_regs, 0x4000, 0, 0x4000); rb_list = enumerate_reg_block_list(ctrl_regs, 0x4000, 0, 0x4000);
printf("Register blocks:\n"); printf("Register blocks:\n");
for (struct reg_block *rb = rb_list; rb->regs; rb++) for (struct reg_block *rb = rb_list; rb->regs; rb++)
@@ -1422,8 +1510,8 @@ skip_flash:
reg_if_write32(fw_id_rb->regs, 0x0C, 0xFEE1DEAD); reg_if_write32(fw_id_rb->regs, 0x0C, 0xFEE1DEAD);
// disconnect // disconnect
reg_if_close(vpd_regs); reg_if_close(ctrl_regs);
vpd_regs = NULL; ctrl_regs = NULL;
close(config_fd); close(config_fd);
} }
@@ -1484,7 +1572,7 @@ err:
flash_release(pri_flash); flash_release(pri_flash);
flash_release(sec_flash); flash_release(sec_flash);
reg_if_close(vpd_regs); reg_if_close(ctrl_regs);
close(config_fd); close(config_fd);
return ret; return ret;