|
|
1.1 ! root 1: /* $Id: stp222x-aspace.c,v 1.1 2009/02/28 16:29:25 fredette Exp $ */ ! 2: ! 3: /* ic/stp222x-aspace.c - address space utilities for emulation of the ! 4: IOMMU of the UPA to SBus interface controller (STP2220) and the UPA ! 5: to PCI interface controller (STP2222): */ ! 6: ! 7: /* ! 8: * Copyright (c) 2009 Matt Fredette ! 9: * All rights reserved. ! 10: * ! 11: * Redistribution and use in source and binary forms, with or without ! 12: * modification, are permitted provided that the following conditions ! 13: * are met: ! 14: * 1. Redistributions of source code must retain the above copyright ! 15: * notice, this list of conditions and the following disclaimer. ! 16: * 2. Redistributions in binary form must reproduce the above copyright ! 17: * notice, this list of conditions and the following disclaimer in the ! 18: * documentation and/or other materials provided with the distribution. ! 19: * 3. All advertising materials mentioning features or use of this software ! 20: * must display the following acknowledgement: ! 21: * This product includes software developed by Matt Fredette. ! 22: * 4. The name of the author may not be used to endorse or promote products ! 23: * derived from this software without specific prior written permission. ! 24: * ! 25: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR ! 26: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED ! 27: * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE ! 28: * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, ! 29: * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ! 30: * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR ! 31: * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ! 32: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, ! 33: * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ! 34: * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ! 35: * POSSIBILITY OF SUCH DAMAGE. ! 36: */ ! 37: ! 38: #include <tme/common.h> ! 39: _TME_RCSID("$Id: stp222x-aspace.c,v 1.1 2009/02/28 16:29:25 fredette Exp $"); ! 40: ! 41: /* includes: */ ! 42: #include "stp222x-impl.h" ! 43: ! 44: /* this searches an address space: */ ! 45: tme_uint32_t ! 46: tme_stp222x_aspace_search(const struct tme_stp222x_aspace *aspace, ! 47: tme_bus_addr64_t address) ! 48: { ! 49: ! 50: /* if this is a 32-bit address: */ ! 51: if (__tme_predict_true(address < (((tme_bus_addr64_t) 1) << 32))) { ! 52: return (tme_stp222x_asearch32(aspace->tme_stp222x_aspace_aranges, ! 53: aspace->tme_stp222x_aspace_arange32_count, ! 54: address)); ! 55: } ! 56: ! 57: /* otherwise, this is a 64-bit address: */ ! 58: return (tme_stp222x_asearch64(aspace->tme_stp222x_aspace_aranges, ! 59: aspace->tme_stp222x_aspace_arange_count, ! 60: address)); ! 61: } ! 62: ! 63: /* this looks up the slave connection for an address in a space, and ! 64: adjusts the address to be slave-relative: */ ! 65: tme_uint32_t ! 66: tme_stp222x_aspace_lookup(const struct tme_stp222x *stp222x, ! 67: unsigned int aspace_i, ! 68: tme_bus_addr64_t *_agent_to_slave_address) ! 69: { ! 70: const struct tme_stp222x_aspace *aspace; ! 71: tme_uint32_t search; ! 72: tme_uint32_t conn_index; ! 73: ! 74: /* get the space: */ ! 75: aspace = &stp222x->tme_stp222x_aspaces[aspace_i]; ! 76: ! 77: /* if this address isn't claimed in the space: */ ! 78: search = tme_stp222x_aspace_search(aspace, *_agent_to_slave_address); ! 79: if (__tme_predict_false(search & TME_STP222X_ASEARCH_MISS)) { ! 80: return (TME_STP222X_CONN_NULL); ! 81: } ! 82: ! 83: /* get the connection index and adjust the address to be ! 84: connection-relative: */ ! 85: conn_index = aspace->tme_stp222x_aspace_aranges[search].tme_stp222x_arange_key; ! 86: assert (conn_index < TME_STP222X_CONN_NULL); ! 87: *_agent_to_slave_address -= aspace->tme_stp222x_aspace_conn_offset[conn_index]; ! 88: return (conn_index); ! 89: } ! 90: ! 91: /* this rebuilds the address spaces: */ ! 92: int ! 93: tme_stp222x_aspaces_rebuild(struct tme_stp222x *stp222x) ! 94: { ! 95: unsigned int aspace_i; ! 96: struct tme_stp222x_aspace *aspace; ! 97: tme_uint32_t conn_index; ! 98: const struct tme_bus_connection *conn_bus; ! 99: const struct tme_bus_connection *conn_bus_other; ! 100: tme_bus_addr32_t conn_offset; ! 101: const struct tme_bus_subregion *subregion; ! 102: tme_bus_addr64_t address_first; ! 103: tme_bus_addr64_t address_last; ! 104: tme_uint32_t search; ! 105: tme_uint32_t arange_count; ! 106: struct tme_stp222x_arange *aranges; ! 107: ! 108: /* loop over the address spaces that apply to this part: */ ! 109: for (aspace_i = 0; aspace_i < TME_STP222X_ASPACE_NULL; aspace_i++) { ! 110: if ((aspace_i == TME_STP2220_ASPACE_SBUS) ! 111: == !TME_STP222X_IS_2220(stp222x)) { ! 112: continue; ! 113: } ! 114: aspace = &stp222x->tme_stp222x_aspaces[aspace_i]; ! 115: ! 116: /* free any existing address ranges: */ ! 117: if (aspace->tme_stp222x_aspace_arange_count != 0) { ! 118: tme_free(aspace->tme_stp222x_aspace_aranges); ! 119: } ! 120: aspace->tme_stp222x_aspace_arange_count = 0; ! 121: aspace->tme_stp222x_aspace_arange32_count = 0; ! 122: ! 123: /* loop over the connections: */ ! 124: for (conn_index = 0; conn_index < TME_STP222X_CONN_NULL; conn_index++) { ! 125: conn_bus = stp222x->tme_stp222x.tme_stp22xx_conns[conn_index].tme_stp22xx_conn_bus; ! 126: if (conn_bus == NULL) { ! 127: continue; ! 128: } ! 129: conn_bus_other = (struct tme_bus_connection *) conn_bus->tme_bus_connection.tme_connection_other; ! 130: ! 131: /* get the offset and subregions for this connection in this ! 132: space: */ ! 133: conn_offset = 0; ! 134: switch (aspace_i) { ! 135: case TME_STP2220_ASPACE_SBUS: ! 136: conn_offset = stp222x->tme_stp2220_conn_offset[conn_index]; ! 137: /* FALLTHROUGH */ ! 138: case TME_STP2222_ASPACE_PCI_MEMORY(0): ! 139: case TME_STP2222_ASPACE_PCI_MEMORY(1): ! 140: subregion = &conn_bus_other->tme_bus_subregions; ! 141: break; ! 142: case TME_STP2222_ASPACE_PCI_IO(0): ! 143: case TME_STP2222_ASPACE_PCI_IO(1): ! 144: abort(); ! 145: default: ! 146: assert (aspace_i == TME_STP2222_ASPACE_PCI_CONFIGURATION); ! 147: abort(); ! 148: } ! 149: ! 150: /* set the offset for this connection in this space: */ ! 151: aspace->tme_stp222x_aspace_conn_offset[conn_index] = conn_offset; ! 152: ! 153: /* loop over the subregions: */ ! 154: for (; subregion != NULL; subregion = subregion->tme_bus_subregion_next) { ! 155: ! 156: /* get the addresses for this subregion: */ ! 157: address_first = conn_offset + subregion->tme_bus_subregion_address_first; ! 158: address_last = conn_offset + subregion->tme_bus_subregion_address_last; ! 159: assert (address_first <= address_last); ! 160: ! 161: /* if this first address is already claimed in the space: */ ! 162: search = tme_stp222x_aspace_search(aspace, address_first); ! 163: if ((search & TME_STP222X_ASEARCH_MISS) == 0) { ! 164: return (-1); ! 165: } ! 166: search &= ~TME_STP222X_ASEARCH_MISS; ! 167: ! 168: /* grow the address ranges: */ ! 169: arange_count = ++aspace->tme_stp222x_aspace_arange_count; ! 170: aranges ! 171: = (arange_count == 1 ! 172: ? tme_new(struct tme_stp222x_arange, 1) ! 173: : tme_renew(struct tme_stp222x_arange, ! 174: aspace->tme_stp222x_aspace_aranges, ! 175: arange_count)); ! 176: aspace->tme_stp222x_aspace_aranges = aranges; ! 177: ! 178: /* if there are later address ranges: */ ! 179: if ((search + 1) < arange_count) { ! 180: ! 181: /* if an address after the first address is already claimed ! 182: in the space: */ ! 183: if (address_last >= aranges[search].tme_stp222x_arange_first) { ! 184: return (-1); ! 185: } ! 186: ! 187: /* move down all of the other address ranges: */ ! 188: memmove(aranges + search + 1, ! 189: aranges + search, ! 190: (sizeof(aranges[0]) ! 191: * (arange_count ! 192: - (search + 1)))); ! 193: } ! 194: ! 195: /* fill this address range: */ ! 196: aranges[search].tme_stp222x_arange_first = address_first; ! 197: aranges[search].tme_stp222x_arange_size_m1 = address_last - address_first; ! 198: aranges[search].tme_stp222x_arange_key = conn_index; ! 199: ! 200: /* if this is a 32-bit address range, update the count: */ ! 201: if (address_first == (tme_uint32_t) address_first) { ! 202: assert (address_last == (tme_uint32_t) address_last); ! 203: aspace->tme_stp222x_aspace_arange32_count++; ! 204: } ! 205: } ! 206: } ! 207: } ! 208: ! 209: return (0); ! 210: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.