|
|
1.1 ! root 1: /* ! 2: * MCA bus driver code ! 3: * ! 4: * Abstracted from 3c509.c. ! 5: * ! 6: */ ! 7: ! 8: FILE_LICENCE ( BSD2 ); ! 9: ! 10: #include <stdint.h> ! 11: #include <string.h> ! 12: #include <stdlib.h> ! 13: #include <stdio.h> ! 14: #include <errno.h> ! 15: #include <ipxe/io.h> ! 16: #include <ipxe/mca.h> ! 17: ! 18: static void mcabus_remove ( struct root_device *rootdev ); ! 19: ! 20: /** ! 21: * Probe an MCA device ! 22: * ! 23: * @v mca MCA device ! 24: * @ret rc Return status code ! 25: * ! 26: * Searches for a driver for the MCA device. If a driver is found, ! 27: * its probe() routine is called. ! 28: */ ! 29: static int mca_probe ( struct mca_device *mca ) { ! 30: struct mca_driver *driver; ! 31: struct mca_device_id *id; ! 32: unsigned int i; ! 33: int rc; ! 34: ! 35: DBG ( "Adding MCA slot %02x (ID %04x POS " ! 36: "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x)\n", ! 37: mca->slot, MCA_ID ( mca ), ! 38: mca->pos[0], mca->pos[1], mca->pos[2], mca->pos[3], ! 39: mca->pos[4], mca->pos[5], mca->pos[6], mca->pos[7] ); ! 40: ! 41: for_each_table_entry ( driver, MCA_DRIVERS ) { ! 42: for ( i = 0 ; i < driver->id_count ; i++ ) { ! 43: id = &driver->ids[i]; ! 44: if ( id->id != MCA_ID ( mca ) ) ! 45: continue; ! 46: mca->driver = driver; ! 47: mca->dev.driver_name = id->name; ! 48: DBG ( "...using driver %s\n", mca->dev.driver_name ); ! 49: if ( ( rc = driver->probe ( mca, id ) ) != 0 ) { ! 50: DBG ( "......probe failed\n" ); ! 51: continue; ! 52: } ! 53: return 0; ! 54: } ! 55: } ! 56: ! 57: DBG ( "...no driver found\n" ); ! 58: return -ENOTTY; ! 59: } ! 60: ! 61: /** ! 62: * Remove an MCA device ! 63: * ! 64: * @v mca MCA device ! 65: */ ! 66: static void mca_remove ( struct mca_device *mca ) { ! 67: mca->driver->remove ( mca ); ! 68: DBG ( "Removed MCA device %02x\n", mca->slot ); ! 69: } ! 70: ! 71: /** ! 72: * Probe MCA root bus ! 73: * ! 74: * @v rootdev MCA bus root device ! 75: * ! 76: * Scans the MCA bus for devices and registers all devices it can ! 77: * find. ! 78: */ ! 79: static int mcabus_probe ( struct root_device *rootdev ) { ! 80: struct mca_device *mca = NULL; ! 81: unsigned int slot; ! 82: int seen_non_ff; ! 83: unsigned int i; ! 84: int rc; ! 85: ! 86: for ( slot = 0 ; slot <= MCA_MAX_SLOT_NR ; slot++ ) { ! 87: /* Allocate struct mca_device */ ! 88: if ( ! mca ) ! 89: mca = malloc ( sizeof ( *mca ) ); ! 90: if ( ! mca ) { ! 91: rc = -ENOMEM; ! 92: goto err; ! 93: } ! 94: memset ( mca, 0, sizeof ( *mca ) ); ! 95: mca->slot = slot; ! 96: ! 97: /* Make sure motherboard setup is off */ ! 98: outb_p ( 0xff, MCA_MOTHERBOARD_SETUP_REG ); ! 99: ! 100: /* Select the slot */ ! 101: outb_p ( 0x8 | ( mca->slot & 0xf ), MCA_ADAPTER_SETUP_REG ); ! 102: ! 103: /* Read the POS registers */ ! 104: seen_non_ff = 0; ! 105: for ( i = 0 ; i < ( sizeof ( mca->pos ) / ! 106: sizeof ( mca->pos[0] ) ) ; i++ ) { ! 107: mca->pos[i] = inb_p ( MCA_POS_REG ( i ) ); ! 108: if ( mca->pos[i] != 0xff ) ! 109: seen_non_ff = 1; ! 110: } ! 111: ! 112: /* Kill all setup modes */ ! 113: outb_p ( 0, MCA_ADAPTER_SETUP_REG ); ! 114: ! 115: /* If all POS registers are 0xff, this means there's no device ! 116: * present ! 117: */ ! 118: if ( ! seen_non_ff ) ! 119: continue; ! 120: ! 121: /* Add to device hierarchy */ ! 122: snprintf ( mca->dev.name, sizeof ( mca->dev.name ), ! 123: "MCA%02x", slot ); ! 124: mca->dev.desc.bus_type = BUS_TYPE_MCA; ! 125: mca->dev.desc.vendor = GENERIC_MCA_VENDOR; ! 126: mca->dev.desc.device = MCA_ID ( mca ); ! 127: mca->dev.parent = &rootdev->dev; ! 128: list_add ( &mca->dev.siblings, &rootdev->dev.children ); ! 129: INIT_LIST_HEAD ( &mca->dev.children ); ! 130: ! 131: /* Look for a driver */ ! 132: if ( mca_probe ( mca ) == 0 ) { ! 133: /* mcadev registered, we can drop our ref */ ! 134: mca = NULL; ! 135: } else { ! 136: /* Not registered; re-use struct */ ! 137: list_del ( &mca->dev.siblings ); ! 138: } ! 139: } ! 140: ! 141: free ( mca ); ! 142: return 0; ! 143: ! 144: err: ! 145: free ( mca ); ! 146: mcabus_remove ( rootdev ); ! 147: return rc; ! 148: } ! 149: ! 150: /** ! 151: * Remove MCA root bus ! 152: * ! 153: * @v rootdev MCA bus root device ! 154: */ ! 155: static void mcabus_remove ( struct root_device *rootdev ) { ! 156: struct mca_device *mca; ! 157: struct mca_device *tmp; ! 158: ! 159: list_for_each_entry_safe ( mca, tmp, &rootdev->dev.children, ! 160: dev.siblings ) { ! 161: mca_remove ( mca ); ! 162: list_del ( &mca->dev.siblings ); ! 163: free ( mca ); ! 164: } ! 165: } ! 166: ! 167: /** MCA bus root device driver */ ! 168: static struct root_driver mca_root_driver = { ! 169: .probe = mcabus_probe, ! 170: .remove = mcabus_remove, ! 171: }; ! 172: ! 173: /** MCA bus root device */ ! 174: struct root_device mca_root_device __root_device = { ! 175: .dev = { .name = "MCA" }, ! 176: .driver = &mca_root_driver, ! 177: };
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.