|
|
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.