|
Lines 65-99
struct mdioproxy_softc {
Link Here
|
| 65 |
}; |
65 |
}; |
| 66 |
|
66 |
|
| 67 |
/* |
67 |
/* |
| 68 |
* The rendevous data structures and functions allow two device endpoints to |
68 |
* The rendezvous data structures and functions allow two device endpoints to |
| 69 |
* match up, so that the proxy endpoint can be associated with a target |
69 |
* match up, so that the proxy endpoint can be associated with a target |
| 70 |
* endpoint. The proxy has to know the device name of the target that it |
70 |
* endpoint. The proxy has to know the device name of the target that it |
| 71 |
* wants to associate with, for example through a hint. The rendevous code |
71 |
* wants to associate with, for example through a hint. The rendezvous code |
| 72 |
* makes no assumptions about the devices that want to meet. |
72 |
* makes no assumptions about the devices that want to meet. |
| 73 |
*/ |
73 |
*/ |
| 74 |
struct rendevous_entry; |
74 |
struct rendezvous_entry; |
| 75 |
|
75 |
|
| 76 |
enum rendevous_op { |
76 |
enum rendezvous_op { |
| 77 |
RENDEVOUS_ATTACH, |
77 |
RENDEVOUS_ATTACH, |
| 78 |
RENDEVOUS_DETACH |
78 |
RENDEVOUS_DETACH |
| 79 |
}; |
79 |
}; |
| 80 |
|
80 |
|
| 81 |
typedef int (*rendevous_callback_t)(enum rendevous_op, |
81 |
typedef int (*rendezvous_callback_t)(enum rendezvous_op, |
| 82 |
struct rendevous_entry *); |
82 |
struct rendezvous_entry *); |
| 83 |
|
83 |
|
| 84 |
static SLIST_HEAD(rendevoushead, rendevous_entry) rendevoushead = |
84 |
static SLIST_HEAD(rendezvoushead, rendezvous_entry) rendezvoushead = |
| 85 |
SLIST_HEAD_INITIALIZER(rendevoushead); |
85 |
SLIST_HEAD_INITIALIZER(rendezvoushead); |
| 86 |
|
86 |
|
| 87 |
struct rendevous_endpoint { |
87 |
struct rendezvous_endpoint { |
| 88 |
device_t device; |
88 |
device_t device; |
| 89 |
const char *name; |
89 |
const char *name; |
| 90 |
rendevous_callback_t callback; |
90 |
rendezvous_callback_t callback; |
| 91 |
}; |
91 |
}; |
| 92 |
|
92 |
|
| 93 |
struct rendevous_entry { |
93 |
struct rendezvous_entry { |
| 94 |
SLIST_ENTRY(rendevous_entry) entries; |
94 |
SLIST_ENTRY(rendezvous_entry) entries; |
| 95 |
struct rendevous_endpoint proxy; |
95 |
struct rendezvous_endpoint proxy; |
| 96 |
struct rendevous_endpoint target; |
96 |
struct rendezvous_endpoint target; |
| 97 |
}; |
97 |
}; |
| 98 |
|
98 |
|
| 99 |
/* |
99 |
/* |
|
Lines 101-107
struct rendevous_entry {
Link Here
|
| 101 |
* returns an error, undo the attachment. |
101 |
* returns an error, undo the attachment. |
| 102 |
*/ |
102 |
*/ |
| 103 |
static int |
103 |
static int |
| 104 |
rendevous_attach(struct rendevous_entry *e, struct rendevous_endpoint *ep) |
104 |
rendezvous_attach(struct rendezvous_entry *e, struct rendezvous_endpoint *ep) |
| 105 |
{ |
105 |
{ |
| 106 |
int error; |
106 |
int error; |
| 107 |
|
107 |
|
|
Lines 118-144
rendevous_attach(struct rendevous_entry *e, struct rendevous_endpoint *ep)
Link Here
|
| 118 |
} |
118 |
} |
| 119 |
|
119 |
|
| 120 |
/* |
120 |
/* |
| 121 |
* Create an entry for the proxy in the rendevous list. The name parameter |
121 |
* Create an entry for the proxy in the rendezvous list. The name parameter |
| 122 |
* indicates the name of the device that is the target endpoint for this |
122 |
* indicates the name of the device that is the target endpoint for this |
| 123 |
* rendevous. The callback will be invoked as soon as the target is |
123 |
* rendezvous. The callback will be invoked as soon as the target is |
| 124 |
* registered: either immediately if the target registered itself earlier, |
124 |
* registered: either immediately if the target registered itself earlier, |
| 125 |
* or once the target registers. Returns ENXIO if the target has not yet |
125 |
* or once the target registers. Returns ENXIO if the target has not yet |
| 126 |
* registered. |
126 |
* registered. |
| 127 |
*/ |
127 |
*/ |
| 128 |
static int |
128 |
static int |
| 129 |
rendevous_register_proxy(device_t dev, const char *name, |
129 |
rendezvous_register_proxy(device_t dev, const char *name, |
| 130 |
rendevous_callback_t callback) |
130 |
rendezvous_callback_t callback) |
| 131 |
{ |
131 |
{ |
| 132 |
struct rendevous_entry *e; |
132 |
struct rendezvous_entry *e; |
| 133 |
|
133 |
|
| 134 |
KASSERT(callback != NULL, ("callback must be set")); |
134 |
KASSERT(callback != NULL, ("callback must be set")); |
| 135 |
SLIST_FOREACH(e, &rendevoushead, entries) { |
135 |
SLIST_FOREACH(e, &rendezvoushead, entries) { |
| 136 |
if (strcmp(name, e->target.name) == 0) { |
136 |
if (strcmp(name, e->target.name) == 0) { |
| 137 |
/* the target is already attached */ |
137 |
/* the target is already attached */ |
| 138 |
e->proxy.name = device_get_nameunit(dev); |
138 |
e->proxy.name = device_get_nameunit(dev); |
| 139 |
e->proxy.device = dev; |
139 |
e->proxy.device = dev; |
| 140 |
e->proxy.callback = callback; |
140 |
e->proxy.callback = callback; |
| 141 |
return (rendevous_attach(e, &e->proxy)); |
141 |
return (rendezvous_attach(e, &e->proxy)); |
| 142 |
} |
142 |
} |
| 143 |
} |
143 |
} |
| 144 |
e = malloc(sizeof(*e), M_MIIPROXY, M_WAITOK | M_ZERO); |
144 |
e = malloc(sizeof(*e), M_MIIPROXY, M_WAITOK | M_ZERO); |
|
Lines 146-179
rendevous_register_proxy(device_t dev, const char *name,
Link Here
|
| 146 |
e->proxy.device = dev; |
146 |
e->proxy.device = dev; |
| 147 |
e->proxy.callback = callback; |
147 |
e->proxy.callback = callback; |
| 148 |
e->target.name = name; |
148 |
e->target.name = name; |
| 149 |
SLIST_INSERT_HEAD(&rendevoushead, e, entries); |
149 |
SLIST_INSERT_HEAD(&rendezvoushead, e, entries); |
| 150 |
return (ENXIO); |
150 |
return (ENXIO); |
| 151 |
} |
151 |
} |
| 152 |
|
152 |
|
| 153 |
/* |
153 |
/* |
| 154 |
* Create an entry in the rendevous list for the target. |
154 |
* Create an entry in the rendezvous list for the target. |
| 155 |
* Returns ENXIO if the proxy has not yet registered. |
155 |
* Returns ENXIO if the proxy has not yet registered. |
| 156 |
*/ |
156 |
*/ |
| 157 |
static int |
157 |
static int |
| 158 |
rendevous_register_target(device_t dev, rendevous_callback_t callback) |
158 |
rendezvous_register_target(device_t dev, rendezvous_callback_t callback) |
| 159 |
{ |
159 |
{ |
| 160 |
struct rendevous_entry *e; |
160 |
struct rendezvous_entry *e; |
| 161 |
const char *name; |
161 |
const char *name; |
| 162 |
|
162 |
|
| 163 |
KASSERT(callback != NULL, ("callback must be set")); |
163 |
KASSERT(callback != NULL, ("callback must be set")); |
| 164 |
name = device_get_nameunit(dev); |
164 |
name = device_get_nameunit(dev); |
| 165 |
SLIST_FOREACH(e, &rendevoushead, entries) { |
165 |
SLIST_FOREACH(e, &rendezvoushead, entries) { |
| 166 |
if (strcmp(name, e->target.name) == 0) { |
166 |
if (strcmp(name, e->target.name) == 0) { |
| 167 |
e->target.device = dev; |
167 |
e->target.device = dev; |
| 168 |
e->target.callback = callback; |
168 |
e->target.callback = callback; |
| 169 |
return (rendevous_attach(e, &e->target)); |
169 |
return (rendezvous_attach(e, &e->target)); |
| 170 |
} |
170 |
} |
| 171 |
} |
171 |
} |
| 172 |
e = malloc(sizeof(*e), M_MIIPROXY, M_WAITOK | M_ZERO); |
172 |
e = malloc(sizeof(*e), M_MIIPROXY, M_WAITOK | M_ZERO); |
| 173 |
e->target.name = name; |
173 |
e->target.name = name; |
| 174 |
e->target.device = dev; |
174 |
e->target.device = dev; |
| 175 |
e->target.callback = callback; |
175 |
e->target.callback = callback; |
| 176 |
SLIST_INSERT_HEAD(&rendevoushead, e, entries); |
176 |
SLIST_INSERT_HEAD(&rendezvoushead, e, entries); |
| 177 |
return (ENXIO); |
177 |
return (ENXIO); |
| 178 |
} |
178 |
} |
| 179 |
|
179 |
|
|
Lines 181-195
rendevous_register_target(device_t dev, rendevous_callback_t callback)
Link Here
|
| 181 |
* Remove the registration for the proxy. |
181 |
* Remove the registration for the proxy. |
| 182 |
*/ |
182 |
*/ |
| 183 |
static int |
183 |
static int |
| 184 |
rendevous_unregister_proxy(device_t dev) |
184 |
rendezvous_unregister_proxy(device_t dev) |
| 185 |
{ |
185 |
{ |
| 186 |
struct rendevous_entry *e; |
186 |
struct rendezvous_entry *e; |
| 187 |
int error = 0; |
187 |
int error = 0; |
| 188 |
|
188 |
|
| 189 |
SLIST_FOREACH(e, &rendevoushead, entries) { |
189 |
SLIST_FOREACH(e, &rendezvoushead, entries) { |
| 190 |
if (e->proxy.device == dev) { |
190 |
if (e->proxy.device == dev) { |
| 191 |
if (e->target.device == NULL) { |
191 |
if (e->target.device == NULL) { |
| 192 |
SLIST_REMOVE(&rendevoushead, e, rendevous_entry, entries); |
192 |
SLIST_REMOVE(&rendezvoushead, e, rendezvous_entry, entries); |
| 193 |
free(e, M_MIIPROXY); |
193 |
free(e, M_MIIPROXY); |
| 194 |
return (0); |
194 |
return (0); |
| 195 |
} else { |
195 |
} else { |
|
Lines 208-222
rendevous_unregister_proxy(device_t dev)
Link Here
|
| 208 |
* Remove the registration for the target. |
208 |
* Remove the registration for the target. |
| 209 |
*/ |
209 |
*/ |
| 210 |
static int |
210 |
static int |
| 211 |
rendevous_unregister_target(device_t dev) |
211 |
rendezvous_unregister_target(device_t dev) |
| 212 |
{ |
212 |
{ |
| 213 |
struct rendevous_entry *e; |
213 |
struct rendezvous_entry *e; |
| 214 |
int error = 0; |
214 |
int error = 0; |
| 215 |
|
215 |
|
| 216 |
SLIST_FOREACH(e, &rendevoushead, entries) { |
216 |
SLIST_FOREACH(e, &rendezvoushead, entries) { |
| 217 |
if (e->target.device == dev) { |
217 |
if (e->target.device == dev) { |
| 218 |
if (e->proxy.device == NULL) { |
218 |
if (e->proxy.device == NULL) { |
| 219 |
SLIST_REMOVE(&rendevoushead, e, rendevous_entry, entries); |
219 |
SLIST_REMOVE(&rendezvoushead, e, rendezvous_entry, entries); |
| 220 |
free(e, M_MIIPROXY); |
220 |
free(e, M_MIIPROXY); |
| 221 |
return (0); |
221 |
return (0); |
| 222 |
} else { |
222 |
} else { |
|
Lines 237-249
rendevous_unregister_target(device_t dev)
Link Here
|
| 237 |
*/ |
237 |
*/ |
| 238 |
|
238 |
|
| 239 |
static int |
239 |
static int |
| 240 |
miiproxy_rendevous_callback(enum rendevous_op op, struct rendevous_entry *rendevous) |
240 |
miiproxy_rendezvous_callback(enum rendezvous_op op, struct rendezvous_entry *rendezvous) |
| 241 |
{ |
241 |
{ |
| 242 |
struct miiproxy_softc *sc = device_get_softc(rendevous->proxy.device); |
242 |
struct miiproxy_softc *sc = device_get_softc(rendezvous->proxy.device); |
| 243 |
|
243 |
|
| 244 |
switch (op) { |
244 |
switch (op) { |
| 245 |
case RENDEVOUS_ATTACH: |
245 |
case RENDEVOUS_ATTACH: |
| 246 |
sc->mdio = device_get_parent(rendevous->target.device); |
246 |
sc->mdio = device_get_parent(rendezvous->target.device); |
| 247 |
break; |
247 |
break; |
| 248 |
case RENDEVOUS_DETACH: |
248 |
case RENDEVOUS_DETACH: |
| 249 |
sc->mdio = NULL; |
249 |
sc->mdio = NULL; |
|
Lines 266-272
miiproxy_attach(device_t dev)
Link Here
|
| 266 |
|
266 |
|
| 267 |
/* |
267 |
/* |
| 268 |
* The ethernet interface needs to call mii_attach_proxy() to pass |
268 |
* The ethernet interface needs to call mii_attach_proxy() to pass |
| 269 |
* the relevant parameters for rendevous with the MDIO target. |
269 |
* the relevant parameters for rendezvous with the MDIO target. |
| 270 |
*/ |
270 |
*/ |
| 271 |
return (bus_generic_attach(dev)); |
271 |
return (bus_generic_attach(dev)); |
| 272 |
} |
272 |
} |
|
Lines 275-281
static int
Link Here
|
| 275 |
miiproxy_detach(device_t dev) |
275 |
miiproxy_detach(device_t dev) |
| 276 |
{ |
276 |
{ |
| 277 |
|
277 |
|
| 278 |
rendevous_unregister_proxy(dev); |
278 |
rendezvous_unregister_proxy(dev); |
| 279 |
bus_generic_detach(dev); |
279 |
bus_generic_detach(dev); |
| 280 |
return (0); |
280 |
return (0); |
| 281 |
} |
281 |
} |
|
Lines 325-331
miiproxy_mediainit(device_t dev)
Link Here
|
| 325 |
* Functions for the MDIO target device driver. |
325 |
* Functions for the MDIO target device driver. |
| 326 |
*/ |
326 |
*/ |
| 327 |
static int |
327 |
static int |
| 328 |
mdioproxy_rendevous_callback(enum rendevous_op op, struct rendevous_entry *rendevous) |
328 |
mdioproxy_rendezvous_callback(enum rendezvous_op op, struct rendezvous_entry *rendezvous) |
| 329 |
{ |
329 |
{ |
| 330 |
return (0); |
330 |
return (0); |
| 331 |
} |
331 |
} |
|
Lines 352-358
static int
Link Here
|
| 352 |
mdioproxy_attach(device_t dev) |
352 |
mdioproxy_attach(device_t dev) |
| 353 |
{ |
353 |
{ |
| 354 |
|
354 |
|
| 355 |
rendevous_register_target(dev, mdioproxy_rendevous_callback); |
355 |
rendezvous_register_target(dev, mdioproxy_rendezvous_callback); |
| 356 |
return (bus_generic_attach(dev)); |
356 |
return (bus_generic_attach(dev)); |
| 357 |
} |
357 |
} |
| 358 |
|
358 |
|
|
Lines 360-366
static int
Link Here
|
| 360 |
mdioproxy_detach(device_t dev) |
360 |
mdioproxy_detach(device_t dev) |
| 361 |
{ |
361 |
{ |
| 362 |
|
362 |
|
| 363 |
rendevous_unregister_target(dev); |
363 |
rendezvous_unregister_target(dev); |
| 364 |
bus_generic_detach(dev); |
364 |
bus_generic_detach(dev); |
| 365 |
return (0); |
365 |
return (0); |
| 366 |
} |
366 |
} |
|
Lines 394-400
mii_attach_proxy(device_t dev)
Link Here
|
| 394 |
sc = device_get_softc(miiproxy); |
394 |
sc = device_get_softc(miiproxy); |
| 395 |
sc->parent = dev; |
395 |
sc->parent = dev; |
| 396 |
sc->proxy = miiproxy; |
396 |
sc->proxy = miiproxy; |
| 397 |
if (rendevous_register_proxy(miiproxy, name, miiproxy_rendevous_callback) != 0) { |
397 |
if (rendezvous_register_proxy(miiproxy, name, miiproxy_rendezvous_callback) != 0) { |
| 398 |
device_printf(dev, "can't attach proxy\n"); |
398 |
device_printf(dev, "can't attach proxy\n"); |
| 399 |
return (NULL); |
399 |
return (NULL); |
| 400 |
} |
400 |
} |