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
pci_probe(struct dev * dev,const char * type_name)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
isa_probe(struct dev * dev,const char * type_name)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 };
probe(struct dev * dev)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 
disable(struct dev * dev)159 void disable(struct dev *dev)
160 {
161 	if (dev->disable) {
162 		dev->disable(dev);
163 		dev->disable = 0;
164 	}
165 }
166