|
|
1.1 root 1: #! /bin/sh
2:
3: # $Id: bus-device-auto.sh,v 1.1 2004/03/28 23:38:28 fredette Exp $
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! */
51: _TME_RCSID("\$Id: bus-device-auto.sh,v 1.1 2004/03/28 23:38:28 fredette Exp $");
52: EOF
53:
54: if $header; then :; else
55: cat <<EOF
56:
57: /* this indexes an initiator bus router array for a device with a port size
58: of 8 * (2 ^ siz_lg2) bits: */
59: #define TME_BUS_ROUTER_INIT_INDEX(siz_lg2, cycle_size, address) \\
60: ((( \\
61: /* by the maximum cycle size: */ \\
62: ((cycle_size) - 1) \\
63: \\
64: /* by the address alignment: */ \\
65: << siz_lg2) \\
66: + ((address) & ((1 << (siz_lg2)) - 1))) \\
67: \\
68: /* factor in the size of the generic bus router array: */ \\
69: * TME_BUS_ROUTER_SIZE(siz_lg2))
70:
71: /* this gives the number of entries that must be in a generic bus
72: router array for a device with a bus size of 8 * (2 ^ siz_lg2)
73: bits: */
74: #define TME_BUS_ROUTER_INIT_SIZE(siz_lg2) \\
75: TME_BUS_ROUTER_INIT_INDEX(siz_lg2, (1 << (siz_lg2)) + 1, 0)
76:
77: EOF
78: fi
79:
80: # permute over initiator bus port width:
81: #
82: i_width=8
83: while test ${i_width} != 32; do
84: i_width=`expr ${i_width} \* 2`
85:
86: # permute over initiator endianness:
87: #
88: for endian in b l; do
89: if test ${endian} = b; then endian_what=big; else endian_what=little; fi
90:
91: # start the array:
92: #
93: echo ""
94: echo "/* the ${i_width}-bit ${endian_what}-endian bus master bus router: */"
95: what="const tme_bus_lane_t tme_bus_device_router_${i_width}e${endian}"
96: if $header; then
97: echo "extern ${what}[];"
98: continue
99: fi
100: echo "${what}[TME_BUS_ROUTER_INIT_SIZE(TME_BUS${i_width}_LOG2)] = {"
101:
102: # permute over initiator maximum cycle size:
103: #
104: i_size=0
105: while test `expr ${i_size} \< ${i_width}` = 1; do
106: i_size=`expr ${i_size} + 8`
107:
108: # permute over initiator address offset:
109: #
110: i_offset=0
111: while test `expr ${i_offset} \< ${i_width}` = 1; do
112:
113: # calculate the initiator least and greatest lanes:
114: #
115: placeholder=false
116: if test ${endian} = b; then
117: i_lane_greatest=`expr -8 + ${i_width} - ${i_offset}`
118: i_lane_least=`expr 8 + ${i_lane_greatest} - ${i_size}`
119: if test `expr ${i_lane_least} \< 0` = 1; then
120: placeholder=true
121: fi
122: else
123: i_lane_least=$i_offset
124: i_lane_greatest=`expr -8 + ${i_offset} + ${i_size}`
125: if test `expr ${i_lane_greatest} \>= ${i_width}` = 1; then
126: placeholder=true
127: fi
128: fi
129:
130: # permute over responder bus port width:
131: #
132: r_width=4
133: while test `expr ${r_width} \< ${i_width}` = 1; do
134: r_width=`expr ${r_width} \* 2`
135:
136: # permute over responder bus port least lane:
137: #
138: r_lane_least=0
139: while test `expr ${r_lane_least} \< ${i_width}` = 1; do
140: r_lane_greatest=`expr -8 + ${r_lane_least} + ${r_width}`
141:
142: # emit the initiator information:
143: #
144: echo ""
145: echo " /* initiator maximum cycle size: ${i_size} bits"
146: echo " initiator address offset: ${i_offset} bits"
147: if $placeholder; then
148: echo " (a ${i_width}-bit initiator cannot request ${i_size} bits at an ${i_offset}-bit offset - this is an array placeholder)"
149: fi
150:
151: # emit the responder information:
152: #
153: echo " responder bus port size: ${r_width} bits"
154: echo -n " responder port least lane: D"`expr ${r_lane_least} + 7`"-D${r_lane_least}"
155:
156: # if the responder bus port greatest lane is
157: # greater than the initiator bus port width,
158: # part of the responder's port is outside of
159: # the initiator's port:
160: #
161: if test `expr ${r_lane_greatest} \>= ${i_width}` = 1; then
162: echo ""
163: echo -n " (responder port not correctly positioned for this initiator)"
164: fi
165: echo ": */"
166:
167: # permute over the lanes:
168: #
169: lane=0
170: if test ${endian} = b; then
171: route=`expr ${i_size} / 8`
172: route_increment=-1
173: else
174: route=-1
175: route_increment=1
176: fi
177: while test `expr ${lane} \< ${i_width}` = 1; do
178: echo -n " /* D"`expr ${lane} + 7`"-D${lane} */ "
179:
180: # see if this lane is on in the responder:
181: #
182: if test `expr ${lane} \>= ${r_lane_least}` = 1 \
183: && test `expr ${lane} \<= ${r_lane_greatest}` = 1; then
184: r_lane_on=true
185: else
186: r_lane_on=false
187: fi
188:
189: # see if this lane is on in the initiator:
190: #
191: if test `expr ${lane} \>= ${i_lane_least}` = 1 \
192: && test `expr ${lane} \<= ${i_lane_greatest}` = 1; then
193: i_lane_on=true
194: route=`expr ${route} + ${route_increment}`
195: else
196: i_lane_on=false
197: fi
198:
199: # if this is a placeholder entry:
200: #
201: if $placeholder; then
202: echo -n "TME_BUS_LANE_ABORT"
203:
204: # otherwise, this is a real entry:
205: #
206: else
207: if $i_lane_on; then
208: echo -n "TME_BUS_LANE_ROUTE(${route})"
209: if $r_lane_on; then :; else
210: echo -n " | TME_BUS_LANE_WARN"
211: fi
212: else
213: echo -n "TME_BUS_LANE_UNDEF"
214: fi
215: fi
216:
217: echo ","
218: lane=`expr ${lane} + 8`
219: done
220:
221: r_lane_least=`expr ${r_lane_least} + 8`
222: done
223: done
224:
225: i_offset=`expr ${i_offset} + 8`
226: done
227: done
228:
229: # finish the array:
230: #
231: echo "};"
232: done
233:
234: # permute over read/write:
235: #
236: for name in read write; do
237: capname=`echo $name | tr a-z A-Z`
238: if test $name = read; then
239: naming="reading"
240: from="from"
241: constbuffer=""
242: else
243: naming="writing"
244: from="to"
245: constbuffer="const "
246: fi
247:
248: echo ""
249: echo "/* the ${i_width}-bit bus master DMA ${name} function: */"
250: if $header; then
251: echo "int tme_bus_device_dma_${name}_${i_width} _TME_P((struct tme_bus_device *,"
252: echo " tme_bus_addr_t,"
253: echo " tme_bus_addr_t,"
254: echo " ${constbuffer}tme_uint8_t *,"
255: echo " unsigned int));"
256: continue
257: fi
258: echo "int"
259: echo "tme_bus_device_dma_${name}_${i_width}(struct tme_bus_device *bus_device,"
260: echo " tme_bus_addr_t address_init,"
261: echo " tme_bus_addr_t size,"
262: echo " ${constbuffer}tme_uint8_t *buffer,"
263: echo " unsigned int locks)"
264: echo "{"
265: echo " struct tme_bus_tlb *tlb, tlb_local;"
266: echo " struct tme_bus_connection *conn_bus;"
267: echo " tme_bus_addr_t count_minus_one, count;"
268: echo " struct tme_bus_cycle cycle;"
269: echo " tme_bus_addr_t address_resp;"
270: echo " tme_bus_addr_t tlb_addr_last;"
271: echo " int shift;"
272: echo " int err;"
273: echo ""
274: echo " /* assume no error: */"
275: echo " err = TME_OK;"
276: echo ""
277: echo " /* loop while we have more bytes to ${name}: */"
278: echo " for (; err == TME_OK && size > 0; ) {"
279: echo ""
280: echo " /* hash this address into a TLB entry: */"
281: echo " tlb = (*bus_device->tme_bus_device_tlb_hash)"
282: echo " (bus_device,"
283: echo " address_init,"
284: echo " TME_BUS_CYCLE_${capname});"
285: echo ""
286: echo " /* if this TLB entry doesn't cover this address, or if it doesn't"
287: echo " allow ${naming}, reload it: */"
288: echo " tlb_addr_last = TME_ATOMIC_READ(tme_bus_addr_t, tlb->tme_bus_tlb_addr_last);"
289: echo " if (address_init < TME_ATOMIC_READ(tme_bus_addr_t, tlb->tme_bus_tlb_addr_first)"
290: echo " || address_init > tlb_addr_last"
291: echo " || (tlb->tme_bus_tlb_emulator_off_${name} == TME_EMULATOR_OFF_UNDEF"
292: echo " && !(tlb->tme_bus_tlb_cycles_ok & TME_BUS_CYCLE_${capname}))) {"
293: echo ""
294: echo " /* reserve this TLB entry: */"
295: echo " tme_bus_tlb_reserve(tlb, &tlb_local);"
296: echo " tlb = &tlb_local;"
297: echo ""
298: echo " /* get our bus connection: */"
299: echo " conn_bus = TME_ATOMIC_READ(struct tme_bus_connection *,"
300: echo " bus_device->tme_bus_device_connection);"
301: echo ""
302: echo " /* unlock the device: */"
303: echo " (*bus_device->tme_bus_device_unlock)(bus_device, locks);"
304: echo ""
305: echo " /* reload the TLB entry: */"
306: echo " err = (*conn_bus->tme_bus_tlb_fill)"
307: echo " (conn_bus,"
308: echo " tlb,"
309: echo " address_init,"
310: echo " TME_BUS_CYCLE_${capname});"
311: echo ""
312: echo " /* lock the device: */"
313: echo " (*bus_device->tme_bus_device_lock)(bus_device, locks);"
314: echo ""
315: echo " /* return if we couldn't fill the TLB entry: */"
316: echo " if (err != TME_OK) {"
317: echo " return (err);"
318: echo " }"
319: echo ""
320: echo " /* the TLB entry must cover this address and allow ${naming}: */"
321: echo " tlb_addr_last = TME_ATOMIC_READ(tme_bus_addr_t, tlb->tme_bus_tlb_addr_last);"
322: echo " assert (address_init >= TME_ATOMIC_READ(tme_bus_addr_t, tlb->tme_bus_tlb_addr_first)"
323: echo " && address_init <= tlb_addr_last"
324: echo " && (tlb->tme_bus_tlb_emulator_off_${name} != TME_EMULATOR_OFF_UNDEF"
325: echo " || (tlb->tme_bus_tlb_cycles_ok & TME_BUS_CYCLE_${capname})));"
326: echo ""
327: echo " /* store the TLB entry: */"
328: echo " tme_bus_tlb_back(tlb);"
329: echo " }"
330: echo ""
331: echo " /* if this TLB entry allows fast ${naming}: */"
332: echo " if (tlb->tme_bus_tlb_emulator_off_${name} != TME_EMULATOR_OFF_UNDEF) {"
333: echo ""
334: echo " /* see how many bytes we can fast ${name} ${from} this TLB entry,"
335: echo " starting at this address: */"
336: echo " count_minus_one = (tlb_addr_last - address_init);"
337: echo ""
338: echo " /* ${name} that many bytes or size bytes, whichever is smaller: */"
339: echo " count_minus_one = TME_MIN(count_minus_one,"
340: echo " (size - 1));"
341: echo " count = count_minus_one + 1;"
342: echo " assert (count != 0);"
343: echo ""
344: echo " /* do the fast ${name}: */"
345: if test ${name} = read; then
346: echo " tme_memory_sequence_rdlock(tlb->tme_bus_tlb_rwlock);"
347: echo " memcpy(buffer,"
348: echo " (tlb->tme_bus_tlb_emulator_off_${name} + address_init), "
349: echo " count);"
350: else
351: echo " tme_memory_sequence_wrlock(tlb->tme_bus_tlb_rwlock);"
352: echo " memcpy((tlb->tme_bus_tlb_emulator_off_${name} + address_init), "
353: echo " buffer,"
354: echo " count);"
355: fi
356: echo " tme_memory_sequence_unlock(tlb->tme_bus_tlb_rwlock);"
357: echo " }"
358: echo ""
359: echo " /* otherwise, we have to do a slow ${name}: */"
360: echo " else {"
361: echo ""
362: echo " /* get the size of this bus cycle: */"
363: echo " count = (1 << TME_BUS${i_width}_LOG2);"
364: echo " count -= (address_init & (count - 1));"
365: echo " count = TME_MIN(count, size);"
366: echo ""
367: echo " /* fill the cycle structure: */"
368: echo " cycle.tme_bus_cycle_type = TME_BUS_CYCLE_${capname};"
369: echo " cycle.tme_bus_cycle_size = count;"
370: echo " cycle.tme_bus_cycle_buffer = (tme_uint8_t *) buffer; /* XXX this breaks const */"
371: echo " cycle.tme_bus_cycle_buffer_increment = 1;"
372: echo " cycle.tme_bus_cycle_lane_routing"
373: echo " = (bus_device->tme_bus_device_router"
374: echo " + TME_BUS_ROUTER_INIT_INDEX(TME_BUS${i_width}_LOG2, count, address_init));"
375: echo ""
376: echo " /* XXX this should come from a socket configuration: */"
377: echo " cycle.tme_bus_cycle_port = TME_BUS_CYCLE_PORT(0, TME_BUS${i_width}_LOG2);"
378: echo ""
379: echo " /* form the physical address for the bus cycle handler: */"
380: echo " address_resp = tlb->tme_bus_tlb_addr_offset + address_init;"
381: echo " shift = tlb->tme_bus_tlb_addr_shift;"
382: echo " if (shift < 0) {"
383: echo " address_resp <<= (0 - shift);"
384: echo " }"
385: echo " else if (shift > 0) {"
386: echo " address_resp >>= shift;"
387: echo " }"
388: echo " cycle.tme_bus_cycle_address = address_resp;"
389: echo ""
390: echo " /* unlock the device: */"
391: echo " (*bus_device->tme_bus_device_unlock)(bus_device, locks);"
392: echo ""
393: echo " /* run the bus cycle: */"
394: echo " err = (*tlb->tme_bus_tlb_cycle)"
395: echo " (tlb->tme_bus_tlb_cycle_private, &cycle);"
396: echo ""
397: echo " /* we don't support deadlocking: */"
398: echo " if (err == TME_EDEADLK) {"
399: echo " abort();"
400: echo " }"
401: echo ""
402: echo " /* otherwise, any other error might be a bus error: */"
403: echo " else if (err != TME_OK) {"
404: echo " err = tme_bus_tlb_fault(tlb, &cycle, err);"
405: echo " assert (err != TME_OK);"
406: echo " }"
407: echo ""
408: echo " /* lock the device: */"
409: echo " (*bus_device->tme_bus_device_lock)(bus_device, locks);"
410: echo " }"
411: echo ""
412: echo " /* update the address, buffer, and size and continue: */"
413: echo " address_init += count;"
414: echo " buffer += count;"
415: echo " size -= count;"
416: echo " }"
417: echo ""
418: echo " return (err);"
419: echo "}"
420: done
421:
422: done
423:
424: # done:
425: #
426: exit 0
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.