|
|
1.1 root 1: #! /bin/sh
2:
1.1.1.3 ! root 3: # $Id: bus-device-auto.sh,v 1.3 2009/08/29 17:52:04 fredette Exp $
1.1 root 4:
5: # generic/bus-device-auto.sh - automatically generates C code for
6: # generic bus device support:
7:
8: #
9: # Copyright (c) 2004 Matt Fredette
10: # All rights reserved.
11: #
12: # Redistribution and use in source and binary forms, with or without
13: # modification, are permitted provided that the following conditions
14: # are met:
15: # 1. Redistributions of source code must retain the above copyright
16: # notice, this list of conditions and the following disclaimer.
17: # 2. Redistributions in binary form must reproduce the above copyright
18: # notice, this list of conditions and the following disclaimer in the
19: # documentation and/or other materials provided with the distribution.
20: # 3. All advertising materials mentioning features or use of this software
21: # must display the following acknowledgement:
22: # This product includes software developed by Matt Fredette.
23: # 4. The name of the author may not be used to endorse or promote products
24: # derived from this software without specific prior written permission.
25: #
26: # THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
27: # IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
28: # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
29: # DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
30: # INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
31: # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
32: # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33: # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
34: # STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
35: # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36: # POSSIBILITY OF SUCH DAMAGE.
37: #
38:
39: header=false
40:
41: for option
42: do
43: case $option in
44: --header) header=true ;;
45: esac
46: done
47:
48: PROG=`basename $0`
49: cat <<EOF
50: /* automatically generated by $PROG, do not edit! */
1.1.1.3 ! root 51: _TME_RCSID("\$Id: bus-device-auto.sh,v 1.3 2009/08/29 17:52:04 fredette Exp $");
1.1 root 52: EOF
53:
54: if $header; then :; else
55: cat <<EOF
56:
57: /* this gives the number of entries that must be in a generic bus
58: router array for a device with a bus size of 8 * (2 ^ siz_lg2)
59: bits: */
60: #define TME_BUS_ROUTER_INIT_SIZE(siz_lg2) \\
61: TME_BUS_ROUTER_INIT_INDEX(siz_lg2, (1 << (siz_lg2)) + 1, 0)
62:
63: EOF
64: fi
65:
66: # permute over initiator bus port width:
67: #
68: i_width=8
69: while test ${i_width} != 32; do
70: i_width=`expr ${i_width} \* 2`
71:
72: # permute over initiator endianness:
73: #
74: for endian in b l; do
75: if test ${endian} = b; then endian_what=big; else endian_what=little; fi
76:
77: # start the array:
78: #
79: echo ""
80: echo "/* the ${i_width}-bit ${endian_what}-endian bus master bus router: */"
81: what="const tme_bus_lane_t tme_bus_device_router_${i_width}e${endian}"
82: if $header; then
83: echo "extern ${what}[];"
84: continue
85: fi
86: echo "${what}[TME_BUS_ROUTER_INIT_SIZE(TME_BUS${i_width}_LOG2)] = {"
87:
88: # permute over initiator maximum cycle size:
89: #
90: i_size=0
91: while test `expr ${i_size} \< ${i_width}` = 1; do
92: i_size=`expr ${i_size} + 8`
93:
94: # permute over initiator address offset:
95: #
96: i_offset=0
97: while test `expr ${i_offset} \< ${i_width}` = 1; do
98:
99: # calculate the initiator least and greatest lanes:
100: #
101: placeholder=false
102: if test ${endian} = b; then
103: i_lane_greatest=`expr -8 + ${i_width} - ${i_offset}`
104: i_lane_least=`expr 8 + ${i_lane_greatest} - ${i_size}`
105: if test `expr ${i_lane_least} \< 0` = 1; then
106: placeholder=true
107: fi
108: else
109: i_lane_least=$i_offset
110: i_lane_greatest=`expr -8 + ${i_offset} + ${i_size}`
111: if test `expr ${i_lane_greatest} \>= ${i_width}` = 1; then
112: placeholder=true
113: fi
114: fi
115:
116: # permute over responder bus port width:
117: #
118: r_width=4
119: while test `expr ${r_width} \< ${i_width}` = 1; do
120: r_width=`expr ${r_width} \* 2`
121:
122: # permute over responder bus port least lane:
123: #
124: r_lane_least=0
125: while test `expr ${r_lane_least} \< ${i_width}` = 1; do
126: r_lane_greatest=`expr -8 + ${r_lane_least} + ${r_width}`
127:
128: # emit the initiator information:
129: #
130: echo ""
131: echo " /* initiator maximum cycle size: ${i_size} bits"
132: echo " initiator address offset: ${i_offset} bits"
133: if $placeholder; then
134: echo " (a ${i_width}-bit initiator cannot request ${i_size} bits at an ${i_offset}-bit offset - this is an array placeholder)"
135: fi
136:
137: # emit the responder information:
138: #
139: echo " responder bus port size: ${r_width} bits"
140: echo -n " responder port least lane: D"`expr ${r_lane_least} + 7`"-D${r_lane_least}"
141:
142: # if the responder bus port greatest lane is
143: # greater than the initiator bus port width,
144: # part of the responder's port is outside of
145: # the initiator's port:
146: #
147: if test `expr ${r_lane_greatest} \>= ${i_width}` = 1; then
148: echo ""
149: echo -n " (responder port not correctly positioned for this initiator)"
150: fi
151: echo ": */"
152:
153: # permute over the lanes:
154: #
155: lane=0
156: if test ${endian} = b; then
157: route=`expr ${i_size} / 8`
158: route_increment=-1
159: else
160: route=-1
161: route_increment=1
162: fi
163: while test `expr ${lane} \< ${i_width}` = 1; do
164: echo -n " /* D"`expr ${lane} + 7`"-D${lane} */ "
165:
166: # see if this lane is on in the responder:
167: #
168: if test `expr ${lane} \>= ${r_lane_least}` = 1 \
169: && test `expr ${lane} \<= ${r_lane_greatest}` = 1; then
170: r_lane_on=true
171: else
172: r_lane_on=false
173: fi
174:
175: # see if this lane is on in the initiator:
176: #
177: if test `expr ${lane} \>= ${i_lane_least}` = 1 \
178: && test `expr ${lane} \<= ${i_lane_greatest}` = 1; then
179: i_lane_on=true
180: route=`expr ${route} + ${route_increment}`
181: else
182: i_lane_on=false
183: fi
184:
185: # if this is a placeholder entry:
186: #
187: if $placeholder; then
188: echo -n "TME_BUS_LANE_ABORT"
189:
190: # otherwise, this is a real entry:
191: #
192: else
193: if $i_lane_on; then
194: echo -n "TME_BUS_LANE_ROUTE(${route})"
195: if $r_lane_on; then :; else
196: echo -n " | TME_BUS_LANE_WARN"
197: fi
198: else
199: echo -n "TME_BUS_LANE_UNDEF"
200: fi
201: fi
202:
203: echo ","
204: lane=`expr ${lane} + 8`
205: done
206:
207: r_lane_least=`expr ${r_lane_least} + 8`
208: done
209: done
210:
211: i_offset=`expr ${i_offset} + 8`
212: done
213: done
214:
215: # finish the array:
216: #
217: echo "};"
218: done
219:
220: # permute over read/write:
221: #
222: for name in read write; do
223: capname=`echo $name | tr a-z A-Z`
224: if test $name = read; then
225: naming="reading"
226: from="from"
227: constbuffer=""
228: else
229: naming="writing"
230: from="to"
231: constbuffer="const "
232: fi
233:
234: echo ""
235: echo "/* the ${i_width}-bit bus master DMA ${name} function: */"
236: if $header; then
237: echo "int tme_bus_device_dma_${name}_${i_width} _TME_P((struct tme_bus_device *,"
238: echo " tme_bus_addr_t,"
239: echo " tme_bus_addr_t,"
240: echo " ${constbuffer}tme_uint8_t *,"
241: echo " unsigned int));"
242: continue
243: fi
244: echo "int"
245: echo "tme_bus_device_dma_${name}_${i_width}(struct tme_bus_device *bus_device,"
246: echo " tme_bus_addr_t address_init,"
247: echo " tme_bus_addr_t size,"
248: echo " ${constbuffer}tme_uint8_t *buffer,"
249: echo " unsigned int locks)"
250: echo "{"
251: echo " struct tme_bus_tlb *tlb, tlb_local;"
252: echo " struct tme_bus_connection *conn_bus;"
253: echo " tme_bus_addr_t count_minus_one, count;"
254: echo " struct tme_bus_cycle cycle;"
255: echo " tme_bus_addr_t address_resp;"
256: echo " int shift;"
257: echo " int err;"
258: echo ""
259: echo " /* assume no error: */"
260: echo " err = TME_OK;"
261: echo ""
262: echo " /* loop while we have more bytes to ${name}: */"
263: echo " for (; err == TME_OK && size > 0; ) {"
264: echo ""
265: echo " /* hash this address into a TLB entry: */"
266: echo " tlb = (*bus_device->tme_bus_device_tlb_hash)"
267: echo " (bus_device,"
268: echo " address_init,"
269: echo " TME_BUS_CYCLE_${capname});"
270: echo ""
1.1.1.2 root 271: echo " /* busy this TLB entry: */"
272: echo " tme_bus_tlb_busy(tlb);"
273: echo ""
274: echo " /* if this TLB entry is invalid, doesn't cover this address, or if it doesn't"
1.1 root 275: echo " allow ${naming}, reload it: */"
1.1.1.2 root 276: echo " if (tme_bus_tlb_is_invalid(tlb)"
277: echo " || address_init < tlb->tme_bus_tlb_addr_first"
278: echo " || address_init > tlb->tme_bus_tlb_addr_last"
1.1 root 279: echo " || (tlb->tme_bus_tlb_emulator_off_${name} == TME_EMULATOR_OFF_UNDEF"
280: echo " && !(tlb->tme_bus_tlb_cycles_ok & TME_BUS_CYCLE_${capname}))) {"
281: echo ""
1.1.1.2 root 282: echo " /* unbusy this TLB entry for filling: */"
283: echo " tme_bus_tlb_unbusy_fill(tlb);"
284: echo ""
1.1.1.3 ! root 285: echo " /* pass this TLB's token: */"
! 286: echo " tlb_local.tme_bus_tlb_token = tlb->tme_bus_tlb_token;"
1.1 root 287: echo ""
288: echo " /* get our bus connection: */"
1.1.1.2 root 289: echo " conn_bus = tme_memory_atomic_pointer_read(struct tme_bus_connection *,"
290: echo " bus_device->tme_bus_device_connection,"
291: echo " &bus_device->tme_bus_device_connection_rwlock);"
1.1 root 292: echo ""
293: echo " /* unlock the device: */"
294: echo " (*bus_device->tme_bus_device_unlock)(bus_device, locks);"
295: echo ""
296: echo " /* reload the TLB entry: */"
297: echo " err = (*conn_bus->tme_bus_tlb_fill)"
298: echo " (conn_bus,"
1.1.1.3 ! root 299: echo " &tlb_local,"
1.1 root 300: echo " address_init,"
301: echo " TME_BUS_CYCLE_${capname});"
302: echo ""
303: echo " /* lock the device: */"
304: echo " (*bus_device->tme_bus_device_lock)(bus_device, locks);"
305: echo ""
306: echo " /* return if we couldn't fill the TLB entry: */"
307: echo " if (err != TME_OK) {"
308: echo " return (err);"
309: echo " }"
310: echo ""
311: echo " /* store the TLB entry: */"
1.1.1.3 ! root 312: echo " *tlb = tlb_local;"
1.1.1.2 root 313: echo ""
314: echo " /* loop to check the newly filled TLB entry: */"
315: echo " continue;"
1.1 root 316: echo " }"
317: echo ""
318: echo " /* if this TLB entry allows fast ${naming}: */"
319: echo " if (tlb->tme_bus_tlb_emulator_off_${name} != TME_EMULATOR_OFF_UNDEF) {"
320: echo ""
321: echo " /* see how many bytes we can fast ${name} ${from} this TLB entry,"
322: echo " starting at this address: */"
1.1.1.2 root 323: echo " count_minus_one = (tlb->tme_bus_tlb_addr_last - address_init);"
1.1 root 324: echo ""
325: echo " /* ${name} that many bytes or size bytes, whichever is smaller: */"
326: echo " count_minus_one = TME_MIN(count_minus_one,"
327: echo " (size - 1));"
328: echo " count = count_minus_one + 1;"
329: echo " assert (count != 0);"
330: echo ""
1.1.1.2 root 331: echo " /* do the bus ${name}: */"
332: echo " tme_memory_bus_${name}_buffer((tlb->tme_bus_tlb_emulator_off_${name} + address_init), buffer, count, tlb->tme_bus_tlb_rwlock, sizeof(tme_uint8_t), sizeof(tme_uint${i_width}_t));"
333: echo ""
334: echo " /* unbusy this TLB entry: */"
335: echo " tme_bus_tlb_unbusy(tlb);"
1.1 root 336: echo " }"
337: echo ""
338: echo " /* otherwise, we have to do a slow ${name}: */"
339: echo " else {"
340: echo ""
341: echo " /* get the size of this bus cycle: */"
342: echo " count = (1 << TME_BUS${i_width}_LOG2);"
343: echo " count -= (address_init & (count - 1));"
344: echo " count = TME_MIN(count, size);"
345: echo ""
346: echo " /* fill the cycle structure: */"
347: echo " cycle.tme_bus_cycle_type = TME_BUS_CYCLE_${capname};"
348: echo " cycle.tme_bus_cycle_size = count;"
349: echo " cycle.tme_bus_cycle_buffer = (tme_uint8_t *) buffer; /* XXX this breaks const */"
350: echo " cycle.tme_bus_cycle_buffer_increment = 1;"
351: echo " cycle.tme_bus_cycle_lane_routing"
352: echo " = (bus_device->tme_bus_device_router"
353: echo " + TME_BUS_ROUTER_INIT_INDEX(TME_BUS${i_width}_LOG2, count, address_init));"
354: echo ""
355: echo " /* XXX this should come from a socket configuration: */"
356: echo " cycle.tme_bus_cycle_port = TME_BUS_CYCLE_PORT(0, TME_BUS${i_width}_LOG2);"
357: echo ""
358: echo " /* form the physical address for the bus cycle handler: */"
359: echo " address_resp = tlb->tme_bus_tlb_addr_offset + address_init;"
360: echo " shift = tlb->tme_bus_tlb_addr_shift;"
361: echo " if (shift < 0) {"
362: echo " address_resp <<= (0 - shift);"
363: echo " }"
364: echo " else if (shift > 0) {"
365: echo " address_resp >>= shift;"
366: echo " }"
367: echo " cycle.tme_bus_cycle_address = address_resp;"
368: echo ""
1.1.1.2 root 369: echo " /* unbusy this TLB entry: */"
370: echo " tme_bus_tlb_unbusy(tlb);"
371: echo ""
1.1 root 372: echo " /* unlock the device: */"
373: echo " (*bus_device->tme_bus_device_unlock)(bus_device, locks);"
374: echo ""
375: echo " /* run the bus cycle: */"
376: echo " err = (*tlb->tme_bus_tlb_cycle)"
377: echo " (tlb->tme_bus_tlb_cycle_private, &cycle);"
378: echo ""
1.1.1.2 root 379: echo " /* if the TLB entry was invalidated before the ${name}: */"
380: echo " if (err == EBADF"
381: echo " && tme_bus_tlb_is_invalid(tlb)) {"
382: echo " count = 0;"
1.1 root 383: echo " }"
384: echo ""
385: echo " /* otherwise, any other error might be a bus error: */"
386: echo " else if (err != TME_OK) {"
387: echo " err = tme_bus_tlb_fault(tlb, &cycle, err);"
388: echo " assert (err != TME_OK);"
389: echo " }"
390: echo ""
391: echo " /* lock the device: */"
392: echo " (*bus_device->tme_bus_device_lock)(bus_device, locks);"
393: echo " }"
394: echo ""
395: echo " /* update the address, buffer, and size and continue: */"
396: echo " address_init += count;"
397: echo " buffer += count;"
398: echo " size -= count;"
399: echo " }"
400: echo ""
401: echo " return (err);"
402: echo "}"
403: done
404:
405: done
406:
407: # done:
408: #
409: exit 0
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.