isa.c
Go to the documentation of this file.00001 #include <stdint.h>
00002 #include <string.h>
00003 #include <stdlib.h>
00004 #include <stdio.h>
00005 #include <errno.h>
00006 #include <gpxe/io.h>
00007 #include <gpxe/isa.h>
00008
00009 FILE_LICENCE ( GPL2_OR_LATER );
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033 static isa_probe_addr_t isa_extra_probe_addrs[] = {
00034 #ifdef ISA_PROBE_ADDRS
00035 ISA_PROBE_ADDRS
00036 #endif
00037 };
00038 #define ISA_EXTRA_PROBE_ADDR_COUNT \
00039 ( sizeof ( isa_extra_probe_addrs ) / sizeof ( isa_extra_probe_addrs[0] ) )
00040
00041 #define ISA_IOIDX_MIN( driver ) ( -ISA_EXTRA_PROBE_ADDR_COUNT )
00042 #ifdef ISA_PROBE_ONLY
00043 #define ISA_IOIDX_MAX( driver ) ( -1 )
00044 #else
00045 #define ISA_IOIDX_MAX( driver ) ( (int) (driver)->addr_count - 1 )
00046 #endif
00047
00048 #define ISA_IOADDR( driver, ioidx ) \
00049 ( ( (ioidx) < 0 ) ? \
00050 isa_extra_probe_addrs[ (ioidx) + ISA_EXTRA_PROBE_ADDR_COUNT ] : \
00051 (driver)->probe_addrs[(ioidx)] )
00052
00053 static void isabus_remove ( struct root_device *rootdev );
00054
00055
00056
00057
00058
00059
00060
00061 static int isa_probe ( struct isa_device *isa ) {
00062 int rc;
00063
00064 DBG ( "Trying ISA driver %s at I/O %04x\n",
00065 isa->driver->name, isa->ioaddr );
00066
00067 if ( ( rc = isa->driver->probe ( isa ) ) != 0 ) {
00068 DBG ( "...probe failed\n" );
00069 return rc;
00070 }
00071
00072 DBG ( "...device found\n" );
00073 return 0;
00074 }
00075
00076
00077
00078
00079
00080
00081 static void isa_remove ( struct isa_device *isa ) {
00082 isa->driver->remove ( isa );
00083 DBG ( "Removed ISA%04x\n", isa->ioaddr );
00084 }
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094 static int isabus_probe ( struct root_device *rootdev ) {
00095 struct isa_device *isa = NULL;
00096 struct isa_driver *driver;
00097 int ioidx;
00098 int rc;
00099
00100 for_each_table_entry ( driver, ISA_DRIVERS ) {
00101 for ( ioidx = ISA_IOIDX_MIN ( driver ) ;
00102 ioidx <= ISA_IOIDX_MAX ( driver ) ; ioidx++ ) {
00103
00104 if ( ! isa )
00105 isa = malloc ( sizeof ( *isa ) );
00106 if ( ! isa ) {
00107 rc = -ENOMEM;
00108 goto err;
00109 }
00110 memset ( isa, 0, sizeof ( *isa ) );
00111 isa->driver = driver;
00112 isa->ioaddr = ISA_IOADDR ( driver, ioidx );
00113
00114
00115 snprintf ( isa->dev.name, sizeof ( isa->dev.name ),
00116 "ISA%04x", isa->ioaddr );
00117 isa->dev.desc.bus_type = BUS_TYPE_ISA;
00118 isa->dev.desc.vendor = driver->vendor_id;
00119 isa->dev.desc.device = driver->prod_id;
00120 isa->dev.parent = &rootdev->dev;
00121 list_add ( &isa->dev.siblings,
00122 &rootdev->dev.children );
00123 INIT_LIST_HEAD ( &isa->dev.children );
00124
00125
00126 if ( isa_probe ( isa ) == 0 ) {
00127
00128 isa = NULL;
00129 } else {
00130
00131 list_del ( &isa->dev.siblings );
00132 }
00133 }
00134 }
00135
00136 free ( isa );
00137 return 0;
00138
00139 err:
00140 free ( isa );
00141 isabus_remove ( rootdev );
00142 return rc;
00143 }
00144
00145
00146
00147
00148
00149
00150 static void isabus_remove ( struct root_device *rootdev ) {
00151 struct isa_device *isa;
00152 struct isa_device *tmp;
00153
00154 list_for_each_entry_safe ( isa, tmp, &rootdev->dev.children,
00155 dev.siblings ) {
00156 isa_remove ( isa );
00157 list_del ( &isa->dev.siblings );
00158 free ( isa );
00159 }
00160 }
00161
00162
00163 static struct root_driver isa_root_driver = {
00164 .probe = isabus_probe,
00165 .remove = isabus_remove,
00166 };
00167
00168
00169 struct root_device isa_root_device __root_device = {
00170 .dev = { .name = "ISA" },
00171 .driver = &isa_root_driver,
00172 };