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