1 /* 2 * This program is free software; you can redistribute it and/or 3 * modify it under the terms of the GNU General Public License as 4 * published by the Free Software Foundation; either version 2, or (at 5 * your option) any later version. 6 */ 7 8 #include "grub.h" 9 #include "pci.h" 10 #include "isa.h" 11 #include "nic.h" 12 13 #ifdef CONFIG_PCI 14 static int pci_probe(struct dev *dev, const char *type_name) 15 { 16 /* 17 * NIC probing is in pci device order, followed by the 18 * link order of the drivers. A driver that matches 19 * on vendor and device id will supersede a driver 20 * that matches on pci class. 21 * 22 * If you want to probe for another device behind the same pci 23 * device just increment index. And the previous probe call 24 * will be repeated. 25 */ 26 struct pci_probe_state *state = &dev->state.pci; 27 printf("Probing pci %s...\n", type_name); 28 if (dev->how_probe == PROBE_FIRST) { 29 state->advance = 1; 30 state->dev.driver = 0; 31 state->dev.bus = 0; 32 state->dev.devfn = 0; 33 dev->index = -1; 34 } 35 for(;;) { 36 if ((dev->how_probe != PROBE_AWAKE) && state->advance) { 37 find_pci(dev->type, &state->dev); 38 dev->index = -1; 39 } 40 state->advance = 1; 41 42 if (state->dev.driver == 0) 43 break; 44 45 #if 0 46 /* FIXME the romaddr code needs a total rethought to be useful */ 47 if (state->dev.romaddr != ((unsigned long) rom.rom_segment << 4)) { 48 continue; 49 } 50 #endif 51 if (dev->how_probe != PROBE_AWAKE) { 52 dev->type_index++; 53 } 54 dev->devid.bus_type = PCI_BUS_TYPE; 55 dev->devid.vendor_id = htons(state->dev.vendor); 56 dev->devid.device_id = htons(state->dev.dev_id); 57 /* FIXME how do I handle dev->index + PROBE_AGAIN?? */ 58 59 printf("[%s]", state->dev.name); 60 if (state->dev.driver->probe(dev, &state->dev)) { 61 state->advance = (dev->index == -1); 62 return PROBE_WORKED; 63 } 64 putchar('\n'); 65 } 66 return PROBE_FAILED; 67 } 68 #endif 69 70 #ifdef CONFIG_ISA 71 static int isa_probe(struct dev *dev, const char *type_name) 72 { 73 /* 74 * NIC probing is in the order the drivers were linked togeter. 75 * If for some reason you want to change the order, 76 * just change the order you list the drivers in. 77 */ 78 struct isa_probe_state *state = &dev->state.isa; 79 printf("Probing isa %s...\n", type_name); 80 if (dev->how_probe == PROBE_FIRST) { 81 state->advance = 0; 82 state->driver = isa_drivers; 83 dev->index = -1; 84 } 85 for(;;) 86 { 87 if ((dev->how_probe != PROBE_AWAKE) && state->advance) { 88 state->driver++; 89 dev->index = -1; 90 } 91 state->advance = 1; 92 93 if (state->driver >= isa_drivers_end) 94 break; 95 96 if (state->driver->type != dev->type) 97 continue; 98 99 if (dev->how_probe != PROBE_AWAKE) { 100 dev->type_index++; 101 } 102 printf("[%s]", state->driver->name); 103 dev->devid.bus_type = ISA_BUS_TYPE; 104 /* FIXME how do I handle dev->index + PROBE_AGAIN?? */ 105 /* driver will fill in vendor and device IDs */ 106 if (state->driver->probe(dev, state->driver->ioaddrs)) { 107 state->advance = (dev->index == -1); 108 return PROBE_WORKED; 109 } 110 putchar('\n'); 111 } 112 return PROBE_FAILED; 113 } 114 #else 115 #define isa_probe(d,tn) (PROBE_FAILED) 116 #endif 117 static const char *driver_name[] = { 118 "nic", 119 "disk", 120 "floppy", 121 }; 122 int probe(struct dev *dev) 123 { 124 const char *type_name; 125 126 EnterFunction("probe"); 127 128 type_name = ""; 129 if ((dev->type >= 0) && 130 (dev->type < sizeof(driver_name)/sizeof(driver_name[0]))) { 131 type_name = driver_name[dev->type]; 132 } 133 if (dev->how_probe == PROBE_FIRST) { 134 dev->to_probe = PROBE_PCI; 135 memset(&dev->state, 0, sizeof(dev->state)); 136 } 137 if (dev->to_probe == PROBE_PCI) { 138 dev->how_probe = pci_probe(dev, type_name); 139 if (dev->how_probe == PROBE_FAILED) { 140 dev->to_probe = PROBE_ISA; 141 } 142 } 143 if (dev->to_probe == PROBE_ISA) { 144 dev->how_probe = isa_probe(dev, type_name); 145 if (dev->how_probe == PROBE_FAILED) { 146 dev->to_probe = PROBE_NONE; 147 } 148 } 149 if ((dev->to_probe != PROBE_PCI) && 150 (dev->to_probe != PROBE_ISA)) { 151 dev->how_probe = PROBE_FAILED; 152 153 } 154 155 LeaveFunction("probe"); 156 return dev->how_probe; 157 } 158 159 void disable(struct dev *dev) 160 { 161 if (dev->disable) { 162 dev->disable(dev); 163 dev->disable = 0; 164 } 165 } 166