5 #define VERSION ((0<<8)|1)
9 #include "udi_internal.h"
12 extern udi_init_t pci_init;
13 extern char pci_udiprops[];
14 extern size_t pci_udiprops_size;
17 int UDI_Install(char **Arguments);
18 int UDI_DetectDriver(void *Base);
19 int UDI_LoadDriver(void *Base);
21 tUDI_DriverModule *UDI_int_LoadDriver(void *LoadBase, udi_init_t *info, const char *udiprops, size_t udiprops_size);
23 tUDI_DriverInstance *UDI_CreateInstance(tUDI_DriverModule *DriverModule);
24 tUDI_DriverRegion *UDI_InitRegion(tUDI_DriverInstance *Inst, udi_ubit16_t Index, udi_ubit16_t Type, size_t RDataSize);
25 void UDI_int_BeginEnumeration(tUDI_DriverInstance *Inst);
28 MODULE_DEFINE(0, VERSION, UDI, UDI_Install, NULL, NULL);
29 tModuleLoader gUDI_Loader = {
30 NULL, "UDI", UDI_DetectDriver, UDI_LoadDriver, NULL
35 * \fn int UDI_Install(char **Arguments)
36 * \brief Stub intialisation routine
38 int UDI_Install(char **Arguments)
40 Module_RegisterLoader( &gUDI_Loader );
42 UDI_int_LoadDriver(NULL, &pci_init, pci_udiprops, pci_udiprops_size);
48 * \brief Detects if a driver should be loaded by the UDI subsystem
50 int UDI_DetectDriver(void *Base)
54 if( Binary_FindSymbol(Base, "udi_init_info", &unused) == 0) {
57 if( Binary_FindSymbol(Base, "_udiprops", &unused) == 0 ) {
58 Log_Warning("UDI", "Driver has udi_init_info, but no _udiprops symbol");
61 if( Binary_FindSymbol(Base, "_udiprops_end", &unused) == 0) {
62 Log_Warning("UDI", "Driver has udi_init_info, but no _udiprops_end symbol");
70 * \fn int UDI_LoadDriver(void *Base)
72 int UDI_LoadDriver(void *Base)
75 char *udiprops = NULL;
76 char *udiprops_end = 0;
78 if( Binary_FindSymbol(Base, "udi_init_info", (Uint*)&info) == 0) {
83 Binary_FindSymbol(Base, "_udiprops", (Uint*)&udiprops);
84 Binary_FindSymbol(Base, "_udiprops_end", (Uint*)&udiprops_end);
85 Log_Debug("UDI", "udiprops = %p, udiprops_end = %p", udiprops, udiprops_end);
87 UDI_int_LoadDriver(Base, info, udiprops, udiprops_end - udiprops);
90 // Create initial driver instance
91 tUDI_DriverInstance *inst = UDI_CreateInstance(driver_module);
94 // TODO: This will move to udi_enumerate_ack handling
95 for( int i = 0; i < driver_module->nParents; i ++ )
97 tUDI_BindOps *parent = &driver_module->Parents[i];
98 udi_channel_t channel = UDI_CreateChannel_Blank( UDI_int_GetMetaLang(inst, parent->meta_idx) );
100 UDI_BindChannel(channel,true, inst, parent->ops_idx, parent->region_idx);
101 //UDI_BindChannel(channel,false, parent_inst, parent_chld->ops_idx, parent_chld->region_idx);
103 udi_cb_t *bind_cb = udi_cb_alloc_internal(inst, parent->bind_cb_idx, channel);
105 Log_Warning("UDI", "Bind CB index is invalid");
109 udi_channel_event_cb_t ev_cb;
110 int n_handles = driver_module->InitInfo->primary_init_info->per_parent_paths;
111 udi_buf_path_t handles[n_handles];
112 memset(&ev_cb, 0, sizeof(ev_cb));
113 ev_cb.gcb.channel = channel;
114 ev_cb.event = UDI_CHANNEL_BOUND;
115 ev_cb.params.parent_bound.bind_cb = bind_cb;
116 ev_cb.params.parent_bound.parent_ID = i+1;
117 ev_cb.params.parent_bound.path_handles = handles;
119 for( int i = 0; i < n_handles; i ++ ) {
120 //handles[i] = udi_buf_path_alloc_internal(inst);
124 udi_channel_event_ind(&ev_cb);
127 // Send enumeraton request
133 tUDI_DriverModule *UDI_int_LoadDriver(void *LoadBase, udi_init_t *info, const char *udiprops, size_t udiprops_size)
135 //UDI_int_DumpInitInfo(info);
137 // TODO: Multiple modules?
138 tUDI_DriverModule *driver_module = NEW(tUDI_DriverModule,);
139 driver_module->InitInfo = info;
143 const char **udipropsptrs;
147 for( int i = 0; i < udiprops_size; i++ )
149 if( udiprops[i] == '\0' )
153 Log_Debug("UDI", "nLines = %i", nLines);
155 udipropsptrs = NEW(const char*,*nLines);
157 udipropsptrs[line++] = udiprops;
158 for( int i = 0; i < udiprops_size; i++ )
160 if( udiprops[i] == '\0' ) {
161 udipropsptrs[line++] = &udiprops[i+1];
164 if(udipropsptrs[line-1] == &udiprops[udiprops_size])
167 for( int i = 0; i < nLines; i ++ )
172 // 'message' into driver_module->Messages
173 // 'region' into driver_module->RegionTypes
174 // 'module' into driver_module->ModuleName
177 int nRegionTypes = 0;
178 for( int i = 0; i < nLines; i ++ )
180 const char *str = udipropsptrs[i];
181 if( strncmp("module ", str, 7) == 0 ) {
182 driver_module->ModuleName = str + 7;
184 else if( strncmp("meta ", str, 5) == 0 ) {
185 driver_module->nMetaLangs ++;
187 else if( strncmp("message ", str, 8) == 0 ) {
188 driver_module->nMessages ++;
190 else if( strncmp("locale ", str, 7) == 0 ) {
193 else if( strncmp("region ", str, 7) == 0 ) {
196 else if( strncmp("parent_bind_ops ", str, 16) == 0 ) {
197 driver_module->nParents ++;
201 // Allocate structures
202 driver_module->Messages = NEW(tUDI_PropMessage, * driver_module->nMessages);
203 driver_module->nRegionTypes = nRegionTypes;
204 driver_module->RegionTypes = NEW(tUDI_PropRegion, * driver_module->nRegionTypes);
205 driver_module->MetaLangs = NEW(tUDI_MetaLangRef, * driver_module->nMetaLangs);
206 driver_module->Parents = NEW(tUDI_BindOps, * driver_module->nParents);
212 int parent_index = 0;
213 for( int i = 0; i < nLines; i ++ )
215 const char *str = udipropsptrs[i];
216 if( strncmp("module ", str, 7) == 0 ) {
217 driver_module->ModuleName = str + 7;
219 else if( strncmp("meta ", str, 5) == 0 ) {
220 tUDI_MetaLangRef *ml = &driver_module->MetaLangs[ml_index++];
222 ml->meta_idx = strtoul(str+5, &end, 10);
223 if( *end != ' ' && !end != '\t' ) {
224 // TODO: handle 'meta' error
227 while( isspace(*end) )
229 ml->interface_name = end;
231 else if( strncmp("message ", str, 8) == 0 ) {
232 tUDI_PropMessage *msg = &driver_module->Messages[msg_index++];
234 msg->locale = cur_locale;
235 msg->index = strtoul(str+8, &end, 10);
236 if( *end != ' ' && *end != '\t' ) {
240 while( isspace(*end) )
244 //Log_Debug("UDI", "Message %i/%i: '%s'", msg->locale, msg->index, msg->string);
246 else if( strncmp("locale ", str, 7) == 0 ) {
250 //else if( strncmp("region ", str, 7) == 0 ) {
253 else if( strncmp("parent_bind_ops ", str, 16) == 0 ) {
254 tUDI_BindOps *bind = &driver_module->Parents[parent_index++];
256 bind->meta_idx = strtoul(str+16, &end, 10);
257 while(isspace(*end)) end++;
258 bind->region_idx = strtoul(end, &end, 10);
259 while(isspace(*end)) end++;
260 bind->ops_idx = strtoul(end, &end, 10);
261 while(isspace(*end)) end++;
262 bind->bind_cb_idx = strtoul(end, &end, 10);
263 Log_Debug("UDI", "Parent bind - meta:%i,rgn:%i,ops:%i,bind:%i",
264 bind->meta_idx, bind->region_idx, bind->ops_idx, bind->bind_cb_idx);
266 //else if( strncmp("internal_bind_ops ", str, 18) == 0 ) {
267 // // Get region using index
270 Log_Debug("UDI", "udipropsptrs[%i] = '%s'", i, udipropsptrs[i]);
275 // TODO: Sort message list
278 int nSecondaryRgns = 0;
279 for( int i = 0; info->secondary_init_list && info->secondary_init_list[i].region_idx; i ++ )
281 driver_module->nRegions = 1+nSecondaryRgns;
284 // Check for orphan drivers, and create an instance of them when loaded
285 if( driver_module->nParents == 0 )
287 tUDI_DriverInstance *inst = UDI_CreateInstance(driver_module);
289 // Enumerate so any pre-loaded drivers are detected
290 UDI_int_BeginEnumeration(inst);
294 // Send rescan requests to all loaded instances that support a parent metalang
297 return driver_module;
300 void UDI_int_DumpInitInfo(udi_init_t *info)
302 Log("primary_init_info = %p = {", info->primary_init_info);
304 Log(" .mgmt_ops = %p = {", info->primary_init_info->mgmt_ops);
305 Log(" .usage_ind_op: %p() - 0x%02x",
306 info->primary_init_info->mgmt_ops->usage_ind_op,
307 info->primary_init_info->mgmt_op_flags[0]
309 Log(" .enumerate_req_op: %p() - 0x%02x",
310 info->primary_init_info->mgmt_ops->enumerate_req_op,
311 info->primary_init_info->mgmt_op_flags[1]
313 Log(" .devmgmt_req_op: %p() - 0x%02x",
314 info->primary_init_info->mgmt_ops->devmgmt_req_op,
315 info->primary_init_info->mgmt_op_flags[2]
317 Log(" .final_cleanup_req_op: %p() - 0x%02x",
318 info->primary_init_info->mgmt_ops->final_cleanup_req_op,
319 info->primary_init_info->mgmt_op_flags[3]
322 Log(" .mgmt_scratch_requirement = 0x%x", info->primary_init_info->mgmt_scratch_requirement);
323 Log(" .enumeration_attr_list_length = 0x%x", info->primary_init_info->enumeration_attr_list_length);
324 Log(" .rdata_size = 0x%x", info->primary_init_info->rdata_size);
325 Log(" .child_data_size = 0x%x", info->primary_init_info->child_data_size);
326 Log(" .per_parent_paths = 0x%x", info->primary_init_info->per_parent_paths);
329 Log("secondary_init_list = %p {", info->secondary_init_list);
330 for( int i = 0; info->secondary_init_list && info->secondary_init_list[i].region_idx; i ++ )
332 Log(" [%i] = { .region_idx=%i, .rdata_size=0x%x }",
333 info->secondary_init_list[i].region_idx, info->secondary_init_list[i].rdata_size);
336 Log("ops_init_list = %p {", info->ops_init_list);
337 for( int i = 0; info->ops_init_list[i].ops_idx; i++ )
340 Log(" .ops_idx = 0x%x", info->ops_init_list[i].ops_idx);
341 Log(" .meta_idx = 0x%x", info->ops_init_list[i].meta_idx);
342 Log(" .meta_ops_num = 0x%x", info->ops_init_list[i].meta_ops_num);
343 Log(" .chan_context_size = 0x%x", info->ops_init_list[i].chan_context_size);
344 Log(" .ops_vector = %p", info->ops_init_list[i].ops_vector);
345 // Log(" .op_flags = %p", info->ops_init_list[i].op_flags);
349 Log("cb_init_list = %p {", info->cb_init_list);
350 for( int i = 0; info->cb_init_list[i].cb_idx; i++ )
352 udi_cb_init_t *ent = &info->cb_init_list[i];
354 Log(" .cbidx = %i", ent->cb_idx);
355 Log(" .meta_idx = %i", ent->meta_idx);
356 Log(" .meta_cb_num = %i", ent->meta_cb_num);
357 Log(" .scratch_requirement = 0x%x", ent->scratch_requirement);
358 Log(" .inline_size = 0x%x", ent->inline_size);
359 Log(" .inline_layout = %p", ent->inline_layout);
364 tUDI_DriverInstance *UDI_CreateInstance(tUDI_DriverModule *DriverModule)
366 tUDI_DriverInstance *inst = NEW_wA(tUDI_DriverInstance, Regions, DriverModule->nRegions);
367 udi_primary_init_t *pri_init = DriverModule->InitInfo->primary_init_info;
368 inst->Module = DriverModule;
369 inst->Regions[0] = UDI_InitRegion(inst, 0, 0, pri_init->rdata_size);
370 udi_secondary_init_t *sec_init = DriverModule->InitInfo->secondary_init_list;
373 for( int i = 0; sec_init[i].region_idx; i ++ )
375 inst->Regions[1+i] = UDI_InitRegion(inst, i,
376 sec_init[i].region_idx, sec_init[i].rdata_size);
380 //inst->ManagementChannel = UDI_CreateChannel(METALANG_MGMT, 0, NULL, 0, inst, 0);
381 inst->ManagementChannel = UDI_CreateChannel_Blank(&cMetaLang_Management);
382 UDI_BindChannel_Raw(inst->ManagementChannel, true,
383 0, inst->Regions[0]->InitContext, pri_init->mgmt_ops);
384 // UDI_BindChannel_Raw(inst->ManagementChannel, false,
385 // 1, inst, NULL); // TODO: ops list for management
387 for( int i = 0; i < DriverModule->nRegions; i ++ )
388 Log("Rgn %i: %p", i, inst->Regions[i]);
390 // Send usage indication
391 char scratch[pri_init->mgmt_scratch_requirement];
394 memset(&ucb, 0, sizeof(ucb));
395 ucb.gcb.scratch = scratch;
396 ucb.gcb.channel = inst->ManagementChannel;
397 udi_usage_ind(&ucb, UDI_RESOURCES_NORMAL);
398 // TODO: Ensure that udi_usage_res is called
401 for( int i = 1; i < DriverModule->nRegions; i ++ )
403 //inst->Regions[i]->PriChannel = UDI_CreateChannel_Blank(
404 // TODO: Bind secondaries to primary
410 tUDI_DriverRegion *UDI_InitRegion(tUDI_DriverInstance *Inst, udi_ubit16_t Index, udi_ubit16_t Type, size_t RDataSize)
412 // ASSERTCR( RDataSize, <=, UDI_MIN_ALLOC_LIMIT, NULL );
413 ASSERTCR( RDataSize, >=, sizeof(udi_init_context_t), NULL );
414 tUDI_DriverRegion *rgn = NEW(tUDI_DriverRegion,+RDataSize);
415 rgn->InitContext = (void*)(rgn+1);
416 rgn->InitContext->region_idx = Type;
417 // rgn->InitContext->limits
421 void UDI_int_BeginEnumeration(tUDI_DriverInstance *Inst)
423 udi_primary_init_t *pri_init = Inst->Module->InitInfo->primary_init_info;
424 char scratch[pri_init->mgmt_scratch_requirement];
425 udi_enumerate_cb_t ecb;
426 memset(&ecb, 0, sizeof(ecb));
427 ecb.gcb.scratch = scratch;
428 ecb.gcb.channel = Inst->ManagementChannel;
429 ecb.child_data = malloc( pri_init->child_data_size);
430 ecb.attr_list = NEW(udi_instance_attr_list_t, *pri_init->enumeration_attr_list_length);
431 ecb.attr_valid_length = 0;
432 udi_enumerate_req(&ecb, UDI_ENUMERATE_START);
435 // TODO: Move this stuff out
436 udi_ops_init_t *UDI_int_GetOps(tUDI_DriverInstance *Inst, udi_index_t index)
438 udi_ops_init_t *ops = Inst->Module->InitInfo->ops_init_list;
439 while( ops->ops_idx && ops->ops_idx != index )
441 if(ops->ops_idx == 0)
446 tUDI_MetaLang *UDI_int_GetMetaLang(tUDI_DriverInstance *Inst, udi_index_t index)
449 return &cMetaLang_Management;
450 for( int i = 0; i < Inst->Module->nMetaLangs; i ++ )
452 if( Inst->Module->MetaLangs[i].meta_idx == index )
453 return Inst->Module->MetaLangs[i].metalang;
458 void *udi_cb_alloc_internal(tUDI_DriverInstance *Inst, udi_ubit8_t bind_cb_idx, udi_channel_t channel)
460 udi_cb_init_t *cb_init = NULL;
461 for( cb_init = Inst->Module->InitInfo->cb_init_list; cb_init->cb_idx; cb_init ++ )
463 if( cb_init->cb_idx == bind_cb_idx )
465 udi_cb_t *ret = NEW(udi_cb_t, + cb_init->inline_size + cb_init->scratch_requirement);
466 ret->channel = channel;
470 Log_Warning("UDI", "Cannot find CB init def %i for '%s'",
471 bind_cb_idx, Inst->Module->ModuleName);