|
|
1.1.1.5 ! root 1: /* $Id: bus-device.c,v 1.10 2009/08/28 01:23:44 fredette Exp $ */ 1.1 root 2: 1.1.1.2 root 3: /* generic/bus-device.c - implementation of a generic bus device support: */ 1.1 root 4: 5: /* 6: * Copyright (c) 2003 Matt Fredette 7: * All rights reserved. 8: * 9: * Redistribution and use in source and binary forms, with or without 10: * modification, are permitted provided that the following conditions 11: * are met: 12: * 1. Redistributions of source code must retain the above copyright 13: * notice, this list of conditions and the following disclaimer. 14: * 2. Redistributions in binary form must reproduce the above copyright 15: * notice, this list of conditions and the following disclaimer in the 16: * documentation and/or other materials provided with the distribution. 17: * 3. All advertising materials mentioning features or use of this software 18: * must display the following acknowledgement: 19: * This product includes software developed by Matt Fredette. 20: * 4. The name of the author may not be used to endorse or promote products 21: * derived from this software without specific prior written permission. 22: * 23: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 24: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 25: * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 26: * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 27: * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 28: * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 29: * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 31: * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 32: * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 33: * POSSIBILITY OF SUCH DAMAGE. 34: */ 35: 36: #include <tme/common.h> 1.1.1.5 ! root 37: _TME_RCSID("$Id: bus-device.c,v 1.10 2009/08/28 01:23:44 fredette Exp $"); 1.1 root 38: 39: /* includes: */ 40: #include <tme/generic/bus-device.h> 41: 1.1.1.3 root 42: /* include the automatically-generated bus-device functions: */ 43: #include "bus-device-auto.c" 44: 1.1.1.5 ! root 45: /* this adds a generic bus TLB set: */ ! 46: int ! 47: tme_bus_device_tlb_set_add(struct tme_bus_device *bus_device, ! 48: unsigned long tlb_count, ! 49: struct tme_bus_tlb *tlb) ! 50: { ! 51: struct tme_bus_tlb_set_info tlb_set_info; ! 52: struct tme_token *token; ! 53: struct tme_bus_connection *conn_bus; ! 54: int rc; ! 55: ! 56: /* make the TLB set information, and allocate a token for each TLB ! 57: entry: */ ! 58: assert (tlb_count > 0); ! 59: memset(&tlb_set_info, 0, sizeof(tlb_set_info)); ! 60: tlb_set_info.tme_bus_tlb_set_info_token0 = tme_new(struct tme_token, tlb_count); ! 61: tlb_set_info.tme_bus_tlb_set_info_token_stride = sizeof(struct tme_token); ! 62: tlb_set_info.tme_bus_tlb_set_info_token_count = tlb_count; ! 63: tlb_set_info.tme_bus_tlb_set_info_bus_context = NULL; ! 64: ! 65: /* connect each TLB entry with its token: */ ! 66: token = tlb_set_info.tme_bus_tlb_set_info_token0; ! 67: do { ! 68: tme_token_init(token); ! 69: tlb->tme_bus_tlb_token = token; ! 70: tlb++; ! 71: token++; ! 72: } while (--tlb_count); ! 73: ! 74: /* get our bus connection: */ ! 75: conn_bus ! 76: = tme_memory_atomic_pointer_read(struct tme_bus_connection *, ! 77: bus_device->tme_bus_device_connection, ! 78: &bus_device->tme_bus_device_connection_rwlock); ! 79: ! 80: /* add the TLB set: */ ! 81: rc ! 82: = ((*conn_bus->tme_bus_tlb_set_add) ! 83: (conn_bus, ! 84: &tlb_set_info)); ! 85: return (rc); ! 86: } ! 87: 1.1 root 88: /* this scores a connection: */ 89: int 90: tme_bus_device_connection_score(struct tme_connection *conn, unsigned int *_score) 91: { 92: struct tme_bus_device *device; 93: struct tme_bus_connection *conn_bus_other_old; 94: struct tme_bus_connection *conn_bus_other_new; 95: 96: /* recover our device: */ 97: device = conn->tme_connection_element->tme_element_private; 98: 99: /* both sides must be generic bus connections: */ 100: assert(conn->tme_connection_type == TME_CONNECTION_BUS_GENERIC); 101: assert(conn->tme_connection_other->tme_connection_type == TME_CONNECTION_BUS_GENERIC); 102: 103: /* a simple bus device can have multiple connections, but they all 104: must be from the same bus. the only way we check that is by 105: comparing elements: */ 1.1.1.4 root 106: conn_bus_other_old 107: = tme_memory_atomic_pointer_read(struct tme_bus_connection *, 108: device->tme_bus_device_connection, 109: &device->tme_bus_device_connection_rwlock); 1.1 root 110: conn_bus_other_new = (struct tme_bus_connection *) conn->tme_connection_other; 111: if (conn_bus_other_old != NULL 112: && (conn_bus_other_old->tme_bus_connection.tme_connection_element 113: != conn_bus_other_new->tme_bus_connection.tme_connection_element)) { 114: *_score = 0; 115: return (TME_OK); 116: } 117: 118: /* otherwise, this is our first connection or another connection to 119: the same element. note that there's no good way to differentiate 120: a connection to a bus from a connection to just another chip, so 121: we always return a nonzero score here: */ 122: *_score = 1; 123: return (TME_OK); 124: } 125: 126: /* this makes a new connection: */ 127: int 128: tme_bus_device_connection_make(struct tme_connection *conn, unsigned int state) 129: { 130: struct tme_bus_device *device; 131: 132: /* recover our device: */ 133: device = conn->tme_connection_element->tme_element_private; 134: 135: /* both sides must be generic bus connections: */ 136: assert(conn->tme_connection_type == TME_CONNECTION_BUS_GENERIC); 137: assert(conn->tme_connection_other->tme_connection_type == TME_CONNECTION_BUS_GENERIC); 138: 139: /* simple bus devices are always set up to answer calls across the 140: connection, so we only have to do work when the connection 141: has gone full, namely taking the other side of the 142: connection: */ 143: if (state == TME_CONNECTION_FULL) { 144: 145: /* save our connection: */ 1.1.1.4 root 146: tme_memory_atomic_pointer_write(struct tme_bus_connection *, 147: device->tme_bus_device_connection, 148: (struct tme_bus_connection *) conn->tme_connection_other, 149: &device->tme_bus_device_connection_rwlock); 1.1 root 150: } 151: 152: return (TME_OK); 153: } 154: 155: /* this breaks a connection: */ 156: int 157: tme_bus_device_connection_break(struct tme_connection *conn, unsigned int state) 158: { 159: abort(); 160: } 161: 162: static int 163: _tme_bus_device_signal(struct tme_bus_connection *conn_bus, unsigned int signal) 164: { 165: struct tme_bus_device *device; 166: device = conn_bus->tme_bus_connection.tme_connection_element->tme_element_private; 167: return ((*device->tme_bus_device_signal)(device, signal)); 168: } 169: 170: static int 171: _tme_bus_device_intack(struct tme_bus_connection *conn_bus, unsigned int signal, int *vector) 172: { 173: struct tme_bus_device *device; 174: device = conn_bus->tme_bus_connection.tme_connection_element->tme_element_private; 175: return ((*device->tme_bus_device_intack)(device, signal, vector)); 176: } 177: 178: static int 179: _tme_bus_device_tlb_fill(struct tme_bus_connection *conn_bus, struct tme_bus_tlb *tlb, 180: tme_bus_addr_t address, unsigned int cycles) 181: { 182: struct tme_bus_device *device; 183: device = conn_bus->tme_bus_connection.tme_connection_element->tme_element_private; 184: return ((*device->tme_bus_device_tlb_fill)(device, tlb, address, cycles)); 185: } 186: 187: /* this makes a new connection side for a simple bus device: */ 188: int 189: tme_bus_device_connections_new(struct tme_element *element, 190: const char * const *args, 191: struct tme_connection **_conns, 192: char **_output) 193: { 194: struct tme_bus_device *device; 195: struct tme_bus_connection *conn_bus; 196: struct tme_connection *conn; 197: 198: /* recover our device: */ 199: device = (struct tme_bus_device *) element->tme_element_private; 200: 201: /* create our side of a generic bus connection: */ 202: conn_bus = tme_new0(struct tme_bus_connection, 1); 203: conn = &conn_bus->tme_bus_connection; 204: 205: /* fill in the generic connection: */ 206: conn->tme_connection_next = *_conns; 207: conn->tme_connection_type = TME_CONNECTION_BUS_GENERIC; 208: conn->tme_connection_score = tme_bus_device_connection_score; 209: conn->tme_connection_make = tme_bus_device_connection_make; 210: conn->tme_connection_break = tme_bus_device_connection_break; 211: 212: /* fill in the generic bus connection: */ 1.1.1.2 root 213: conn_bus->tme_bus_subregions = device->tme_bus_device_subregions; 1.1 root 214: if (device->tme_bus_device_signal != NULL) { 215: conn_bus->tme_bus_signal = _tme_bus_device_signal; 216: } 217: if (device->tme_bus_device_intack != NULL) { 218: conn_bus->tme_bus_intack = _tme_bus_device_intack; 219: } 220: conn_bus->tme_bus_tlb_fill = _tme_bus_device_tlb_fill; 221: 222: /* return the connection side possibility: */ 223: *_conns = conn; 224: return (TME_OK); 225: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.