1 /* $Id: stp22xx-impl.h,v 1.2 2009/08/29 21:17:06 fredette Exp $ */
2 
3 /* ic/stp22xx/stp22xx-impl.h - implementation header file for STP2200,
4    STP2202, STP2220, and STP2222 emulation: */
5 
6 /*
7  * Copyright (c) 2009 Matt Fredette
8  * All rights reserved.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  * 3. All advertising materials mentioning features or use of this software
19  *    must display the following acknowledgement:
20  *      This product includes software developed by Matt Fredette.
21  * 4. The name of the author may not be used to endorse or promote products
22  *    derived from this software without specific prior written permission.
23  *
24  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
25  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
27  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
28  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
30  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
32  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
33  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34  * POSSIBILITY OF SUCH DAMAGE.
35  */
36 
37 #ifndef _STP22XX_IMPL_H
38 #define _STP22XX_IMPL_H
39 
40 #include <tme/common.h>
41 _TME_RCSID("$Id: stp22xx-impl.h,v 1.2 2009/08/29 21:17:06 fredette Exp $");
42 
43 /* includes: */
44 #include <tme/completion.h>
45 #include <tme/bus/upa.h>
46 
47 /* macros: */
48 
49 /* this macro wraps code used during the transition to the new bus
50    interface.  the new bus interface will remove everything from
51    struct tme_bus_tlb starting with the tme_bus_tlb_cycles_ok member
52    until the end.  this will remove all slow cycle information from a
53    TLB, so TLB filling will only give fast read and write information.
54 
55    every bus connection will then have a slow cycle function.  when a
56    master needs to do a slow cycle, through its bus connection it will
57    arbitrate for the bus and then start its cycle.  the bus
58    implementation will steer the cycle towards the slave, which may be
59    across a bridge and over another bus, etc.  slow bus cycles will
60    then follow the actual path from master to slave, with bus
61    implementations ordering bus access and cycles as needed.
62 
63    this seems better than the old interface, where masters called
64    directly into slaves through function pointers in a TLB.  in the
65    old interface, buses couldn't enforce any ordering, because they
66    weren't involved.  this created the risk that a master in the
67    middle of running a bus cycle could be called as a slave over the
68    same bus connection.  real devices never have to face that, and
69    without eliminating that here, turning on preemptive threading
70    seems impossible.
71 
72    the new cycle function in a bus connection will take the bus
73    connection, the struct tme_bus_cycle *, a struct tme_completion *,
74    and a pointer to a mask of cycle types that can be done fast.  as
75    the slow bus cycle makes its way from master to slave, if any point
76    along that path can't allow fast reads or writes, those bits are
77    cleared from the mask.  when the slow cycle completes, if the
78    master finds that any cycles can be done fast again, it may choose
79    to fill a TLB entry again to get the new fast cycle information.
80    this frees slaves from having to track filled TLBs that weren't
81    filled with any fast cycle information, just so they can be
82    invalidated when addresses become fast-capable to make sure that
83    masters refill them.
84 
85    eventually, all of the code wrapped by this macro will be
86    removed: */
87 #define TME_STP22XX_BUS_TRANSITION		(TRUE)
88 
89 /* the maximum number of completions: */
90 #define TME_STP22XX_COMPLETIONS_MAX		(2)
91 
92 /* the maximum number of delayed completions: */
93 #define TME_STP22XX_COMPLETIONS_DELAYED_MAX	(2)
94 
95 /* condition states: */
96 #define TME_STP22XX_COND_STATE_IDLE		(0)
97 #define TME_STP22XX_COND_STATE_RUNNING		(1)
98 #define TME_STP22XX_COND_STATE_WAITING		(2)
99 #define TME_STP22XX_COND_STATE_NOTIFIED		(3)
100 
101 /* types: */
102 struct tme_stp22xx;
103 
104 /* a completion handler: */
105 typedef void (*_tme_stp22xx_completion_handler_t) _TME_P((struct tme_stp22xx *, struct tme_completion *, void *));
106 
107 /* a condition: */
108 struct tme_stp22xx_cond {
109   int tme_stp22xx_cond_state;
110   tme_cond_t tme_stp22xx_cond_cond;
111 };
112 
113 /* a connection: */
114 union tme_stp22xx_conn {
115   struct tme_bus_connection *tme_stp22xx_conn_bus;
116   struct tme_upa_bus_connection *tme_stp22xx_conn_upa;
117 };
118 
119 /* the device: */
120 struct tme_stp22xx {
121 
122   /* backpointer to the device's element: */
123   struct tme_element *tme_stp22xx_element;
124 
125   /* the mutex protecting the device: */
126   tme_mutex_t tme_stp22xx_mutex;
127 
128   /* the size of the part-specific structure: */
129   unsigned long tme_stp22xx_sizeof;
130 
131   /* this is nonzero if the run function is running: */
132   int tme_stp22xx_running;
133 
134   /* the run function: */
135   void (*tme_stp22xx_run) _TME_P((struct tme_stp22xx *));
136 
137   /* our completions: */
138   struct tme_completion tme_stp22xx_completions[TME_STP22XX_COMPLETIONS_MAX];
139   _tme_stp22xx_completion_handler_t tme_stp22xx_completion_handlers[TME_STP22XX_COMPLETIONS_MAX];
140   void * tme_stp22xx_completion_args[TME_STP22XX_COMPLETIONS_MAX];
141 
142   /* any delayed completions: */
143   /* NB: this array is always NULL-terminated: */
144   struct tme_completion *tme_stp22xx_completions_delayed[TME_STP22XX_COMPLETIONS_DELAYED_MAX + 1];
145 
146   /* the undefined connection index: */
147   tme_uint32_t tme_stp22xx_conn_index_null;
148 
149   /* any pending master connection index: */
150   tme_uint32_t tme_stp22xx_master_conn_index_pending;
151 
152   /* any current master connection index and its completion: */
153   tme_uint32_t tme_stp22xx_master_conn_index;
154   struct tme_completion **tme_stp22xx_master_completion;
155 
156 #if TME_STP22XX_BUS_TRANSITION
157   /* the token for filling TLB entries for slave cycles: */
158   struct tme_token tme_stp22xx_slave_cycle_tlb_token;
159 #endif /* TME_STP22XX_BUS_TRANSITION */
160 
161   /* any current slave connection: */
162   struct tme_bus_connection *tme_stp22xx_slave_conn_bus;
163 
164   /* the connections: */
165   /* NB: this must be the last member of this structure; the
166      part-specific structure allocates enough space for its real
167      size: */
168   union tme_stp22xx_conn tme_stp22xx_conns[1];
169 };
170 
171 /* prototypes: */
172 
173 /* this busies a generic bus connection: */
174 struct tme_bus_connection *tme_stp22xx_busy_bus _TME_P((struct tme_stp22xx *, tme_uint32_t));
175 
176 /* this unbusies a generic bus connection: */
177 void tme_stp22xx_unbusy_bus _TME_P((struct tme_stp22xx *, struct tme_bus_connection *));
178 
179 /* this busies a slave generic bus connection: */
180 struct tme_bus_connection *tme_stp22xx_slave_busy_bus _TME_P((struct tme_stp22xx *, tme_uint32_t));
181 
182 /* this unbusies a slave generic bus connection: */
183 void tme_stp22xx_slave_unbusy _TME_P((struct tme_stp22xx *));
184 
185 /* this enters: */
186 struct tme_stp22xx *tme_stp22xx_enter _TME_P((struct tme_stp22xx *));
187 
188 /* this enters as the bus master: */
189 struct tme_stp22xx *tme_stp22xx_enter_master _TME_P((struct tme_bus_connection *));
190 
191 /* this leaves: */
192 void tme_stp22xx_leave _TME_P((struct tme_stp22xx *));
193 
194 /* this waits on a condition, with an optional sleep time: */
195 void tme_stp22xx_cond_sleep_yield _TME_P((struct tme_stp22xx *, struct tme_stp22xx_cond *, const struct timeval *));
196 
197 /* this validates a completion: */
198 void tme_stp22xx_completion_validate _TME_P((struct tme_stp22xx *, struct tme_completion *));
199 
200 /* this allocates a completion: */
201 struct tme_completion *tme_stp22xx_completion_alloc _TME_P((struct tme_stp22xx *, _tme_stp22xx_completion_handler_t, void *));
202 
203 /* this calls out a bus signal to a connection: */
204 void tme_stp22xx_callout_signal _TME_P((struct tme_stp22xx *, tme_uint32_t, unsigned int, _tme_stp22xx_completion_handler_t));
205 
206 /* this completes a bus grant: */
207 void tme_stp22xx_complete_bg _TME_P((struct tme_stp22xx *, struct tme_completion *, void *));
208 
209 /* this completes a bus operation between master and slave: */
210 void tme_stp22xx_complete_master _TME_P((struct tme_stp22xx *, struct tme_completion *, void *));
211 
212 /* this is a no-op completion: */
213 void tme_stp22xx_complete_nop _TME_P((struct tme_stp22xx *, struct tme_completion *, void *));
214 
215 /* this runs a slave bus cycle: */
216 void tme_stp22xx_slave_cycle _TME_P((struct tme_bus_connection *, tme_uint32_t, struct tme_bus_cycle *,	tme_uint32_t *,	struct tme_completion **));
217 
218 /* this fills a TLB entry: */
219 void tme_stp22xx_tlb_fill _TME_P((struct tme_bus_connection *, struct tme_bus_tlb *, tme_uint32_t, tme_bus_addr64_t, unsigned int));
220 
221 /* this adds a TLB set: */
222 void tme_stp22xx_tlb_set_add _TME_P((struct tme_bus_connection *, struct tme_bus_tlb_set_info *, struct tme_completion *));
223 
224 #if TME_STP22XX_BUS_TRANSITION
225 
226 /* this is the bus TLB set add transition glue: */
227 int tme_stp22xx_tlb_set_add_transition _TME_P((struct tme_bus_connection *, struct tme_bus_tlb_set_info *));
228 #define tme_stp22xx_tlb_set_add tme_stp22xx_tlb_set_add_transition
229 
230 #endif /* TME_STP22XX_BUS_TRANSITION */
231 
232 /* this notifies a condition: */
233 void tme_stp22xx_cond_notify _TME_P((struct tme_stp22xx_cond *));
234 
235 /* this initializes a condition: */
236 void tme_stp22xx_cond_init _TME_P((struct tme_stp22xx_cond *));
237 
238 /* this initializes an stp22xx: */
239 void tme_stp22xx_init _TME_P((struct tme_stp22xx *, unsigned long, tme_uint32_t));
240 
241 #endif /* !_STP22XX_IMPL_H */
242