17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * This program is free software; you can redistribute it and/or
37c478bd9Sstevel@tonic-gate  * modify it under the terms of the GNU General Public License as
47c478bd9Sstevel@tonic-gate  * published by the Free Software Foundation; either version 2, or (at
57c478bd9Sstevel@tonic-gate  * your option) any later version.
67c478bd9Sstevel@tonic-gate  */
77c478bd9Sstevel@tonic-gate 
87c478bd9Sstevel@tonic-gate #include	"grub.h"
97c478bd9Sstevel@tonic-gate #include	"pci.h"
107c478bd9Sstevel@tonic-gate #include	"isa.h"
117c478bd9Sstevel@tonic-gate #include	"nic.h"
127c478bd9Sstevel@tonic-gate 
137c478bd9Sstevel@tonic-gate #ifdef CONFIG_PCI
pci_probe(struct dev * dev,const char * type_name)147c478bd9Sstevel@tonic-gate static int pci_probe(struct dev *dev, const char *type_name)
157c478bd9Sstevel@tonic-gate {
167c478bd9Sstevel@tonic-gate /*
177c478bd9Sstevel@tonic-gate  *	NIC probing is in pci device order, followed by the
187c478bd9Sstevel@tonic-gate  *      link order of the drivers.  A driver that matches
197c478bd9Sstevel@tonic-gate  *      on vendor and device id will supersede a driver
207c478bd9Sstevel@tonic-gate  *      that matches on pci class.
217c478bd9Sstevel@tonic-gate  *
227c478bd9Sstevel@tonic-gate  *	If you want to probe for another device behind the same pci
237c478bd9Sstevel@tonic-gate  *      device just increment index.  And the previous probe call
247c478bd9Sstevel@tonic-gate  *      will be repeated.
257c478bd9Sstevel@tonic-gate  */
267c478bd9Sstevel@tonic-gate 	struct pci_probe_state *state = &dev->state.pci;
277c478bd9Sstevel@tonic-gate 	printf("Probing pci %s...\n", type_name);
287c478bd9Sstevel@tonic-gate 	if (dev->how_probe == PROBE_FIRST) {
297c478bd9Sstevel@tonic-gate 		state->advance    = 1;
307c478bd9Sstevel@tonic-gate 		state->dev.driver = 0;
317c478bd9Sstevel@tonic-gate 		state->dev.bus    = 0;
327c478bd9Sstevel@tonic-gate 		state->dev.devfn  = 0;
337c478bd9Sstevel@tonic-gate 		dev->index        = -1;
347c478bd9Sstevel@tonic-gate 	}
357c478bd9Sstevel@tonic-gate 	for(;;) {
367c478bd9Sstevel@tonic-gate 		if ((dev->how_probe != PROBE_AWAKE) && state->advance) {
377c478bd9Sstevel@tonic-gate 			find_pci(dev->type, &state->dev);
387c478bd9Sstevel@tonic-gate 			dev->index = -1;
397c478bd9Sstevel@tonic-gate 		}
407c478bd9Sstevel@tonic-gate 		state->advance = 1;
417c478bd9Sstevel@tonic-gate 
427c478bd9Sstevel@tonic-gate 		if (state->dev.driver == 0)
437c478bd9Sstevel@tonic-gate 			break;
447c478bd9Sstevel@tonic-gate 
457c478bd9Sstevel@tonic-gate #if 0
467c478bd9Sstevel@tonic-gate 		/* FIXME the romaddr code needs a total rethought to be useful */
477c478bd9Sstevel@tonic-gate 		if (state->dev.romaddr != ((unsigned long) rom.rom_segment << 4)) {
487c478bd9Sstevel@tonic-gate 			continue;
497c478bd9Sstevel@tonic-gate 		}
507c478bd9Sstevel@tonic-gate #endif
517c478bd9Sstevel@tonic-gate 		if (dev->how_probe != PROBE_AWAKE) {
527c478bd9Sstevel@tonic-gate 			dev->type_index++;
537c478bd9Sstevel@tonic-gate 		}
547c478bd9Sstevel@tonic-gate 		dev->devid.bus_type = PCI_BUS_TYPE;
557c478bd9Sstevel@tonic-gate 		dev->devid.vendor_id = htons(state->dev.vendor);
567c478bd9Sstevel@tonic-gate 		dev->devid.device_id = htons(state->dev.dev_id);
577c478bd9Sstevel@tonic-gate 		/* FIXME how do I handle dev->index + PROBE_AGAIN?? */
587c478bd9Sstevel@tonic-gate 
597c478bd9Sstevel@tonic-gate 		printf("[%s]", state->dev.name);
607c478bd9Sstevel@tonic-gate 		if (state->dev.driver->probe(dev, &state->dev)) {
617c478bd9Sstevel@tonic-gate 			state->advance = (dev->index == -1);
627c478bd9Sstevel@tonic-gate 			return PROBE_WORKED;
637c478bd9Sstevel@tonic-gate 		}
647c478bd9Sstevel@tonic-gate 		putchar('\n');
657c478bd9Sstevel@tonic-gate 	}
667c478bd9Sstevel@tonic-gate 	return PROBE_FAILED;
677c478bd9Sstevel@tonic-gate }
687c478bd9Sstevel@tonic-gate #endif
697c478bd9Sstevel@tonic-gate 
707c478bd9Sstevel@tonic-gate #ifdef CONFIG_ISA
isa_probe(struct dev * dev,const char * type_name)717c478bd9Sstevel@tonic-gate static int isa_probe(struct dev *dev, const char *type_name)
727c478bd9Sstevel@tonic-gate {
737c478bd9Sstevel@tonic-gate /*
747c478bd9Sstevel@tonic-gate  *	NIC probing is in the order the drivers were linked togeter.
757c478bd9Sstevel@tonic-gate  *	If for some reason you want to change the order,
767c478bd9Sstevel@tonic-gate  *	just change the order you list the drivers in.
777c478bd9Sstevel@tonic-gate  */
787c478bd9Sstevel@tonic-gate 	struct isa_probe_state *state = &dev->state.isa;
797c478bd9Sstevel@tonic-gate 	printf("Probing isa %s...\n", type_name);
807c478bd9Sstevel@tonic-gate 	if (dev->how_probe == PROBE_FIRST) {
817c478bd9Sstevel@tonic-gate 		state->advance = 0;
827c478bd9Sstevel@tonic-gate 		state->driver  = isa_drivers;
837c478bd9Sstevel@tonic-gate 		dev->index     = -1;
847c478bd9Sstevel@tonic-gate 	}
857c478bd9Sstevel@tonic-gate 	for(;;)
867c478bd9Sstevel@tonic-gate 	{
877c478bd9Sstevel@tonic-gate 		if ((dev->how_probe != PROBE_AWAKE) && state->advance) {
887c478bd9Sstevel@tonic-gate 			state->driver++;
897c478bd9Sstevel@tonic-gate 			dev->index = -1;
907c478bd9Sstevel@tonic-gate 		}
917c478bd9Sstevel@tonic-gate 		state->advance = 1;
927c478bd9Sstevel@tonic-gate 
937c478bd9Sstevel@tonic-gate 		if (state->driver >= isa_drivers_end)
947c478bd9Sstevel@tonic-gate 			break;
957c478bd9Sstevel@tonic-gate 
967c478bd9Sstevel@tonic-gate 		if (state->driver->type != dev->type)
977c478bd9Sstevel@tonic-gate 			continue;
987c478bd9Sstevel@tonic-gate 
997c478bd9Sstevel@tonic-gate 		if (dev->how_probe != PROBE_AWAKE) {
1007c478bd9Sstevel@tonic-gate 			dev->type_index++;
1017c478bd9Sstevel@tonic-gate 		}
1027c478bd9Sstevel@tonic-gate 		printf("[%s]", state->driver->name);
1037c478bd9Sstevel@tonic-gate 		dev->devid.bus_type = ISA_BUS_TYPE;
1047c478bd9Sstevel@tonic-gate 		/* FIXME how do I handle dev->index + PROBE_AGAIN?? */
1057c478bd9Sstevel@tonic-gate 		/* driver will fill in vendor and device IDs */
1067c478bd9Sstevel@tonic-gate 		if (state->driver->probe(dev, state->driver->ioaddrs)) {
1077c478bd9Sstevel@tonic-gate 			state->advance = (dev->index == -1);
1087c478bd9Sstevel@tonic-gate 			return PROBE_WORKED;
1097c478bd9Sstevel@tonic-gate 		}
1107c478bd9Sstevel@tonic-gate 		putchar('\n');
1117c478bd9Sstevel@tonic-gate 	}
1127c478bd9Sstevel@tonic-gate 	return PROBE_FAILED;
1137c478bd9Sstevel@tonic-gate }
1147c478bd9Sstevel@tonic-gate #else
1157c478bd9Sstevel@tonic-gate #define isa_probe(d,tn) (PROBE_FAILED)
1167c478bd9Sstevel@tonic-gate #endif
1177c478bd9Sstevel@tonic-gate static const char *driver_name[] = {
1187c478bd9Sstevel@tonic-gate 	"nic",
1197c478bd9Sstevel@tonic-gate 	"disk",
1207c478bd9Sstevel@tonic-gate 	"floppy",
1217c478bd9Sstevel@tonic-gate };
probe(struct dev * dev)1227c478bd9Sstevel@tonic-gate int probe(struct dev *dev)
1237c478bd9Sstevel@tonic-gate {
1247c478bd9Sstevel@tonic-gate 	const char *type_name;
1257c478bd9Sstevel@tonic-gate 
1267c478bd9Sstevel@tonic-gate 	EnterFunction("probe");
1277c478bd9Sstevel@tonic-gate 
1287c478bd9Sstevel@tonic-gate 	type_name = "";
1297c478bd9Sstevel@tonic-gate 	if ((dev->type >= 0) &&
1307c478bd9Sstevel@tonic-gate 		(dev->type < sizeof(driver_name)/sizeof(driver_name[0]))) {
1317c478bd9Sstevel@tonic-gate 		type_name = driver_name[dev->type];
1327c478bd9Sstevel@tonic-gate 	}
1337c478bd9Sstevel@tonic-gate 	if (dev->how_probe == PROBE_FIRST) {
1347c478bd9Sstevel@tonic-gate 		dev->to_probe = PROBE_PCI;
1357c478bd9Sstevel@tonic-gate 		memset(&dev->state, 0, sizeof(dev->state));
1367c478bd9Sstevel@tonic-gate 	}
1377c478bd9Sstevel@tonic-gate 	if (dev->to_probe == PROBE_PCI) {
1387c478bd9Sstevel@tonic-gate 		dev->how_probe = pci_probe(dev, type_name);
1397c478bd9Sstevel@tonic-gate 		if (dev->how_probe == PROBE_FAILED) {
1407c478bd9Sstevel@tonic-gate 			dev->to_probe = PROBE_ISA;
1417c478bd9Sstevel@tonic-gate 		}
1427c478bd9Sstevel@tonic-gate 	}
1437c478bd9Sstevel@tonic-gate 	if (dev->to_probe == PROBE_ISA) {
1447c478bd9Sstevel@tonic-gate 		dev->how_probe = isa_probe(dev, type_name);
1457c478bd9Sstevel@tonic-gate 		if (dev->how_probe == PROBE_FAILED) {
1467c478bd9Sstevel@tonic-gate 			dev->to_probe = PROBE_NONE;
1477c478bd9Sstevel@tonic-gate 		}
1487c478bd9Sstevel@tonic-gate 	}
1497c478bd9Sstevel@tonic-gate 	if ((dev->to_probe != PROBE_PCI) &&
1507c478bd9Sstevel@tonic-gate 		(dev->to_probe != PROBE_ISA)) {
1517c478bd9Sstevel@tonic-gate 		dev->how_probe = PROBE_FAILED;
1527c478bd9Sstevel@tonic-gate 
1537c478bd9Sstevel@tonic-gate 	}
1547c478bd9Sstevel@tonic-gate 
1557c478bd9Sstevel@tonic-gate 	LeaveFunction("probe");
1567c478bd9Sstevel@tonic-gate 	return dev->how_probe;
1577c478bd9Sstevel@tonic-gate }
1587c478bd9Sstevel@tonic-gate 
disable(struct dev * dev)1597c478bd9Sstevel@tonic-gate void disable(struct dev *dev)
1607c478bd9Sstevel@tonic-gate {
1617c478bd9Sstevel@tonic-gate 	if (dev->disable) {
1627c478bd9Sstevel@tonic-gate 		dev->disable(dev);
1637c478bd9Sstevel@tonic-gate 		dev->disable = 0;
1647c478bd9Sstevel@tonic-gate 	}
1657c478bd9Sstevel@tonic-gate }
166