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
pci_probe(struct dev * dev,const char * type_name)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
isa_probe(struct dev * dev,const char * type_name)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 };
probe(struct dev * dev)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
disable(struct dev * dev)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