OpenCores
URL https://opencores.org/ocsvn/test_project/test_project/trunk

Subversion Repositories test_project

[/] [test_project/] [trunk/] [linux_sd_driver/] [include/] [linux/] [scatterlist.h] - Blame information for rev 62

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 62 marcus.erl
#ifndef _LINUX_SCATTERLIST_H
2
#define _LINUX_SCATTERLIST_H
3
 
4
#include <asm/types.h>
5
#include <asm/scatterlist.h>
6
#include <linux/mm.h>
7
#include <linux/string.h>
8
#include <asm/io.h>
9
 
10
/*
11
 * Notes on SG table design.
12
 *
13
 * Architectures must provide an unsigned long page_link field in the
14
 * scatterlist struct. We use that to place the page pointer AND encode
15
 * information about the sg table as well. The two lower bits are reserved
16
 * for this information.
17
 *
18
 * If bit 0 is set, then the page_link contains a pointer to the next sg
19
 * table list. Otherwise the next entry is at sg + 1.
20
 *
21
 * If bit 1 is set, then this sg entry is the last element in a list.
22
 *
23
 * See sg_next().
24
 *
25
 */
26
 
27
#define SG_MAGIC        0x87654321
28
 
29
/*
30
 * We overload the LSB of the page pointer to indicate whether it's
31
 * a valid sg entry, or whether it points to the start of a new scatterlist.
32
 * Those low bits are there for everyone! (thanks mason :-)
33
 */
34
#define sg_is_chain(sg)         ((sg)->page_link & 0x01)
35
#define sg_is_last(sg)          ((sg)->page_link & 0x02)
36
#define sg_chain_ptr(sg)        \
37
        ((struct scatterlist *) ((sg)->page_link & ~0x03))
38
 
39
/**
40
 * sg_assign_page - Assign a given page to an SG entry
41
 * @sg:             SG entry
42
 * @page:           The page
43
 *
44
 * Description:
45
 *   Assign page to sg entry. Also see sg_set_page(), the most commonly used
46
 *   variant.
47
 *
48
 **/
49
static inline void sg_assign_page(struct scatterlist *sg, struct page *page)
50
{
51
        unsigned long page_link = sg->page_link & 0x3;
52
 
53
        /*
54
         * In order for the low bit stealing approach to work, pages
55
         * must be aligned at a 32-bit boundary as a minimum.
56
         */
57
        BUG_ON((unsigned long) page & 0x03);
58
#ifdef CONFIG_DEBUG_SG
59
        BUG_ON(sg->sg_magic != SG_MAGIC);
60
        BUG_ON(sg_is_chain(sg));
61
#endif
62
        sg->page_link = page_link | (unsigned long) page;
63
}
64
 
65
/**
66
 * sg_set_page - Set sg entry to point at given page
67
 * @sg:          SG entry
68
 * @page:        The page
69
 * @len:         Length of data
70
 * @offset:      Offset into page
71
 *
72
 * Description:
73
 *   Use this function to set an sg entry pointing at a page, never assign
74
 *   the page directly. We encode sg table information in the lower bits
75
 *   of the page pointer. See sg_page() for looking up the page belonging
76
 *   to an sg entry.
77
 *
78
 **/
79
static inline void sg_set_page(struct scatterlist *sg, struct page *page,
80
                               unsigned int len, unsigned int offset)
81
{
82
        sg_assign_page(sg, page);
83
        sg->offset = offset;
84
        sg->length = len;
85
}
86
 
87
static inline struct page *sg_page(struct scatterlist *sg)
88
{
89
#ifdef CONFIG_DEBUG_SG
90
        BUG_ON(sg->sg_magic != SG_MAGIC);
91
        BUG_ON(sg_is_chain(sg));
92
#endif
93
        return (struct page *)((sg)->page_link & ~0x3);
94
}
95
 
96
/**
97
 * sg_set_buf - Set sg entry to point at given data
98
 * @sg:          SG entry
99
 * @buf:         Data
100
 * @buflen:      Data length
101
 *
102
 **/
103
static inline void sg_set_buf(struct scatterlist *sg, const void *buf,
104
                              unsigned int buflen)
105
{
106
        sg_set_page(sg, virt_to_page(buf), buflen, offset_in_page(buf));
107
}
108
 
109
/**
110
 * sg_next - return the next scatterlist entry in a list
111
 * @sg:         The current sg entry
112
 *
113
 * Description:
114
 *   Usually the next entry will be @sg@ + 1, but if this sg element is part
115
 *   of a chained scatterlist, it could jump to the start of a new
116
 *   scatterlist array.
117
 *
118
 **/
119
static inline struct scatterlist *sg_next(struct scatterlist *sg)
120
{
121
#ifdef CONFIG_DEBUG_SG
122
        BUG_ON(sg->sg_magic != SG_MAGIC);
123
#endif
124
        if (sg_is_last(sg))
125
                return NULL;
126
 
127
        sg++;
128
        if (unlikely(sg_is_chain(sg)))
129
                sg = sg_chain_ptr(sg);
130
 
131
        return sg;
132
}
133
 
134
/*
135
 * Loop over each sg element, following the pointer to a new list if necessary
136
 */
137
#define for_each_sg(sglist, sg, nr, __i)        \
138
        for (__i = 0, sg = (sglist); __i < (nr); __i++, sg = sg_next(sg))
139
 
140
/**
141
 * sg_last - return the last scatterlist entry in a list
142
 * @sgl:        First entry in the scatterlist
143
 * @nents:      Number of entries in the scatterlist
144
 *
145
 * Description:
146
 *   Should only be used casually, it (currently) scan the entire list
147
 *   to get the last entry.
148
 *
149
 *   Note that the @sgl@ pointer passed in need not be the first one,
150
 *   the important bit is that @nents@ denotes the number of entries that
151
 *   exist from @sgl@.
152
 *
153
 **/
154
static inline struct scatterlist *sg_last(struct scatterlist *sgl,
155
                                          unsigned int nents)
156
{
157
#ifndef ARCH_HAS_SG_CHAIN
158
        struct scatterlist *ret = &sgl[nents - 1];
159
#else
160
        struct scatterlist *sg, *ret = NULL;
161
        unsigned int i;
162
 
163
        for_each_sg(sgl, sg, nents, i)
164
                ret = sg;
165
 
166
#endif
167
#ifdef CONFIG_DEBUG_SG
168
        BUG_ON(sgl[0].sg_magic != SG_MAGIC);
169
        BUG_ON(!sg_is_last(ret));
170
#endif
171
        return ret;
172
}
173
 
174
/**
175
 * sg_chain - Chain two sglists together
176
 * @prv:        First scatterlist
177
 * @prv_nents:  Number of entries in prv
178
 * @sgl:        Second scatterlist
179
 *
180
 * Description:
181
 *   Links @prv@ and @sgl@ together, to form a longer scatterlist.
182
 *
183
 **/
184
static inline void sg_chain(struct scatterlist *prv, unsigned int prv_nents,
185
                            struct scatterlist *sgl)
186
{
187
#ifndef ARCH_HAS_SG_CHAIN
188
        BUG();
189
#endif
190
 
191
        /*
192
         * offset and length are unused for chain entry.  Clear them.
193
         */
194
        prv[prv_nents - 1].offset = 0;
195
        prv[prv_nents - 1].length = 0;
196
 
197
        /*
198
         * Set lowest bit to indicate a link pointer, and make sure to clear
199
         * the termination bit if it happens to be set.
200
         */
201
        prv[prv_nents - 1].page_link = ((unsigned long) sgl | 0x01) & ~0x02;
202
}
203
 
204
/**
205
 * sg_mark_end - Mark the end of the scatterlist
206
 * @sg:          SG entryScatterlist
207
 *
208
 * Description:
209
 *   Marks the passed in sg entry as the termination point for the sg
210
 *   table. A call to sg_next() on this entry will return NULL.
211
 *
212
 **/
213
static inline void sg_mark_end(struct scatterlist *sg)
214
{
215
#ifdef CONFIG_DEBUG_SG
216
        BUG_ON(sg->sg_magic != SG_MAGIC);
217
#endif
218
        /*
219
         * Set termination bit, clear potential chain bit
220
         */
221
        sg->page_link |= 0x02;
222
        sg->page_link &= ~0x01;
223
}
224
 
225
/**
226
 * sg_init_table - Initialize SG table
227
 * @sgl:           The SG table
228
 * @nents:         Number of entries in table
229
 *
230
 * Notes:
231
 *   If this is part of a chained sg table, sg_mark_end() should be
232
 *   used only on the last table part.
233
 *
234
 **/
235
static inline void sg_init_table(struct scatterlist *sgl, unsigned int nents)
236
{
237
        memset(sgl, 0, sizeof(*sgl) * nents);
238
#ifdef CONFIG_DEBUG_SG
239
        {
240
                unsigned int i;
241
                for (i = 0; i < nents; i++)
242
                        sgl[i].sg_magic = SG_MAGIC;
243
        }
244
#endif
245
        sg_mark_end(&sgl[nents - 1]);
246
}
247
 
248
/**
249
 * sg_init_one - Initialize a single entry sg list
250
 * @sg:          SG entry
251
 * @buf:         Virtual address for IO
252
 * @buflen:      IO length
253
 *
254
 * Notes:
255
 *   This should not be used on a single entry that is part of a larger
256
 *   table. Use sg_init_table() for that.
257
 *
258
 **/
259
static inline void sg_init_one(struct scatterlist *sg, const void *buf,
260
                               unsigned int buflen)
261
{
262
        sg_init_table(sg, 1);
263
        sg_set_buf(sg, buf, buflen);
264
}
265
 
266
/**
267
 * sg_phys - Return physical address of an sg entry
268
 * @sg:      SG entry
269
 *
270
 * Description:
271
 *   This calls page_to_phys() on the page in this sg entry, and adds the
272
 *   sg offset. The caller must know that it is legal to call page_to_phys()
273
 *   on the sg page.
274
 *
275
 **/
276
static inline dma_addr_t sg_phys(struct scatterlist *sg)
277
{
278
        return page_to_phys(sg_page(sg)) + sg->offset;
279
}
280
 
281
/**
282
 * sg_virt - Return virtual address of an sg entry
283
 * @sg:      SG entry
284
 *
285
 * Description:
286
 *   This calls page_address() on the page in this sg entry, and adds the
287
 *   sg offset. The caller must know that the sg page has a valid virtual
288
 *   mapping.
289
 *
290
 **/
291
static inline void *sg_virt(struct scatterlist *sg)
292
{
293
        return page_address(sg_page(sg)) + sg->offset;
294
}
295
 
296
#endif /* _LINUX_SCATTERLIST_H */

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.