|
|
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 <unistd.h> ! 8: #include <ipxe/eisa.h> ! 9: ! 10: FILE_LICENCE ( GPL2_OR_LATER ); ! 11: ! 12: static void eisabus_remove ( struct root_device *rootdev ); ! 13: ! 14: /** ! 15: * Reset and enable/disable an EISA device ! 16: * ! 17: * @v eisa EISA device ! 18: * @v enabled 1=enable, 0=disable ! 19: */ ! 20: void eisa_device_enabled ( struct eisa_device *eisa, int enabled ) { ! 21: /* Set reset line high for 1000 �s. Spec says 500 �s, but ! 22: * this doesn't work for all cards, so we are conservative. ! 23: */ ! 24: outb ( EISA_CMD_RESET, eisa->ioaddr + EISA_GLOBAL_CONFIG ); ! 25: udelay ( 1000 ); /* Must wait 800 */ ! 26: ! 27: /* Set reset low and write a 1 to ENABLE. Delay again, in ! 28: * case the card takes a while to wake up. ! 29: */ ! 30: outb ( enabled ? EISA_CMD_ENABLE : 0, ! 31: eisa->ioaddr + EISA_GLOBAL_CONFIG ); ! 32: udelay ( 1000 ); /* Must wait 800 */ ! 33: ! 34: DBG ( "EISA %s device %02x\n", ( enabled ? "enabled" : "disabled" ), ! 35: eisa->slot ); ! 36: } ! 37: ! 38: /** ! 39: * Probe an EISA device ! 40: * ! 41: * @v eisa EISA device ! 42: * @ret rc Return status code ! 43: * ! 44: * Searches for a driver for the EISA device. If a driver is found, ! 45: * its probe() routine is called. ! 46: */ ! 47: static int eisa_probe ( struct eisa_device *eisa ) { ! 48: struct eisa_driver *driver; ! 49: struct eisa_device_id *id; ! 50: unsigned int i; ! 51: int rc; ! 52: ! 53: DBG ( "Adding EISA device %02x (%04x:%04x (\"%s\") io %x)\n", ! 54: eisa->slot, eisa->vendor_id, eisa->prod_id, ! 55: isa_id_string ( eisa->vendor_id, eisa->prod_id ), eisa->ioaddr ); ! 56: ! 57: for_each_table_entry ( driver, EISA_DRIVERS ) { ! 58: for ( i = 0 ; i < driver->id_count ; i++ ) { ! 59: id = &driver->ids[i]; ! 60: if ( id->vendor_id != eisa->vendor_id ) ! 61: continue; ! 62: if ( ISA_PROD_ID ( id->prod_id ) != ! 63: ISA_PROD_ID ( eisa->prod_id ) ) ! 64: continue; ! 65: eisa->driver = driver; ! 66: eisa->dev.driver_name = id->name; ! 67: DBG ( "...using driver %s\n", eisa->dev.driver_name ); ! 68: if ( ( rc = driver->probe ( eisa, id ) ) != 0 ) { ! 69: DBG ( "......probe failed\n" ); ! 70: continue; ! 71: } ! 72: return 0; ! 73: } ! 74: } ! 75: ! 76: DBG ( "...no driver found\n" ); ! 77: return -ENOTTY; ! 78: } ! 79: ! 80: /** ! 81: * Remove an EISA device ! 82: * ! 83: * @v eisa EISA device ! 84: */ ! 85: static void eisa_remove ( struct eisa_device *eisa ) { ! 86: eisa->driver->remove ( eisa ); ! 87: DBG ( "Removed EISA device %02x\n", eisa->slot ); ! 88: } ! 89: ! 90: /** ! 91: * Probe EISA root bus ! 92: * ! 93: * @v rootdev EISA bus root device ! 94: * ! 95: * Scans the EISA bus for devices and registers all devices it can ! 96: * find. ! 97: */ ! 98: static int eisabus_probe ( struct root_device *rootdev ) { ! 99: struct eisa_device *eisa = NULL; ! 100: unsigned int slot; ! 101: int rc; ! 102: ! 103: for ( slot = EISA_MIN_SLOT ; slot <= EISA_MAX_SLOT ; slot++ ) { ! 104: /* Allocate struct eisa_device */ ! 105: if ( ! eisa ) ! 106: eisa = malloc ( sizeof ( *eisa ) ); ! 107: if ( ! eisa ) { ! 108: rc = -ENOMEM; ! 109: goto err; ! 110: } ! 111: memset ( eisa, 0, sizeof ( *eisa ) ); ! 112: eisa->slot = slot; ! 113: eisa->ioaddr = EISA_SLOT_BASE ( eisa->slot ); ! 114: ! 115: /* Test for board present */ ! 116: outb ( 0xff, eisa->ioaddr + EISA_VENDOR_ID ); ! 117: eisa->vendor_id = ! 118: le16_to_cpu ( inw ( eisa->ioaddr + EISA_VENDOR_ID ) ); ! 119: eisa->prod_id = ! 120: le16_to_cpu ( inw ( eisa->ioaddr + EISA_PROD_ID ) ); ! 121: if ( eisa->vendor_id & 0x80 ) { ! 122: /* No board present */ ! 123: continue; ! 124: } ! 125: ! 126: /* Add to device hierarchy */ ! 127: snprintf ( eisa->dev.name, sizeof ( eisa->dev.name ), ! 128: "EISA%02x", slot ); ! 129: eisa->dev.desc.bus_type = BUS_TYPE_EISA; ! 130: eisa->dev.desc.vendor = eisa->vendor_id; ! 131: eisa->dev.desc.device = eisa->prod_id; ! 132: eisa->dev.parent = &rootdev->dev; ! 133: list_add ( &eisa->dev.siblings, &rootdev->dev.children ); ! 134: INIT_LIST_HEAD ( &eisa->dev.children ); ! 135: ! 136: /* Look for a driver */ ! 137: if ( eisa_probe ( eisa ) == 0 ) { ! 138: /* eisadev registered, we can drop our ref */ ! 139: eisa = NULL; ! 140: } else { ! 141: /* Not registered; re-use struct */ ! 142: list_del ( &eisa->dev.siblings ); ! 143: } ! 144: } ! 145: ! 146: free ( eisa ); ! 147: return 0; ! 148: ! 149: err: ! 150: free ( eisa ); ! 151: eisabus_remove ( rootdev ); ! 152: return rc; ! 153: } ! 154: ! 155: /** ! 156: * Remove EISA root bus ! 157: * ! 158: * @v rootdev EISA bus root device ! 159: */ ! 160: static void eisabus_remove ( struct root_device *rootdev ) { ! 161: struct eisa_device *eisa; ! 162: struct eisa_device *tmp; ! 163: ! 164: list_for_each_entry_safe ( eisa, tmp, &rootdev->dev.children, ! 165: dev.siblings ) { ! 166: eisa_remove ( eisa ); ! 167: list_del ( &eisa->dev.siblings ); ! 168: free ( eisa ); ! 169: } ! 170: } ! 171: ! 172: /** EISA bus root device driver */ ! 173: static struct root_driver eisa_root_driver = { ! 174: .probe = eisabus_probe, ! 175: .remove = eisabus_remove, ! 176: }; ! 177: ! 178: /** EISA bus root device */ ! 179: struct root_device eisa_root_device __root_device = { ! 180: .dev = { .name = "EISA" }, ! 181: .driver = &eisa_root_driver, ! 182: };
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.