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
14static 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
71static 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
117static const char *driver_name[] = {
118	"nic",
119	"disk",
120	"floppy",
121};
122int 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
159void disable(struct dev *dev)
160{
161	if (dev->disable) {
162		dev->disable(dev);
163		dev->disable = 0;
164	}
165}
166