|
|
1.1 ! root 1: #include <stdint.h> ! 2: #include <string.h> ! 3: #include <stdlib.h> ! 4: #include <stdio.h> ! 5: #include <errno.h> ! 6: #include <ipxe/io.h> ! 7: #include <ipxe/isa.h> ! 8: ! 9: FILE_LICENCE ( GPL2_OR_LATER ); ! 10: ! 11: /* ! 12: * isa.c implements a "classical" port-scanning method of ISA device ! 13: * detection. The driver must provide a list of probe addresses ! 14: * (probe_addrs), together with a function (probe_addr) that can be ! 15: * used to test for the physical presence of a device at any given ! 16: * address. ! 17: * ! 18: * Note that this should probably be considered the "last resort" for ! 19: * device probing. If the card supports ISAPnP or EISA, use that ! 20: * instead. Some cards (e.g. the 3c509) implement a proprietary ! 21: * ISAPnP-like mechanism. ! 22: * ! 23: * The ISA probe address list can be overridden by config.h; if the ! 24: * user specifies ISA_PROBE_ADDRS then that list will be used first. ! 25: * (If ISA_PROBE_ONLY is defined, the driver's own list will never be ! 26: * used). ! 27: */ ! 28: ! 29: /* ! 30: * User-supplied probe address list ! 31: * ! 32: */ ! 33: static isa_probe_addr_t isa_extra_probe_addrs[] = { ! 34: #ifdef ISA_PROBE_ADDRS ! 35: ISA_PROBE_ADDRS ! 36: #endif ! 37: }; ! 38: #define ISA_EXTRA_PROBE_ADDR_COUNT \ ! 39: ( sizeof ( isa_extra_probe_addrs ) / sizeof ( isa_extra_probe_addrs[0] ) ) ! 40: ! 41: #define ISA_IOIDX_MIN( driver ) ( -ISA_EXTRA_PROBE_ADDR_COUNT ) ! 42: #ifdef ISA_PROBE_ONLY ! 43: #define ISA_IOIDX_MAX( driver ) ( -1 ) ! 44: #else ! 45: #define ISA_IOIDX_MAX( driver ) ( (int) (driver)->addr_count - 1 ) ! 46: #endif ! 47: ! 48: #define ISA_IOADDR( driver, ioidx ) \ ! 49: ( ( (ioidx) < 0 ) ? \ ! 50: isa_extra_probe_addrs[ (ioidx) + ISA_EXTRA_PROBE_ADDR_COUNT ] : \ ! 51: (driver)->probe_addrs[(ioidx)] ) ! 52: ! 53: static void isabus_remove ( struct root_device *rootdev ); ! 54: ! 55: /** ! 56: * Probe an ISA device ! 57: * ! 58: * @v isa ISA device ! 59: * @ret rc Return status code ! 60: */ ! 61: static int isa_probe ( struct isa_device *isa ) { ! 62: int rc; ! 63: ! 64: DBG ( "Trying ISA driver %s at I/O %04x\n", ! 65: isa->driver->name, isa->ioaddr ); ! 66: ! 67: if ( ( rc = isa->driver->probe ( isa ) ) != 0 ) { ! 68: DBG ( "...probe failed\n" ); ! 69: return rc; ! 70: } ! 71: ! 72: DBG ( "...device found\n" ); ! 73: return 0; ! 74: } ! 75: ! 76: /** ! 77: * Remove an ISA device ! 78: * ! 79: * @v isa ISA device ! 80: */ ! 81: static void isa_remove ( struct isa_device *isa ) { ! 82: isa->driver->remove ( isa ); ! 83: DBG ( "Removed ISA%04x\n", isa->ioaddr ); ! 84: } ! 85: ! 86: /** ! 87: * Probe ISA root bus ! 88: * ! 89: * @v rootdev ISA bus root device ! 90: * ! 91: * Scans the ISA bus for devices and registers all devices it can ! 92: * find. ! 93: */ ! 94: static int isabus_probe ( struct root_device *rootdev ) { ! 95: struct isa_device *isa = NULL; ! 96: struct isa_driver *driver; ! 97: int ioidx; ! 98: int rc; ! 99: ! 100: for_each_table_entry ( driver, ISA_DRIVERS ) { ! 101: for ( ioidx = ISA_IOIDX_MIN ( driver ) ; ! 102: ioidx <= ISA_IOIDX_MAX ( driver ) ; ioidx++ ) { ! 103: /* Allocate struct isa_device */ ! 104: if ( ! isa ) ! 105: isa = malloc ( sizeof ( *isa ) ); ! 106: if ( ! isa ) { ! 107: rc = -ENOMEM; ! 108: goto err; ! 109: } ! 110: memset ( isa, 0, sizeof ( *isa ) ); ! 111: isa->driver = driver; ! 112: isa->ioaddr = ISA_IOADDR ( driver, ioidx ); ! 113: ! 114: /* Add to device hierarchy */ ! 115: snprintf ( isa->dev.name, sizeof ( isa->dev.name ), ! 116: "ISA%04x", isa->ioaddr ); ! 117: isa->dev.driver_name = driver->name; ! 118: isa->dev.desc.bus_type = BUS_TYPE_ISA; ! 119: isa->dev.desc.vendor = driver->vendor_id; ! 120: isa->dev.desc.device = driver->prod_id; ! 121: isa->dev.parent = &rootdev->dev; ! 122: list_add ( &isa->dev.siblings, ! 123: &rootdev->dev.children ); ! 124: INIT_LIST_HEAD ( &isa->dev.children ); ! 125: ! 126: /* Try probing at this I/O address */ ! 127: if ( isa_probe ( isa ) == 0 ) { ! 128: /* isadev registered, we can drop our ref */ ! 129: isa = NULL; ! 130: } else { ! 131: /* Not registered; re-use struct */ ! 132: list_del ( &isa->dev.siblings ); ! 133: } ! 134: } ! 135: } ! 136: ! 137: free ( isa ); ! 138: return 0; ! 139: ! 140: err: ! 141: free ( isa ); ! 142: isabus_remove ( rootdev ); ! 143: return rc; ! 144: } ! 145: ! 146: /** ! 147: * Remove ISA root bus ! 148: * ! 149: * @v rootdev ISA bus root device ! 150: */ ! 151: static void isabus_remove ( struct root_device *rootdev ) { ! 152: struct isa_device *isa; ! 153: struct isa_device *tmp; ! 154: ! 155: list_for_each_entry_safe ( isa, tmp, &rootdev->dev.children, ! 156: dev.siblings ) { ! 157: isa_remove ( isa ); ! 158: list_del ( &isa->dev.siblings ); ! 159: free ( isa ); ! 160: } ! 161: } ! 162: ! 163: /** ISA bus root device driver */ ! 164: static struct root_driver isa_root_driver = { ! 165: .probe = isabus_probe, ! 166: .remove = isabus_remove, ! 167: }; ! 168: ! 169: /** ISA bus root device */ ! 170: struct root_device isa_root_device __root_device = { ! 171: .dev = { .name = "ISA" }, ! 172: .driver = &isa_root_driver, ! 173: };
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.