|
|
1.1 root 1: /* $Id: bus-device.c,v 1.5 2003/05/16 21:48:08 fredette Exp $ */
2:
3: /* bus/bus-device.c - implementation of a generic bus device support: */
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>
37: _TME_RCSID("$Id: bus-device.c,v 1.5 2003/05/16 21:48:08 fredette Exp $");
38:
39: /* includes: */
40: #include <tme/generic/bus-device.h>
41:
42: /* this scores a connection: */
43: int
44: tme_bus_device_connection_score(struct tme_connection *conn, unsigned int *_score)
45: {
46: struct tme_bus_device *device;
47: struct tme_bus_connection *conn_bus_other_old;
48: struct tme_bus_connection *conn_bus_other_new;
49:
50: /* recover our device: */
51: device = conn->tme_connection_element->tme_element_private;
52:
53: /* both sides must be generic bus connections: */
54: assert(conn->tme_connection_type == TME_CONNECTION_BUS_GENERIC);
55: assert(conn->tme_connection_other->tme_connection_type == TME_CONNECTION_BUS_GENERIC);
56:
57: /* a simple bus device can have multiple connections, but they all
58: must be from the same bus. the only way we check that is by
59: comparing elements: */
60: conn_bus_other_old = TME_ATOMIC_READ(struct tme_bus_connection *,
61: device->tme_bus_device_connection);
62: conn_bus_other_new = (struct tme_bus_connection *) conn->tme_connection_other;
63: if (conn_bus_other_old != NULL
64: && (conn_bus_other_old->tme_bus_connection.tme_connection_element
65: != conn_bus_other_new->tme_bus_connection.tme_connection_element)) {
66: *_score = 0;
67: return (TME_OK);
68: }
69:
70: /* otherwise, this is our first connection or another connection to
71: the same element. note that there's no good way to differentiate
72: a connection to a bus from a connection to just another chip, so
73: we always return a nonzero score here: */
74: *_score = 1;
75: return (TME_OK);
76: }
77:
78: /* this makes a new connection: */
79: int
80: tme_bus_device_connection_make(struct tme_connection *conn, unsigned int state)
81: {
82: struct tme_bus_device *device;
83:
84: /* recover our device: */
85: device = conn->tme_connection_element->tme_element_private;
86:
87: /* both sides must be generic bus connections: */
88: assert(conn->tme_connection_type == TME_CONNECTION_BUS_GENERIC);
89: assert(conn->tme_connection_other->tme_connection_type == TME_CONNECTION_BUS_GENERIC);
90:
91: /* simple bus devices are always set up to answer calls across the
92: connection, so we only have to do work when the connection
93: has gone full, namely taking the other side of the
94: connection: */
95: if (state == TME_CONNECTION_FULL) {
96:
97: /* save our connection: */
98: TME_ATOMIC_WRITE(struct tme_bus_connection *,
99: device->tme_bus_device_connection,
100: (struct tme_bus_connection *) conn->tme_connection_other);
101: }
102:
103: return (TME_OK);
104: }
105:
106: /* this breaks a connection: */
107: int
108: tme_bus_device_connection_break(struct tme_connection *conn, unsigned int state)
109: {
110: abort();
111: }
112:
113: static int
114: _tme_bus_device_signal(struct tme_bus_connection *conn_bus, unsigned int signal)
115: {
116: struct tme_bus_device *device;
117: device = conn_bus->tme_bus_connection.tme_connection_element->tme_element_private;
118: return ((*device->tme_bus_device_signal)(device, signal));
119: }
120:
121: static int
122: _tme_bus_device_intack(struct tme_bus_connection *conn_bus, unsigned int signal, int *vector)
123: {
124: struct tme_bus_device *device;
125: device = conn_bus->tme_bus_connection.tme_connection_element->tme_element_private;
126: return ((*device->tme_bus_device_intack)(device, signal, vector));
127: }
128:
129: static int
130: _tme_bus_device_tlb_fill(struct tme_bus_connection *conn_bus, struct tme_bus_tlb *tlb,
131: tme_bus_addr_t address, unsigned int cycles)
132: {
133: struct tme_bus_device *device;
134: device = conn_bus->tme_bus_connection.tme_connection_element->tme_element_private;
135: return ((*device->tme_bus_device_tlb_fill)(device, tlb, address, cycles));
136: }
137:
138: /* this makes a new connection side for a simple bus device: */
139: int
140: tme_bus_device_connections_new(struct tme_element *element,
141: const char * const *args,
142: struct tme_connection **_conns,
143: char **_output)
144: {
145: struct tme_bus_device *device;
146: struct tme_bus_connection *conn_bus;
147: struct tme_connection *conn;
148:
149: /* recover our device: */
150: device = (struct tme_bus_device *) element->tme_element_private;
151:
152: /* create our side of a generic bus connection: */
153: conn_bus = tme_new0(struct tme_bus_connection, 1);
154: conn = &conn_bus->tme_bus_connection;
155:
156: /* fill in the generic connection: */
157: conn->tme_connection_next = *_conns;
158: conn->tme_connection_type = TME_CONNECTION_BUS_GENERIC;
159: conn->tme_connection_score = tme_bus_device_connection_score;
160: conn->tme_connection_make = tme_bus_device_connection_make;
161: conn->tme_connection_break = tme_bus_device_connection_break;
162:
163: /* fill in the generic bus connection: */
164: conn_bus->tme_bus_address_last = device->tme_bus_device_address_last;
165: if (device->tme_bus_device_signal != NULL) {
166: conn_bus->tme_bus_signal = _tme_bus_device_signal;
167: }
168: if (device->tme_bus_device_intack != NULL) {
169: conn_bus->tme_bus_intack = _tme_bus_device_intack;
170: }
171: conn_bus->tme_bus_tlb_fill = _tme_bus_device_tlb_fill;
172:
173: /* return the connection side possibility: */
174: *_conns = conn;
175: return (TME_OK);
176: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.