1 // Copyright 2017 The Fuchsia Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #pragma once
6 
7 #include <zircon/types.h>
8 
9 __BEGIN_CDECLS;
10 
11 // An entry in a scatter gather list.
12 typedef struct {
13     // length starting at the scatter gather entry offset, must be non zero
14     size_t length;
15     // offset relative to the buffer's vmo_offset
16     size_t offset;
17 } phys_iter_sg_entry_t;
18 
19 // Specifies the buffer to iterate over.
20 typedef struct {
21     zx_paddr_t* phys;     // list of physical addresses backing the buffer starting at vmo_offset
22     uint64_t phys_count;  // number of entries in phys list
23 
24     size_t length;        // length of the buffer starting at vmo_offset, used if scatter gather
25                           // list is not present
26     uint64_t vmo_offset;  // offset into first page to start iterating on
27 
28     phys_iter_sg_entry_t* sg_list;  // optional list of scatter gather entries to iterate over
29     size_t sg_count;                // number of entries in the scatter gather list
30 } phys_iter_buffer_t;
31 
32 // Used to iterate over contiguous buffer ranges in the physical address space.
33 typedef struct {
34     phys_iter_buffer_t buf;
35 
36     size_t      total_iterated;  // total bytes iterated across all calls for this iterator
37     zx_off_t    offset;          // current offset in the segment (relative to the segment offset)
38                                  // i.e. the total number of bytes iterated for the current segment
39     size_t      max_length;      // max length to be returned by phys_iter_next()
40     uint64_t    page;            // index of page in buf->phys that contains offset
41     uint64_t    last_page;       // last valid page index in buf->phys
42 
43     size_t next_sg_entry_idx;    // next index in the scatter gather list
44     size_t segment_offset;       // offset of the current scatter gather entry, relative to buffer
45                                  // vmo_offset, or zero if no scatter gather list is present.
46     size_t segment_length;       // length of the buffer for the current scatter gather entry,
47                                  // or equal to buf.length if no scatter gather list is present.
48 } phys_iter_t;
49 
50 // Initializes a phys_iter_t for iterating over physical memory.
51 // max_length is the maximum length of a range returned by phys_iter_next()
52 // max_length must be either a positive multiple of PAGE_SIZE, or zero for no limit.
53 void phys_iter_init(phys_iter_t* iter, phys_iter_buffer_t* buf, size_t max_length);
54 
55 // Returns the next physical address and length for the iterator up to size max_length.
56 // Return value is length, or zero if iteration is done.
57 size_t phys_iter_next(phys_iter_t* iter, zx_paddr_t* out_paddr);
58 
59 __END_CDECLS;
60