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