diff --git a/src/data.zig b/src/data.zig index a2517f5..a1ec0b8 100644 --- a/src/data.zig +++ b/src/data.zig @@ -185,8 +185,8 @@ pub const Resources = struct { pub const I2c = struct { const MAGIC: [5]u8 = MAGIC_START ++ .{0x4}; + // SDDF Queue connection between PDs pub const Connection = extern struct { - data: Region, req_queue: Region, resp_queue: Region, num_buffers: u16, @@ -196,7 +196,12 @@ pub const Resources = struct { pub const Virt = extern struct { pub const Client = extern struct { conn: Connection, - driver_data_offset: u64, + data_size: usize, + meta_size: usize, + driver_data_vaddr: u64, + driver_meta_vaddr: u64, // vaddr as mapped into driver + client_data_vaddr: u64, + client_meta_vaddr: u64, }; magic: [5]u8 = MAGIC, @@ -213,6 +218,8 @@ pub const Resources = struct { pub const Client = extern struct { magic: [5]u8 = MAGIC, virt: Connection, + data: Region, + meta: Region, }; }; diff --git a/src/sddf.zig b/src/sddf.zig index b0333e7..0e84fa3 100644 --- a/src/sddf.zig +++ b/src/sddf.zig @@ -418,6 +418,7 @@ pub const I2c = struct { region_req_size: usize, region_resp_size: usize, region_data_size: usize, + region_meta_size: usize, driver_config: ConfigResources.I2c.Driver, virt_config: ConfigResources.I2c.Virt, client_configs: std.ArrayList(ConfigResources.I2c.Client), @@ -431,6 +432,7 @@ pub const I2c = struct { region_req_size: usize = 0x1000, region_resp_size: usize = 0x1000, region_data_size: usize = 0x1000, + region_meta_size: usize = 0x10000, }; pub fn init(allocator: Allocator, sdf: *SystemDescription, device: ?*dtb.Node, driver: *Pd, virt: *Pd, options: Options) I2c { @@ -445,11 +447,11 @@ pub const I2c = struct { .region_req_size = options.region_req_size, .region_resp_size = options.region_resp_size, .region_data_size = options.region_data_size, + .region_meta_size = options.region_meta_size, .driver_config = std.mem.zeroInit(ConfigResources.I2c.Driver, .{}), .virt_config = std.mem.zeroInit(ConfigResources.I2c.Virt, .{}), .client_configs = std.ArrayList(ConfigResources.I2c.Client).init(allocator), - // TODO: handle properly - .num_buffers = 128, + .num_buffers = 64, }; } @@ -505,8 +507,6 @@ pub const I2c = struct { system.driver_config = .{ .virt = .{ - // Will be set in connectClient - .data = undefined, .req_queue = .createFromMap(driver_map_req), .resp_queue = .createFromMap(driver_map_resp), .num_buffers = system.num_buffers, @@ -515,8 +515,6 @@ pub const I2c = struct { }; system.virt_config.driver = .{ - // Will be set in connectClient - .data = undefined, .req_queue = .createFromMap(virt_map_req), .resp_queue = .createFromMap(virt_map_resp), .num_buffers = system.num_buffers, @@ -535,14 +533,20 @@ pub const I2c = struct { const mr_req = Mr.create(allocator, fmt(allocator, "i2c_client_request_{s}", .{client.name}), system.region_req_size, .{}); const mr_resp = Mr.create(allocator, fmt(allocator, "i2c_client_response_{s}", .{client.name}), system.region_resp_size, .{}); const mr_data = Mr.create(allocator, fmt(allocator, "i2c_client_data_{s}", .{client.name}), system.region_data_size, .{}); + const mr_meta = Mr.create(allocator, fmt(allocator, "i2c_client_meta_{s}", .{client.name}), system.region_meta_size, .{}); sdf.addMemoryRegion(mr_req); sdf.addMemoryRegion(mr_resp); sdf.addMemoryRegion(mr_data); + sdf.addMemoryRegion(mr_meta); const driver_map_data = Map.create(mr_data, system.driver.getMapVaddr(&mr_data), .rw, .{}); driver.addMap(driver_map_data); + // The meta region backs buffers in the data region. Accessed only by driver and client. + const driver_map_meta = Map.create(mr_meta, system.driver.getMapVaddr(&mr_meta), .rw, .{ .cached = false }); + driver.addMap(driver_map_meta); + const virt_map_req = Map.create(mr_req, system.virt.getMapVaddr(&mr_req), .rw, .{}); virt.addMap(virt_map_req); const virt_map_resp = Map.create(mr_resp, system.virt.getMapVaddr(&mr_resp), .rw, .{}); @@ -552,38 +556,46 @@ pub const I2c = struct { client.addMap(client_map_req); const client_map_resp = Map.create(mr_resp, client.getMapVaddr(&mr_resp), .rw, .{}); client.addMap(client_map_resp); + const client_map_data = Map.create(mr_data, client.getMapVaddr(&mr_data), .rw, .{}); client.addMap(client_map_data); + const client_map_meta = Map.create(mr_meta, client.getMapVaddr(&mr_meta), .rw, .{ .cached = false }); + client.addMap(client_map_meta); // Create a channel between the virtualiser and client const ch = Channel.create(virt, client, .{ .pp = .b }) catch unreachable; sdf.addChannel(ch); + // The below section originally passed the virt a region structure with no vaddr for the + // data region. Instead of doing this, just pass the size of the region. system.virt_config.clients[i] = .{ .conn = .{ - .data = .{ - // TODO: absolute hack - .vaddr = 0, - .size = system.region_data_size, - }, .req_queue = .createFromMap(virt_map_req), .resp_queue = .createFromMap(virt_map_resp), .num_buffers = system.num_buffers, .id = ch.pd_a_id, }, - .driver_data_offset = i * system.region_data_size, + .data_size = system.region_data_size, + .meta_size = system.region_meta_size, + // vaddrs used to convert offsets in cmd / meta buffers to a pointer used by the driver + // .driver_data_vaddr = i * driver_map_data.vaddr, + // .driver_meta_vaddr = i * driver_map_meta.vaddr, + .driver_data_vaddr = driver_map_data.vaddr, + .driver_meta_vaddr = driver_map_meta.vaddr, + .client_data_vaddr = client_map_data.vaddr, + .client_meta_vaddr = client_map_meta.vaddr, }; - if (i == 0) { - system.driver_config.virt.data = .createFromMap(driver_map_data); - } - system.client_configs.items[i] = .{ .virt = .{ + system.client_configs.items[i] = .{ + .virt = .{ + .req_queue = .createFromMap(client_map_req), + .resp_queue = .createFromMap(client_map_resp), + .num_buffers = system.num_buffers, + .id = ch.pd_b_id, + }, .data = .createFromMap(client_map_data), - .req_queue = .createFromMap(client_map_req), - .resp_queue = .createFromMap(client_map_resp), - .num_buffers = system.num_buffers, - .id = ch.pd_b_id, - } }; + .meta = .createFromMap(client_map_meta), + }; } pub fn connect(system: *I2c) !void { @@ -596,7 +608,7 @@ pub const I2c = struct { // 2. Connect the driver to the virtualiser system.connectDriver(); - // 3. Connect each client to the virtualiser + // 3. Connect each client to the virtualiser (and connect the meta region to the driver) for (system.clients.items, 0..) |client, i| { system.connectClient(client, i); } diff --git a/tests/c_example.system b/tests/c_example.system index 48add69..55de436 100644 --- a/tests/c_example.system +++ b/tests/c_example.system @@ -5,11 +5,13 @@ + + @@ -23,6 +25,7 @@ +