Modules/UDI - Channel code implimented (partially)
[tpg/acess2.git] / KernelLand / Modules / Interfaces / UDI / main.c
1 /*
2  * Acess2 UDI Layer
3  */
4 #define DEBUG   0
5 #define VERSION ((0<<8)|1)
6 #include <acess.h>
7 #include <modules.h>
8 #include <udi.h>
9 #include "udi_internal.h"
10
11 // === PROTOTYPES ===
12  int    UDI_Install(char **Arguments);
13  int    UDI_DetectDriver(void *Base);
14  int    UDI_LoadDriver(void *Base);
15
16 tUDI_DriverInstance     *UDI_CreateInstance(tUDI_DriverModule *DriverModule);
17 tUDI_DriverRegion       *UDI_InitRegion(tUDI_DriverInstance *Inst, udi_ubit16_t Index, udi_ubit16_t Type, size_t RDataSize);
18
19 // === GLOBALS ===
20 MODULE_DEFINE(0, VERSION, UDI, UDI_Install, NULL, NULL);
21 tModuleLoader   gUDI_Loader = {
22         NULL, "UDI", UDI_DetectDriver, UDI_LoadDriver, NULL
23 };
24
25 // === CODE ===
26 /**
27  * \fn int UDI_Install(char **Arguments)
28  * \brief Stub intialisation routine
29  */
30 int UDI_Install(char **Arguments)
31 {
32         Module_RegisterLoader( &gUDI_Loader );
33         return MODULE_ERR_OK;
34 }
35
36 /**
37  * \brief Detects if a driver should be loaded by the UDI subsystem
38  */
39 int UDI_DetectDriver(void *Base)
40 {
41         Uint    unused;
42         
43         if( Binary_FindSymbol(Base, "udi_init_info", &unused) == 0) {
44                 return 0;
45         }
46         if( Binary_FindSymbol(Base, "_udiprops", &unused) == 0 ) {
47                 Log_Warning("UDI", "Driver has udi_init_info, but no _udiprops symbol");
48                 return 0;
49         }
50         if( Binary_FindSymbol(Base, "_udiprops_end", &unused) == 0) {
51                 Log_Warning("UDI", "Driver has udi_init_info, but no _udiprops_end symbol");
52                 return 0;
53         }
54         
55         return 1;
56 }
57
58 /**
59  * \fn int UDI_LoadDriver(void *Base)
60  */
61 int UDI_LoadDriver(void *Base)
62 {
63         udi_init_t      *info;
64         char    *udiprops = NULL;
65         char    *udiprops_end = 0;
66         
67         ENTER("pBase", Base);
68         
69         if( Binary_FindSymbol(Base, "udi_init_info", (Uint*)&info) == 0) {
70                 Binary_Unload(Base);
71                 LEAVE('i', 0);
72                 return 0;
73         }
74         
75         Binary_FindSymbol(Base, "_udiprops", (Uint*)&udiprops);
76         Binary_FindSymbol(Base, "_udiprops_end", (Uint*)&udiprops_end);
77
78         #if 0   
79         Log("primary_init_info = %p = {", info->primary_init_info);
80         {
81                 Log(" .mgmt_ops = %p = {", info->primary_init_info->mgmt_ops);
82                 Log("  .usage_ind_op: %p() - 0x%02x",
83                         info->primary_init_info->mgmt_ops->usage_ind_op,
84                         info->primary_init_info->mgmt_op_flags[0]
85                         );
86                 Log("  .enumerate_req_op: %p() - 0x%02x",
87                         info->primary_init_info->mgmt_ops->enumerate_req_op,
88                         info->primary_init_info->mgmt_op_flags[1]
89                         );
90                 Log("  .devmgmt_req_op: %p() - 0x%02x",
91                         info->primary_init_info->mgmt_ops->devmgmt_req_op,
92                         info->primary_init_info->mgmt_op_flags[2]
93                         );
94                 Log("  .final_cleanup_req_op: %p() - 0x%02x",
95                         info->primary_init_info->mgmt_ops->final_cleanup_req_op,
96                         info->primary_init_info->mgmt_op_flags[3]
97                         );
98                 Log(" }");
99                 Log(" .mgmt_scratch_requirement = 0x%x", info->primary_init_info->mgmt_scratch_requirement);
100                 Log(" .enumeration_attr_list_length = 0x%x", info->primary_init_info->enumeration_attr_list_length);
101                 Log(" .rdata_size = 0x%x", info->primary_init_info->rdata_size);
102                 Log(" .child_data_size = 0x%x", info->primary_init_info->child_data_size);
103                 Log(" .per_parent_paths = 0x%x", info->primary_init_info->per_parent_paths);
104         }
105         Log("}");
106         Log("secondary_init_list = %p {", info->secondary_init_list);
107         for( int i = 0; info->secondary_init_list && info->secondary_init_list[i].region_idx; i ++ )
108         {
109                 Log(" [%i] = { .region_idx=%i, .rdata_size=0x%x }",
110                         info->secondary_init_list[i].region_idx, info->secondary_init_list[i].rdata_size);
111         }
112         LOG("}");
113         Log("ops_init_list = %p", info->ops_init_list);
114         
115         for( int i = 0; info->ops_init_list[i].ops_idx; i++ )
116         {
117                 Log("info->ops_init_list[%i] = {", i);
118                 Log(" .ops_idx = 0x%x", info->ops_init_list[i].ops_idx);
119                 Log(" .meta_idx = 0x%x", info->ops_init_list[i].meta_idx);
120                 Log(" .meta_ops_num = 0x%x", info->ops_init_list[i].meta_ops_num);
121                 Log(" .chan_context_size = 0x%x", info->ops_init_list[i].chan_context_size);
122                 Log(" .ops_vector = %p", info->ops_init_list[i].ops_vector);
123 //              Log(" .op_flags = %p", info->ops_init_list[i].op_flags);
124                 Log("}");
125         }
126         #endif
127
128         
129         // TODO: Multiple modules?
130         tUDI_DriverModule *driver_module = NEW(tUDI_DriverModule,);
131         driver_module->InitInfo = info;
132
133         // - Parse udiprops
134         {
135                 char    **udipropsptrs;
136                 
137                 Log_Debug("UDI", "udiprops = %p, udiprops_end = %p", udiprops, udiprops_end);
138                 size_t  udiprops_size = udiprops_end - udiprops;
139                 
140                 int nLines = 1;
141                 for( int i = 0; i < udiprops_size; i++ )
142                 {
143                         if( udiprops[i] == '\0' )
144                                 nLines ++;
145                 }
146                 
147                 Log_Debug("UDI", "nLines = %i", nLines);
148                 
149                 udipropsptrs = NEW(char*,*nLines);
150                 int line = 0;
151                 udipropsptrs[line++] = udiprops;
152                 for( int i = 0; i < udiprops_size; i++ )
153                 {
154                         if( udiprops[i] == '\0' ) {
155                                 udipropsptrs[line++] = &udiprops[i+1];
156                         }
157                 }
158                 if(udipropsptrs[line-1] == &udiprops[udiprops_size])
159                         nLines --;
160                 
161                 for( int i = 0; i < nLines; i ++ )
162                 {
163                 }
164                 
165                 // Parse out:
166                 // 'message' into driver_module->Messages
167                 // 'region' into driver_module->RegionTypes
168                 // 'module' into driver_module->ModuleName
169                 
170                  int    nMessages = 0;
171                  int    nLocales = 1;
172                  int    nRegionTypes = 0;
173                 for( int i = 0; i < nLines; i ++ )
174                 {
175                         const char *str = udipropsptrs[i];
176                         if( strncmp("module ", str, 7) == 0 ) {
177                                 driver_module->ModuleName = str + 7;
178                         }
179                         else if( strncmp("message ", str, 8) == 0 ) {
180                                 nMessages ++;
181                         }
182                         else if( strncmp("locale ", str, 7) == 0 ) {
183                                 nLocales ++;
184                         }
185                         else if( strncmp("region ", str, 7) == 0 ) {
186                                 nRegionTypes ++;
187                         }
188                 }
189
190                 // Allocate structures
191                 driver_module->nMessages = nMessages;
192                 driver_module->Messages = NEW(tUDI_PropMessage, *nMessages);
193                 driver_module->nRegionTypes = nRegionTypes;
194                 driver_module->RegionTypes = NEW(tUDI_PropRegion, *nRegionTypes);
195
196                 // Populate
197                  int    cur_locale = 0;
198                  int    msg_index = 0;
199                 for( int i = 0; i < nLines; i ++ )
200                 {
201                         const char *str = udipropsptrs[i];
202                         if( strncmp("module ", str, 7) == 0 ) {
203                                 driver_module->ModuleName = str + 7;
204                         }
205                         else if( strncmp("message ", str, 8) == 0 ) {
206                                 tUDI_PropMessage *msg = &driver_module->Messages[msg_index++];
207                                 char    *end;
208                                 msg->locale = cur_locale;
209                                 msg->index = strtoul(str+8, &end, 10);
210                                 if( *end != ' ' && *end != '\t' ) {
211                                         // Oops.
212                                         continue ;
213                                 }
214                                 while( isspace(*end) )
215                                         end ++;
216                                 msg->string = end;
217                                 
218                                 Log_Debug("UDI", "Message %i/%i: '%s'", msg->locale, msg->index, msg->string);
219                         }
220                         else if( strncmp("locale ", str, 7) == 0 ) {
221                                 // TODO: Set locale
222                                 cur_locale = 1;
223                         }
224                         else if( strncmp("region ", str, 7) == 0 ) {
225                                 nRegionTypes ++;
226                         }
227                         else {
228                                 Log_Debug("UDI", "udipropsptrs[%i] = '%s'", i, udipropsptrs[i]);
229                         }
230                 }
231                 
232                 // Sort message list
233                 // TODO: Sort message list
234         }
235
236          int    nSecondaryRgns = 0;
237         for( int i = 0; info->secondary_init_list && info->secondary_init_list[i].region_idx; i ++ )
238                 nSecondaryRgns ++;
239         driver_module->nSecondaryRegions = nSecondaryRgns;
240         
241         // Create initial driver instance
242         tUDI_DriverInstance *inst = UDI_CreateInstance(driver_module);
243
244         for( int i = 0; i < 1+driver_module->nSecondaryRegions; i ++ )
245                 Log("Rgn %i: %p", i, inst->Regions[i]);
246
247         // Send usage indication
248         udi_usage_cb_t ucb;
249         memset(&ucb, 0, sizeof(ucb));
250         ucb.gcb.channel = inst->ManagementChannel;
251         udi_usage_ind(&ucb, UDI_RESOURCES_NORMAL);
252         
253         return 0;
254 }
255
256 tUDI_DriverInstance *UDI_CreateInstance(tUDI_DriverModule *DriverModule)
257 {
258         tUDI_DriverInstance     *inst = NEW_wA(tUDI_DriverInstance, Regions, (1+DriverModule->nSecondaryRegions));
259         inst->Module = DriverModule;
260         inst->Regions[0] = UDI_InitRegion(inst, 0, 0, DriverModule->InitInfo->primary_init_info->rdata_size);
261         udi_secondary_init_t    *sec_init = DriverModule->InitInfo->secondary_init_list;
262         if( sec_init )
263         {
264                 for( int i = 0; sec_init[i].region_idx; i ++ )
265                 {
266                         inst->Regions[1+i] = UDI_InitRegion(inst, i, sec_init[i].region_idx, sec_init[i].rdata_size);
267                 }
268         }
269
270         inst->ManagementChannel = UDI_CreateChannel(METALANG_MGMT, 0, NULL, 0, inst, 0);
271         
272         return inst;
273 }
274
275 tUDI_DriverRegion *UDI_InitRegion(tUDI_DriverInstance *Inst, udi_ubit16_t Index, udi_ubit16_t Type, size_t RDataSize)
276 {
277 //      ASSERTCR( RDataSize, <=, UDI_MIN_ALLOC_LIMIT, NULL );
278         ASSERTCR( RDataSize, >, sizeof(udi_init_context_t), NULL );
279         tUDI_DriverRegion       *rgn = NEW(tUDI_DriverRegion,+RDataSize);
280         rgn->InitContext = (void*)(rgn+1);
281         rgn->InitContext->region_idx = Type;
282 //      rgn->InitContext->limits
283         return rgn;
284 }
285

UCC git Repository :: git.ucc.asn.au