2 ** Copyright 2001/02, Thomas Kurschel. All rights reserved.
3 ** Distributed under the terms of the NewOS License.
8 // - "offsetof" macro is missing
9 // -> move it to a public place
11 #include <kernel/module.h>
12 #include <kernel/lock.h>
13 #include <kernel/heap.h>
14 #include <kernel/vm.h>
15 #include <kernel/cpu.h>
16 #include <kernel/debug.h>
17 #include <kernel/khash.h>
19 #include <kernel/elf.h>
23 #define debug_level_flow -1
24 #define debug_level_error 0
25 #define debug_level_info 0
27 #define DEBUG_MSG_PREFIX "MODULE -- "
29 #include <kernel/debug_ext.h>
32 #include <kernel/bus/isa/isa.h>
38 #define offsetof(type, member) ((size_t)&(((type *)0)->member))
41 bool modules_disable_user_addons
= false;
48 module_uninitializing
,
52 typedef struct module_info
{
53 struct module_info
*next
;
54 struct module_image
*image
;
55 module_header
*header
;
62 typedef struct module_image
{
63 struct module_image
*next
;
69 module_header
**headers
;
73 // XXX locking scheme: there is a global lock only; having several locks
74 // makes trouble if dependent modules get loaded concurrently ->
75 // they have to wait for each other, i.e. we need one lock per module;
76 // also we must detect circular references during init and not dead-lock
77 static recursive_lock modules_lock
;
79 const char *const module_paths
[] = {
80 "/boot/user-addons/modules",
81 "/boot/addons/modules"
84 #define num_module_paths (sizeof( module_paths ) / sizeof( module_paths[0] ))
86 #define MODULES_HASH_SIZE 16
88 void *modules_images
[num_module_paths
];
92 static int module_info_compare( void *a
, const void *key
)
94 module_info
*module
= a
;
95 const char *name
= key
;
97 return strcmp( module
->header
->name
, name
);
100 static unsigned int module_info_hash( void *a
, const void *key
, unsigned int range
)
102 module_info
*module
= a
;
105 return hash_hash_str( module
->header
->name
) % range
;
107 return hash_hash_str( key
) % range
;
110 static int module_image_compare( void *a
, const void *key
)
112 module_image
*image
= a
;
113 const char *name
= key
;
115 return strcmp( image
->name
, name
);
118 static unsigned int module_image_hash( void *a
, const void *key
, unsigned int range
)
120 module_image
*image
= a
;
123 return hash_hash_str( image
->name
) % range
;
125 return hash_hash_str( key
) % range
;
129 static inline int check_module_header( module_header
*header
)
131 if( header
->version
!= MODULE_CURR_VERSION
) {
132 SHOW_ERROR( 0, "module %s has unsupported version (%i)", header
->name
, header
->version
);
136 if( header
->interface
== NULL
) {
137 SHOW_ERROR( 0, "module %s has no public interface", header
->name
);
141 if( (header
->flags
& ~(MODULE_KEEP_LOADED
)) != 0 ) {
142 SHOW_ERROR( 0, "module %s has unknown flag(s) set (%x)", header
->name
, header
->flags
);
150 static inline module_info
*register_module( module_image
*image
, module_header
*header
)
154 SHOW_FLOW( 3, "module %s in image %s", header
->name
, image
->path
);
156 if( check_module_header( header
) != NO_ERROR
)
159 module
= (module_info
*)kmalloc( sizeof( module_info
));
164 module
->header
= header
;
165 module
->image
= image
;
166 module
->ref_count
= 1;
167 module
->keep_loaded
= header
->flags
& MODULE_KEEP_LOADED
;
168 image
->keep_loaded
|= module
->keep_loaded
;
169 module
->state
= module_loaded
;
171 SHOW_FLOW0( 3, "adding to hash" );
172 if( hash_insert( modules_list
, module
) != NO_ERROR
) {
179 SHOW_FLOW0( 3, "done" );
184 static inline void unregister_module_image( module_image
*image
)
186 SHOW_FLOW( 3, "name=%s", image
->name
);
188 hash_remove( modules_images
[image
->base_path_id
], image
);
190 kfree( image
->name
);
191 kfree( image
->path
);
195 static void put_module_image( module_image
*image
)
197 if( --image
->ref_count
== 0 ) {
198 SHOW_FLOW( 3, "image %s not in use anymore", image
->name
);
200 if( image
->keep_loaded
)
203 SHOW_FLOW( 1, "unloading image... %s", image
->path
);
204 elf_unload_kspace( image
->path
);
205 SHOW_FLOW0( 1, "...done" );
207 unregister_module_image( image
);
211 static inline void unregister_module( module_info
*module
)
213 SHOW_FLOW( 3, "%s", module
->header
->name
);
214 hash_remove( modules_list
, module
);
216 put_module_image( module
->image
);
222 static inline module_image
*register_module_image_int( const char *image_name
, const char *path
,
223 int base_path_id
, module_header
**headers
, bool keep_loaded
)
227 image
= (module_image
*)kmalloc( sizeof( module_image
));
232 memset( image
, 0, sizeof( image
));
233 image
->ref_count
= 1;
234 image
->keep_loaded
= keep_loaded
;
235 image
->name
= kstrdup( image_name
);
236 if( image
->name
== NULL
)
239 image
->path
= kstrdup( path
);
240 if( image
->path
== NULL
)
243 image
->base_path_id
= base_path_id
;
244 image
->headers
= headers
;
246 SHOW_FLOW( 3, "adding image to hash %i", base_path_id
);
247 if( hash_insert( modules_images
[base_path_id
], image
) != NO_ERROR
)
253 kfree( image
->path
);
255 kfree( image
->name
);
261 static module_image
*register_module_image( const char *image_name
, const char *path
,
262 int base_path_id
, module_header
**headers
, bool keep_loaded
)
265 module_header
**header
;
267 SHOW_FLOW( 3, "module %s", image_name
);
269 image
= register_module_image_int( image_name
, path
, base_path_id
, headers
, keep_loaded
);
273 for( header
= image
->headers
; *header
; ++header
) {
274 if( strncmp( (*header
)->name
, image
->name
, strlen( image
->name
)) != 0 )
275 SHOW_INFO( 0, "module %s stored in wrong image (%s)", (*header
)->name
, image
->name
);
281 static inline module_image
*load_module_image( const char *image_name
, const char *path
, int base_path_id
)
284 module_header
**headers
;
287 SHOW_FLOW( 2, "loading %s", path
);
289 file_image
= elf_load_kspace( path
, "" );
291 if( file_image
< 0 ) {
292 SHOW_FLOW( 3, "couldn't load image %s (%s)", path
, strerror( file_image
));
296 headers
= (module_header
**)elf_lookup_symbol( file_image
, "modules" );
298 if( headers
== NULL
) {
299 SHOW_INFO( 0, "image %s has no interface", path
);
300 elf_unload_kspace( path
);
304 SHOW_FLOW( 1, "loaded image %s", image_name
);
306 image
= register_module_image( image_name
, path
, base_path_id
, headers
, false );
308 if( image
== NULL
) {
309 elf_unload_kspace( path
);
316 static inline module_header
*find_module_in_image( module_image
*image
, const char *name
)
318 module_header
**header
;
320 for( header
= image
->headers
; *header
; ++header
) {
321 if( strcmp( (*header
)->name
, name
) == 0 ) {
322 SHOW_FLOW( 3, "found module %s in image %s", name
, image
->name
);
327 SHOW_FLOW( 3, "cannot find module %s in image %s", name
, image
->name
);
331 static module_image
*get_module_image( const char *name
, size_t name_len
, int base_path_id
)
333 char path
[SYS_MAX_PATH_LEN
];
338 if( base_path_id
== 0 && modules_disable_user_addons
) {
339 SHOW_FLOW0( 3, "ignored - user add-ons are disabled" );
343 total_len
= min( name_len
, SYS_MAX_PATH_LEN
) + 1;
344 memcpy( path
, name
, total_len
- 1 );
345 path
[total_len
- 1] = 0;
347 SHOW_FLOW( 3, "%s", path
);
349 image
= hash_lookup( modules_images
[base_path_id
], (void *)path
);
352 SHOW_FLOW0( 3, "image already loaded" );
357 total_len
= strlen( module_paths
[base_path_id
] ) + 1 + name_len
+ 1;
359 if( total_len
> SYS_MAX_PATH_LEN
) {
360 SHOW_FLOW0( 3, "ups, path too long" );
364 strcpy( path
, module_paths
[base_path_id
] );
366 rel_name
= path
+ strlen( path
);
368 strncat( path
, name
, name_len
);
369 path
[total_len
- 1] = 0;
371 SHOW_FLOW( 3, "trying to load %s", path
);
373 image
= load_module_image( rel_name
, path
, base_path_id
);
377 static module_info
*search_module( const char *name
)
382 SHOW_FLOW( 3, "name: %s", name
);
384 module
= hash_lookup( modules_list
, (void *)name
);
386 if( module
!= NULL
) {
387 SHOW_FLOW0( 3, "already loaded" );
393 SHOW_FLOW0( 3, "try to load it" );
394 pos
= strlen( name
);
399 for( i
= 0; i
< (int)num_module_paths
; ++i
) {
402 image
= get_module_image( name
, pos
, i
);
405 module_header
*header
;
407 SHOW_FLOW0( 3, "got image" );
409 header
= find_module_in_image( image
, name
);
411 SHOW_FLOW0( 3, "got header" );
413 module
= register_module( image
, header
);
415 put_module_image( image
);
419 put_module_image( image
);
425 while( pos
> 0 && name
[pos
] != '/' )
432 static inline int init_module( module_info
*module
)
436 switch( module
->state
) {
438 module
->state
= module_initializing
;
439 SHOW_FLOW( 3, "initing module %s... ", module
->header
->name
);
440 res
= module
->header
->init();
441 SHOW_FLOW( 3, "...done (%s)", strerror( res
));
444 module
->state
= module_ready
;
446 module
->state
= module_loaded
;
453 case module_initializing
:
454 SHOW_ERROR( 0, "circular reference to %s", module
->header
->name
);
458 case module_uninitializing
:
459 SHOW_ERROR( 0, "tried to load module %s which is currently unloading", module
->header
->name
);
463 case module_err_uninit
:
464 SHOW_INFO( 0, "cannot load module %s because its earlier unloading failed", module
->header
->name
);
475 static inline int uninit_module( module_info
*module
)
477 switch( module
->state
) {
481 case module_initializing
:
482 panic( "Trying to unload module %s which is initializing",
483 module
->header
->name
);
486 case module_uninitializing
:
487 panic( "Trying to unload module %s which is un-initializing", module
->header
->name
);
494 module
->state
= module_uninitializing
;
496 SHOW_FLOW( 2, "uniniting module %s...", module
->header
->name
);
497 res
= module
->header
->uninit();
498 SHOW_FLOW( 2, "...done (%s)", strerror( res
));
500 if( res
== NO_ERROR
) {
501 module
->state
= module_loaded
;
505 SHOW_ERROR( 0, "Error unloading module %s (%i)", module
->header
->name
, res
);
508 module
->state
= module_err_uninit
;
509 module
->keep_loaded
= true;
510 module
->image
->keep_loaded
= true;
518 static int put_module_info( module_info
*module
)
522 if( --module
->ref_count
!= 0 )
525 SHOW_FLOW( 2, "module %s not in use anymore", module
->header
->name
);
527 if( module
->keep_loaded
)
530 res
= uninit_module( module
);
532 if( res
== NO_ERROR
)
533 unregister_module( module
);
538 int module_get( const char *name
, int flags
, void **interface
)
543 SHOW_FLOW( 0, "name=%s, flags=%i", name
, flags
);
546 return ERR_INVALID_ARGS
;
548 recursive_lock_lock( &modules_lock
);
550 module
= search_module( name
);
553 SHOW_FLOW( 3, "couldn't find module %s", name
);
558 SHOW_FLOW0( 3, "make sure module is ready" );
559 res
= init_module( module
);
561 if( res
!= NO_ERROR
)
564 SHOW_FLOW0( 3, "module's ready to use" );
566 *interface
= module
->header
->interface
;
568 recursive_lock_unlock( &modules_lock
);
572 put_module_info( module
);
574 recursive_lock_unlock( &modules_lock
);
578 int module_put( const char *name
)
583 SHOW_FLOW( 0, "name=%s", name
);
585 recursive_lock_lock( &modules_lock
);
587 module
= hash_lookup( modules_list
, (void *)name
);
588 if( module
== NULL
) {
593 res
= put_module_info( module
);
596 recursive_lock_unlock( &modules_lock
);
601 typedef struct module_iterator
{
603 module_image
*cur_image
;
604 module_header
**cur_header
;
606 struct module_dir_iterator
*base_dir
, *cur_dir
;
609 unsigned int prefix_base_path_id
;
612 typedef struct module_dir_iterator
{
613 struct module_dir_iterator
*parent_dir
, *sub_dir
;
616 } module_dir_iterator
;
619 modules_cookie
module_open_list( const char *prefix
)
621 module_iterator
*iter
;
623 SHOW_FLOW( 3, "prefix: %s", prefix
);
625 if( (iter
= kmalloc( sizeof( *iter
))) == NULL
)
628 iter
->prefix
= kstrdup( prefix
);
634 /*iter->cur_image = module_sys_image;
635 ++module_sys_image->ref_count;
636 iter->cur_header = iter->cur_image->headers;*/
637 iter
->cur_image
= NULL
;
638 iter
->cur_header
= NULL
;
640 iter
->base_path_id
= -1;
641 iter
->base_dir
= iter
->cur_dir
= NULL
;
642 iter
->err
= NO_ERROR
;
643 iter
->prefix_pos
= strlen( prefix
);
645 iter
->prefix_base_path_id
= 0;
647 return (modules_cookie
)iter
;
651 static inline int module_enter_image( module_iterator
*iter
, const char *image_name
)
655 SHOW_FLOW( 3, "%s", image_name
);
657 image
= get_module_image( image_name
, strlen( image_name
), iter
->base_path_id
);
659 if( image
== NULL
) {
660 SHOW_FLOW( 3, "cannot get image %s", image_name
);
665 iter
->cur_image
= image
;
666 iter
->cur_header
= image
->headers
;
668 SHOW_FLOW( 3, "entered image %s", image_name
);
672 static inline int module_create_dir_iterator( module_iterator
*iter
, int file
, const char *name
)
674 module_dir_iterator
*dir
;
676 dir
= kmalloc( sizeof( *dir
));
678 return ERR_NO_MEMORY
;
680 dir
->name
= kstrdup( name
);
681 if( dir
->name
== NULL
) {
683 return ERR_NO_MEMORY
;
689 dir
->parent_dir
= iter
->cur_dir
;
692 iter
->cur_dir
->sub_dir
= dir
;
694 iter
->base_dir
= dir
;
698 SHOW_FLOW( 3, "created dir iterator for %s", name
);
702 static inline int module_enter_dir( module_iterator
*iter
, const char *path
, const char *name
)
707 file
= sys_opendir( path
);
709 SHOW_FLOW( 3, "couldn't open directory %s (%s)", path
, strerror( file
));
711 // there are so many errors for "not found" that we don't bother
712 // and always assume that the directory suddenly disappeared
716 res
= module_create_dir_iterator( iter
, file
, name
);
717 if( res
!= NO_ERROR
) {
718 sys_closedir( file
);
719 return ERR_NO_MEMORY
;
722 SHOW_FLOW( 3, "entered directory %s", path
);
727 static inline void destroy_dir_iterator( module_iterator
*iter
)
729 module_dir_iterator
*dir
;
733 SHOW_FLOW( 3, "destroying directory iterator for sub-dir %s", dir
->name
);
735 if( dir
->parent_dir
)
736 dir
->parent_dir
->sub_dir
= NULL
;
738 iter
->cur_dir
= dir
->parent_dir
;
745 static inline void module_leave_dir( module_iterator
*iter
)
747 module_dir_iterator
*parent_dir
;
749 SHOW_FLOW( 3, "leaving directory %s", iter
->cur_dir
->name
);
751 parent_dir
= iter
->cur_dir
->parent_dir
;
753 sys_closedir( iter
->cur_dir
->file
);
754 destroy_dir_iterator( iter
);
756 iter
->cur_dir
= parent_dir
;
759 static void compose_path( char *path
, module_iterator
*iter
, const char *name
, bool full_path
)
761 module_dir_iterator
*dir
;
764 strlcpy( path
, iter
->base_dir
->name
, SYS_MAX_PATH_LEN
);
765 strlcat( path
, "/", SYS_MAX_PATH_LEN
);
767 strlcpy( path
, iter
->prefix
, SYS_MAX_PATH_LEN
);
769 strlcat( path
, "/", SYS_MAX_PATH_LEN
);
772 for( dir
= iter
->base_dir
->sub_dir
; dir
; dir
= dir
->sub_dir
) {
773 strlcat( path
, dir
->name
, SYS_MAX_PATH_LEN
);
774 strlcat( path
, "/", SYS_MAX_PATH_LEN
);
777 strlcat( path
, name
, SYS_MAX_PATH_LEN
);
779 SHOW_FLOW( 3, "name: %s, %s -> %s", name
,
780 full_path
? "full path" : "relative path",
785 static inline int module_traverse_dir( module_iterator
*iter
)
788 struct file_stat stat
;
789 char name
[SYS_MAX_NAME_LEN
];
790 char path
[SYS_MAX_PATH_LEN
];
792 SHOW_FLOW( 3, "scanning %s", iter
->cur_dir
->name
);
794 if( (res
= sys_readdir( iter
->cur_dir
->file
, name
, sizeof( name
))) <= 0 ) {
795 SHOW_FLOW( 3, "got error: %s", strerror( res
));
796 module_leave_dir( iter
);
800 SHOW_FLOW( 3, "got %s", name
);
802 if( strcmp( name
, "." ) == 0 ||
803 strcmp( name
, ".." ) == 0 )
806 // currently, sys_read returns an error if buffer is too small
807 // I don't know the official specification, so it's always safe
808 // to add a trailing end-of-string
809 name
[sizeof(name
) - 1] = 0;
811 compose_path( path
, iter
, name
, true );
813 if( (res
= sys_rstat( path
, &stat
)) != NO_ERROR
)
816 switch( stat
.type
) {
817 case STREAM_TYPE_FILE
:
818 compose_path( path
, iter
, name
, false );
820 return module_enter_image( iter
, path
);
822 case STREAM_TYPE_DIR
:
823 return module_enter_dir( iter
, path
, name
);
826 SHOW_FLOW( 3, "entry %s not a file nor a directory - ignored", name
);
832 static inline int module_enter_master_image( module_iterator
*iter
)
838 if( iter
->prefix_base_path_id
>= num_module_paths
) {
840 SHOW_FLOW0( 3, "reducing image name" );
844 iter
->prefix_pos
> 0 &&
845 iter
->prefix
[iter
->prefix_pos
] != '/' )
850 iter
->prefix_base_path_id
= 0;
852 if( iter
->prefix_pos
< 0 ) {
853 SHOW_FLOW0( 3, "no possible master image left" );
858 SHOW_FLOW0( 3, "trying new image" );
859 image
= get_module_image( iter
->prefix
, iter
->prefix_pos
, iter
->prefix_base_path_id
);
861 ++iter
->prefix_base_path_id
;
864 SHOW_FLOW( 3, "got image %s", image
->name
);
866 iter
->cur_image
= image
;
867 iter
->cur_header
= image
->headers
;
873 static inline int module_enter_base_path( module_iterator
*iter
)
875 char path
[SYS_MAX_PATH_LEN
];
878 ++iter
->base_path_id
;
880 if( iter
->base_path_id
>= (int)num_module_paths
) {
881 SHOW_FLOW0( 3, "no locations left" );
882 return ERR_NOT_FOUND
;
885 SHOW_FLOW( 3, "checking new base path (%s)", module_paths
[iter
->base_path_id
] );
887 if( iter
->base_path_id
== 0 && modules_disable_user_addons
) {
888 SHOW_FLOW0( 3, "ignoring user add-ons (they are disabled)" );
892 strcpy( path
, module_paths
[iter
->base_path_id
] );
893 if( *iter
->prefix
) {
895 strlcat( path
, iter
->prefix
, sizeof( path
));
898 res
= module_enter_dir( iter
, path
, path
);
903 static inline bool iter_check_module_header( module_iterator
*iter
)
906 module_image
*tmp_image
;
909 if( *iter
->cur_header
== NULL
) {
910 SHOW_FLOW0( 3, "reached end of modules list in image" );
912 put_module_image( iter
->cur_image
);
914 iter
->cur_header
= NULL
;
915 iter
->cur_image
= NULL
;
920 name
= (*iter
->cur_header
)->name
;
922 SHOW_FLOW( 3, "checking %s", name
);
924 if( strlen( name
) < strlen( iter
->prefix
) ||
925 memcmp( name
, iter
->prefix
, strlen( iter
->prefix
)) != 0 )
927 SHOW_FLOW( 3, "module %s has wrong prefix", name
);
933 module
= search_module( name
);
935 if( module
== NULL
) {
936 SHOW_FLOW( 3, "couldn't get module %s -> must be broken", name
);
942 SHOW_FLOW0( 3, "get rid of image" );
944 tmp_image
= module
->image
;
945 ++tmp_image
->ref_count
;
947 put_module_info( module
);
949 if( iter
->base_path_id
>= 0 ) {
950 if( strlen( tmp_image
->name
) < strlen( iter
->prefix
) ||
951 tmp_image
->base_path_id
!= iter
->base_path_id
)
953 if( strlen( tmp_image
->name
) < strlen( iter
->prefix
))
954 SHOW_FLOW( 3, "image name (%s) is shorter then prefix -> already scanned",
957 SHOW_FLOW( 3, "image (%s) is from wrong base path", tmp_image
->name
);
959 put_module_image( tmp_image
);
965 put_module_image( tmp_image
);
967 SHOW_FLOW( 3, "found module %s", name
);
971 int read_next_module_name( modules_cookie cookie
, char *buf
, size_t *bufsize
)
973 module_iterator
*iter
= (module_iterator
*)cookie
;
977 return ERR_INVALID_ARGS
;
981 while( res
== NO_ERROR
) {
982 if( iter
->cur_header
) {
983 SHOW_FLOW0( 3, "having image to scan" );
985 if( iter_check_module_header( iter
)) {
986 strlcpy( buf
, (*iter
->cur_header
)->name
, *bufsize
);
987 *bufsize
= strlen( buf
);
995 SHOW_FLOW0( 3, "looking for new image" );
997 if( iter
->cur_dir
== NULL
) {
998 if( iter
->prefix_pos
>= 0 )
999 res
= module_enter_master_image( iter
);
1001 res
= module_enter_base_path( iter
);
1003 res
= module_traverse_dir( iter
);
1009 SHOW_FLOW( 3, "finished with status %s", strerror( iter
->err
));
1014 int close_module_list( modules_cookie cookie
)
1016 module_iterator
*iter
= (module_iterator
*)cookie
;
1018 SHOW_FLOW0( 3, "" );
1021 return ERR_INVALID_ARGS
;
1023 while( iter
->cur_dir
)
1024 module_leave_dir( iter
);
1026 kfree( iter
->prefix
);
1031 module_header
*dummy
[] = { NULL
};
1034 int module_init( kernel_args
*ka
, module_header
**sys_module_headers
)
1038 SHOW_FLOW0( 0, "" );
1039 recursive_lock_create( &modules_lock
);
1041 modules_list
= hash_init( MODULES_HASH_SIZE
,
1042 offsetof( module_info
, next
),
1043 module_info_compare
, module_info_hash
);
1045 if( modules_list
== NULL
)
1046 return ERR_NO_MEMORY
;
1048 for( i
= 0; i
< num_module_paths
; ++i
) {
1049 modules_images
[i
] = hash_init( MODULES_HASH_SIZE
,
1050 offsetof( module_image
, next
),
1051 module_image_compare
, module_image_hash
);
1053 if( modules_images
[i
] == NULL
)
1054 return ERR_NO_MEMORY
;
1057 if( sys_module_headers
== NULL
)
1058 sys_module_headers
= dummy
;
1060 if( register_module_image( "", "(built-in)", 0, sys_module_headers
, true ) == NULL
)
1061 return ERR_NO_MEMORY
;
1063 // XXX: VERY VERY BAD LINK HACK!
1064 // we need to link all libc functions into kernel, but there are
1065 // some user space functions in libc that obviously must not be
1066 // added to the kernel image -> split libc in common and user space
1067 // only lib and force linking of entire common lib into kernel via
1070 // meanwhile, we make sure that nothing is missing by referencing all
1071 // functions manually (ouch!)
1077 dummy
= strerror( NO_ERROR
);
1083 isa_bus_manager
*isa_interface
;
1087 char module_name
[SYS_MAX_PATH_LEN
];
1089 const char prefix
[] = "bus_managers";
1090 modules_cookie modules_cookie
;
1092 if( (res
= module_get( ISA_MODULE_NAME
, 0, (void **)&isa_interface
)) != NO_ERROR
)
1093 dprintf( "Cannot load isa module (%s)", strerror( res
));
1095 for( i
= 'A'; i
<= 'Z'; ++i
)
1096 isa_interface
->write_io_8( 0xe9, i
);
1098 module_put( ISA_MODULE_NAME
);
1101 dprintf( "Getting modules with prefix %s", prefix
);
1102 modules_cookie
= module_open_list( prefix
);
1104 while( name_len
= sizeof( module_name
),
1105 read_next_module_name( modules_cookie
, module_name
, &name_len
) == NO_ERROR
)
1107 dprintf( "Found module %s", module_name
);
1110 close_module_list( modules_cookie
);
1119 module_get( "busses/ide/ide_isa", 0, &interface
);