17c478bd9Sstevel@tonic-gate 
27c478bd9Sstevel@tonic-gate /*
37c478bd9Sstevel@tonic-gate  * This program is free software; you can redistribute it and/or
47c478bd9Sstevel@tonic-gate  * modify it under the terms of the GNU General Public License as
57c478bd9Sstevel@tonic-gate  * published by the Free Software Foundation; either version 2, or (at
67c478bd9Sstevel@tonic-gate  * your option) any later version.
77c478bd9Sstevel@tonic-gate  */
87c478bd9Sstevel@tonic-gate 
97c478bd9Sstevel@tonic-gate #include "grub.h"
107c478bd9Sstevel@tonic-gate #include "pci.h"
117c478bd9Sstevel@tonic-gate 
127c478bd9Sstevel@tonic-gate unsigned long virt_offset = 0;
virt_to_phys(volatile const void * virt_addr)137c478bd9Sstevel@tonic-gate unsigned long virt_to_phys(volatile const void *virt_addr)
147c478bd9Sstevel@tonic-gate {
157c478bd9Sstevel@tonic-gate 	return ((unsigned long)virt_addr) + virt_offset;
167c478bd9Sstevel@tonic-gate }
177c478bd9Sstevel@tonic-gate 
phys_to_virt(unsigned long phys_addr)187c478bd9Sstevel@tonic-gate void *phys_to_virt(unsigned long phys_addr)
197c478bd9Sstevel@tonic-gate {
207c478bd9Sstevel@tonic-gate 	return (void *)(phys_addr - virt_offset);
217c478bd9Sstevel@tonic-gate }
227c478bd9Sstevel@tonic-gate 
237c478bd9Sstevel@tonic-gate #ifdef INCLUDE_3C595
247c478bd9Sstevel@tonic-gate extern struct pci_driver t595_driver;
257c478bd9Sstevel@tonic-gate #endif /* INCLUDE_3C595 */
267c478bd9Sstevel@tonic-gate 
277c478bd9Sstevel@tonic-gate #ifdef INCLUDE_3C90X
287c478bd9Sstevel@tonic-gate extern struct pci_driver a3c90x_driver;
297c478bd9Sstevel@tonic-gate #endif /* INCLUDE_3C90X */
307c478bd9Sstevel@tonic-gate 
317c478bd9Sstevel@tonic-gate #ifdef INCLUDE_DAVICOM
327c478bd9Sstevel@tonic-gate extern struct pci_driver davicom_driver;
337c478bd9Sstevel@tonic-gate #endif /* INCLUDE_DAVICOM */
347c478bd9Sstevel@tonic-gate 
357c478bd9Sstevel@tonic-gate #ifdef INCLUDE_E1000
367c478bd9Sstevel@tonic-gate extern struct pci_driver e1000_driver;
377c478bd9Sstevel@tonic-gate #endif /* INCLUDE_E1000 */
387c478bd9Sstevel@tonic-gate 
397c478bd9Sstevel@tonic-gate #ifdef INCLUDE_EEPRO100
407c478bd9Sstevel@tonic-gate extern struct pci_driver eepro100_driver;
417c478bd9Sstevel@tonic-gate #endif /* INCLUDE_EEPRO100 */
427c478bd9Sstevel@tonic-gate 
437c478bd9Sstevel@tonic-gate #ifdef INCLUDE_EPIC100
447c478bd9Sstevel@tonic-gate extern struct pci_driver epic100_driver;
457c478bd9Sstevel@tonic-gate #endif /* INCLUDE_EPIC100 */
467c478bd9Sstevel@tonic-gate 
477c478bd9Sstevel@tonic-gate #ifdef INCLUDE_FORCEDETH
487c478bd9Sstevel@tonic-gate extern struct pci_driver forcedeth_driver;
497c478bd9Sstevel@tonic-gate #endif /* INCLUDE_FORCEDETH */
507c478bd9Sstevel@tonic-gate 
517c478bd9Sstevel@tonic-gate #ifdef INCLUDE_NATSEMI
527c478bd9Sstevel@tonic-gate extern struct pci_driver natsemi_driver;
537c478bd9Sstevel@tonic-gate #endif /* INCLUDE_NATSEMI */
547c478bd9Sstevel@tonic-gate 
557c478bd9Sstevel@tonic-gate #ifdef INCLUDE_NS83820
567c478bd9Sstevel@tonic-gate extern struct pci_driver ns83820_driver;
577c478bd9Sstevel@tonic-gate #endif /* INCLUDE_NS83820 */
587c478bd9Sstevel@tonic-gate 
597c478bd9Sstevel@tonic-gate #ifdef INCLUDE_NS8390
607c478bd9Sstevel@tonic-gate extern struct pci_driver nepci_driver;
617c478bd9Sstevel@tonic-gate #endif /* INCLUDE_NS8390 */
627c478bd9Sstevel@tonic-gate 
637c478bd9Sstevel@tonic-gate #ifdef INCLUDE_PCNET32
647c478bd9Sstevel@tonic-gate extern struct pci_driver pcnet32_driver;
657c478bd9Sstevel@tonic-gate #endif /* INCLUDE_PCNET32 */
667c478bd9Sstevel@tonic-gate 
677c478bd9Sstevel@tonic-gate #ifdef INCLUDE_PNIC
687c478bd9Sstevel@tonic-gate extern struct pci_driver pnic_driver;
697c478bd9Sstevel@tonic-gate #endif /* INCLUDE_PNIC */
707c478bd9Sstevel@tonic-gate 
717c478bd9Sstevel@tonic-gate #ifdef INCLUDE_RTL8139
727c478bd9Sstevel@tonic-gate extern struct pci_driver rtl8139_driver;
737c478bd9Sstevel@tonic-gate #endif /* INCLUDE_RTL8139 */
747c478bd9Sstevel@tonic-gate 
757c478bd9Sstevel@tonic-gate #ifdef INCLUDE_SIS900
767c478bd9Sstevel@tonic-gate extern struct pci_driver sis900_driver;
777c478bd9Sstevel@tonic-gate extern struct pci_driver sis_bridge_driver;
787c478bd9Sstevel@tonic-gate #endif /* INCLUDE_SIS900 */
797c478bd9Sstevel@tonic-gate 
807c478bd9Sstevel@tonic-gate #ifdef INCLUDE_SUNDANCE
817c478bd9Sstevel@tonic-gate extern struct pci_driver sundance_driver;
827c478bd9Sstevel@tonic-gate #endif	/* INCLUDE_SUNDANCE */
837c478bd9Sstevel@tonic-gate 
847c478bd9Sstevel@tonic-gate #ifdef INCLUDE_TG3
857c478bd9Sstevel@tonic-gate extern struct pci_driver  tg3_driver;
867c478bd9Sstevel@tonic-gate #endif /* INCLUDE_TG3 */
877c478bd9Sstevel@tonic-gate 
887c478bd9Sstevel@tonic-gate #ifdef INCLUDE_TLAN
897c478bd9Sstevel@tonic-gate extern struct pci_driver tlan_driver;
907c478bd9Sstevel@tonic-gate #endif /* INCLUDE_TLAN */
917c478bd9Sstevel@tonic-gate 
927c478bd9Sstevel@tonic-gate #ifdef INCLUDE_TULIP
937c478bd9Sstevel@tonic-gate extern struct pci_driver tulip_driver;
947c478bd9Sstevel@tonic-gate #endif /* INCLUDE_TULIP */
957c478bd9Sstevel@tonic-gate 
967c478bd9Sstevel@tonic-gate #ifdef INCLUDE_UNDI
977c478bd9Sstevel@tonic-gate extern struct pci_driver undi_driver;
987c478bd9Sstevel@tonic-gate #endif /* INCLUDE_UNDI */
997c478bd9Sstevel@tonic-gate 
1007c478bd9Sstevel@tonic-gate #ifdef INCLUDE_VIA_RHINE
1017c478bd9Sstevel@tonic-gate extern struct pci_driver rhine_driver;
1027c478bd9Sstevel@tonic-gate #endif/* INCLUDE_VIA_RHINE */
1037c478bd9Sstevel@tonic-gate 
1047c478bd9Sstevel@tonic-gate #ifdef INCLUDE_W89C840
1057c478bd9Sstevel@tonic-gate extern struct pci_driver w89c840_driver;
1067c478bd9Sstevel@tonic-gate #endif /* INCLUDE_W89C840 */
1077c478bd9Sstevel@tonic-gate 
1087c478bd9Sstevel@tonic-gate #ifdef INCLUDE_R8169
1097c478bd9Sstevel@tonic-gate extern struct pci_driver r8169_driver;
1107c478bd9Sstevel@tonic-gate #endif /* INCLUDE_R8169 */
1117c478bd9Sstevel@tonic-gate 
1127c478bd9Sstevel@tonic-gate static const struct pci_driver *pci_drivers[] = {
1137c478bd9Sstevel@tonic-gate 
1147c478bd9Sstevel@tonic-gate #ifdef INCLUDE_3C595
1157c478bd9Sstevel@tonic-gate 	&t595_driver,
1167c478bd9Sstevel@tonic-gate #endif /* INCLUDE_3C595 */
1177c478bd9Sstevel@tonic-gate 
1187c478bd9Sstevel@tonic-gate #ifdef INCLUDE_3C90X
1197c478bd9Sstevel@tonic-gate 	&a3c90x_driver,
1207c478bd9Sstevel@tonic-gate #endif /* INCLUDE_3C90X */
1217c478bd9Sstevel@tonic-gate 
1227c478bd9Sstevel@tonic-gate #ifdef INCLUDE_DAVICOM
1237c478bd9Sstevel@tonic-gate 	&davicom_driver,
1247c478bd9Sstevel@tonic-gate #endif /* INCLUDE_DAVICOM */
1257c478bd9Sstevel@tonic-gate 
1267c478bd9Sstevel@tonic-gate #ifdef INCLUDE_E1000
1277c478bd9Sstevel@tonic-gate 	&e1000_driver,
1287c478bd9Sstevel@tonic-gate #endif /* INCLUDE_E1000 */
1297c478bd9Sstevel@tonic-gate 
1307c478bd9Sstevel@tonic-gate #ifdef INCLUDE_EEPRO100
1317c478bd9Sstevel@tonic-gate 	&eepro100_driver,
1327c478bd9Sstevel@tonic-gate #endif /* INCLUDE_EEPRO100 */
1337c478bd9Sstevel@tonic-gate 
1347c478bd9Sstevel@tonic-gate #ifdef INCLUDE_EPIC100
1357c478bd9Sstevel@tonic-gate 	&epic100_driver,
1367c478bd9Sstevel@tonic-gate #endif /* INCLUDE_EPIC100 */
1377c478bd9Sstevel@tonic-gate 
1387c478bd9Sstevel@tonic-gate #ifdef INCLUDE_FORCEDETH
1397c478bd9Sstevel@tonic-gate 	&forcedeth_driver,
1407c478bd9Sstevel@tonic-gate #endif /* INCLUDE_FORCEDETH */
1417c478bd9Sstevel@tonic-gate 
1427c478bd9Sstevel@tonic-gate #ifdef INCLUDE_NATSEMI
1437c478bd9Sstevel@tonic-gate 	&natsemi_driver,
1447c478bd9Sstevel@tonic-gate #endif /* INCLUDE_NATSEMI */
1457c478bd9Sstevel@tonic-gate 
1467c478bd9Sstevel@tonic-gate #ifdef INCLUDE_NS83820
1477c478bd9Sstevel@tonic-gate 	&ns83820_driver,
1487c478bd9Sstevel@tonic-gate #endif /* INCLUDE_NS83820 */
1497c478bd9Sstevel@tonic-gate 
1507c478bd9Sstevel@tonic-gate #ifdef INCLUDE_NS8390
1517c478bd9Sstevel@tonic-gate 	&nepci_driver,
1527c478bd9Sstevel@tonic-gate #endif /* INCLUDE_NS8390 */
1537c478bd9Sstevel@tonic-gate 
1547c478bd9Sstevel@tonic-gate #ifdef INCLUDE_PCNET32
1557c478bd9Sstevel@tonic-gate 	&pcnet32_driver,
1567c478bd9Sstevel@tonic-gate #endif /* INCLUDE_PCNET32 */
1577c478bd9Sstevel@tonic-gate 
1587c478bd9Sstevel@tonic-gate #ifdef INCLUDE_PNIC
1597c478bd9Sstevel@tonic-gate 	&pnic_driver,
1607c478bd9Sstevel@tonic-gate #endif /* INCLUDE_PNIC */
1617c478bd9Sstevel@tonic-gate 
1627c478bd9Sstevel@tonic-gate #ifdef INCLUDE_RTL8139
1637c478bd9Sstevel@tonic-gate 	&rtl8139_driver,
1647c478bd9Sstevel@tonic-gate #endif /* INCLUDE_RTL8139 */
1657c478bd9Sstevel@tonic-gate 
1667c478bd9Sstevel@tonic-gate #ifdef INCLUDE_SIS900
1677c478bd9Sstevel@tonic-gate 	&sis900_driver,
1687c478bd9Sstevel@tonic-gate 	&sis_bridge_driver,
1697c478bd9Sstevel@tonic-gate #endif /* INCLUDE_SIS900 */
1707c478bd9Sstevel@tonic-gate 
1717c478bd9Sstevel@tonic-gate #ifdef INCLUDE_SUNDANCE
1727c478bd9Sstevel@tonic-gate 	&sundance_driver,
1737c478bd9Sstevel@tonic-gate #endif /* INCLUDE_SUNDANCE */
1747c478bd9Sstevel@tonic-gate 
1757c478bd9Sstevel@tonic-gate #ifdef INCLUDE_TG3
1767c478bd9Sstevel@tonic-gate 	& tg3_driver,
1777c478bd9Sstevel@tonic-gate #endif /* INCLUDE_TG3 */
1787c478bd9Sstevel@tonic-gate 
1797c478bd9Sstevel@tonic-gate #ifdef INCLUDE_TLAN
1807c478bd9Sstevel@tonic-gate 	&tlan_driver,
1817c478bd9Sstevel@tonic-gate #endif /* INCLUDE_TLAN */
1827c478bd9Sstevel@tonic-gate 
1837c478bd9Sstevel@tonic-gate #ifdef INCLUDE_TULIP
1847c478bd9Sstevel@tonic-gate 	& tulip_driver,
1857c478bd9Sstevel@tonic-gate #endif /* INCLUDE_TULIP */
1867c478bd9Sstevel@tonic-gate 
1877c478bd9Sstevel@tonic-gate #ifdef INCLUDE_VIA_RHINE
1887c478bd9Sstevel@tonic-gate 	&rhine_driver,
1897c478bd9Sstevel@tonic-gate #endif/* INCLUDE_VIA_RHINE */
1907c478bd9Sstevel@tonic-gate 
1917c478bd9Sstevel@tonic-gate #ifdef INCLUDE_W89C840
1927c478bd9Sstevel@tonic-gate 	&w89c840_driver,
1937c478bd9Sstevel@tonic-gate #endif /* INCLUDE_W89C840 */
1947c478bd9Sstevel@tonic-gate 
1957c478bd9Sstevel@tonic-gate #ifdef INCLUDE_R8169
1967c478bd9Sstevel@tonic-gate 	&r8169_driver,
1977c478bd9Sstevel@tonic-gate #endif /* INCLUDE_R8169 */
1987c478bd9Sstevel@tonic-gate 
1997c478bd9Sstevel@tonic-gate /* We must be the last one */
2007c478bd9Sstevel@tonic-gate #ifdef INCLUDE_UNDI
2017c478bd9Sstevel@tonic-gate 	&undi_driver,
2027c478bd9Sstevel@tonic-gate #endif /* INCLUDE_UNDI */
2037c478bd9Sstevel@tonic-gate 
2047c478bd9Sstevel@tonic-gate 	0
2057c478bd9Sstevel@tonic-gate };
2067c478bd9Sstevel@tonic-gate 
scan_drivers(int type,uint32_t class,uint16_t vendor,uint16_t device,const struct pci_driver * last_driver,struct pci_device * dev)2077c478bd9Sstevel@tonic-gate static void scan_drivers(
2087c478bd9Sstevel@tonic-gate 	int type,
2097c478bd9Sstevel@tonic-gate 	uint32_t class, uint16_t vendor, uint16_t device,
2107c478bd9Sstevel@tonic-gate 	const struct pci_driver *last_driver, struct pci_device *dev)
2117c478bd9Sstevel@tonic-gate {
2127c478bd9Sstevel@tonic-gate 	const struct pci_driver *skip_driver = last_driver;
2137c478bd9Sstevel@tonic-gate 	/* Assume there is only one match of the correct type */
2147c478bd9Sstevel@tonic-gate 	const struct pci_driver *driver;
2157c478bd9Sstevel@tonic-gate 	int i, j;
2167c478bd9Sstevel@tonic-gate 
2177c478bd9Sstevel@tonic-gate 	for(j = 0; pci_drivers[j] != 0; j++){
2187c478bd9Sstevel@tonic-gate 		driver = pci_drivers[j];
2197c478bd9Sstevel@tonic-gate 		if (driver->type != type)
2207c478bd9Sstevel@tonic-gate 			continue;
2217c478bd9Sstevel@tonic-gate 		if (skip_driver) {
2227c478bd9Sstevel@tonic-gate 			if (skip_driver == driver)
2237c478bd9Sstevel@tonic-gate 				skip_driver = 0;
2247c478bd9Sstevel@tonic-gate 			continue;
2257c478bd9Sstevel@tonic-gate 		}
2267c478bd9Sstevel@tonic-gate 		for(i = 0; i < driver->id_count; i++) {
2277c478bd9Sstevel@tonic-gate 			if ((vendor == driver->ids[i].vendor) &&
2287c478bd9Sstevel@tonic-gate 			    (device == driver->ids[i].dev_id)) {
2297c478bd9Sstevel@tonic-gate 
2307c478bd9Sstevel@tonic-gate 				dev->driver = driver;
2317c478bd9Sstevel@tonic-gate 				dev->name   = driver->ids[i].name;
2327c478bd9Sstevel@tonic-gate 
2337c478bd9Sstevel@tonic-gate 				goto out;
2347c478bd9Sstevel@tonic-gate 			}
2357c478bd9Sstevel@tonic-gate 		}
2367c478bd9Sstevel@tonic-gate 	}
2377c478bd9Sstevel@tonic-gate 	if (!class) {
2387c478bd9Sstevel@tonic-gate 		goto out;
2397c478bd9Sstevel@tonic-gate 	}
2407c478bd9Sstevel@tonic-gate 	for(j = 0; pci_drivers[j] != 0; j++){
2417c478bd9Sstevel@tonic-gate 		driver = pci_drivers[j];
2427c478bd9Sstevel@tonic-gate 		if (driver->type != type)
2437c478bd9Sstevel@tonic-gate 			continue;
2447c478bd9Sstevel@tonic-gate 		if (skip_driver) {
2457c478bd9Sstevel@tonic-gate 			if (skip_driver == driver)
2467c478bd9Sstevel@tonic-gate 				skip_driver = 0;
2477c478bd9Sstevel@tonic-gate 			continue;
2487c478bd9Sstevel@tonic-gate 		}
2497c478bd9Sstevel@tonic-gate 		if (last_driver == driver)
2507c478bd9Sstevel@tonic-gate 			continue;
2517c478bd9Sstevel@tonic-gate 		if ((class >> 8) == driver->class) {
2527c478bd9Sstevel@tonic-gate 			dev->driver = driver;
2537c478bd9Sstevel@tonic-gate 			dev->name   = driver->name;
2547c478bd9Sstevel@tonic-gate 			goto out;
2557c478bd9Sstevel@tonic-gate 		}
2567c478bd9Sstevel@tonic-gate 	}
2577c478bd9Sstevel@tonic-gate  out:
2587c478bd9Sstevel@tonic-gate 	return;
2597c478bd9Sstevel@tonic-gate }
2607c478bd9Sstevel@tonic-gate 
scan_pci_bus(int type,struct pci_device * dev)2617c478bd9Sstevel@tonic-gate void scan_pci_bus(int type, struct pci_device *dev)
2627c478bd9Sstevel@tonic-gate {
2637c478bd9Sstevel@tonic-gate 	unsigned int first_bus, first_devfn;
2647c478bd9Sstevel@tonic-gate 	const struct pci_driver *first_driver;
2657c478bd9Sstevel@tonic-gate 	unsigned int devfn, bus, buses;
2667c478bd9Sstevel@tonic-gate 	unsigned char hdr_type = 0;
2677c478bd9Sstevel@tonic-gate 	uint32_t class;
2687c478bd9Sstevel@tonic-gate 	uint16_t vendor, device;
2697c478bd9Sstevel@tonic-gate 	uint32_t l, membase, ioaddr, romaddr;
2707c478bd9Sstevel@tonic-gate 	int reg;
2717c478bd9Sstevel@tonic-gate 
2727c478bd9Sstevel@tonic-gate 	EnterFunction("scan_pci_bus");
2737c478bd9Sstevel@tonic-gate 	first_bus    = 0;
2747c478bd9Sstevel@tonic-gate 	first_devfn  = 0;
2757c478bd9Sstevel@tonic-gate 	first_driver = 0;
2767c478bd9Sstevel@tonic-gate 	if (dev->driver) {
2777c478bd9Sstevel@tonic-gate 		first_driver = dev->driver;
2787c478bd9Sstevel@tonic-gate 		first_bus    = dev->bus;
2797c478bd9Sstevel@tonic-gate 		first_devfn  = dev->devfn;
2807c478bd9Sstevel@tonic-gate 		/* Re read the header type on a restart */
2817c478bd9Sstevel@tonic-gate 		pcibios_read_config_byte(first_bus, first_devfn & ~0x7,
2827c478bd9Sstevel@tonic-gate 			PCI_HEADER_TYPE, &hdr_type);
2837c478bd9Sstevel@tonic-gate 		dev->driver  = 0;
2847c478bd9Sstevel@tonic-gate 		dev->bus     = 0;
2857c478bd9Sstevel@tonic-gate 		dev->devfn   = 0;
2867c478bd9Sstevel@tonic-gate 	}
2877c478bd9Sstevel@tonic-gate 
2887c478bd9Sstevel@tonic-gate 	/* Scan all PCI buses, until we find our card.
2897c478bd9Sstevel@tonic-gate 	 * We could be smart only scan the required buses but that
2907c478bd9Sstevel@tonic-gate 	 * is error prone, and tricky.
2917c478bd9Sstevel@tonic-gate 	 * By scanning all possible pci buses in order we should find
2927c478bd9Sstevel@tonic-gate 	 * our card eventually.
2937c478bd9Sstevel@tonic-gate 	 */
2947c478bd9Sstevel@tonic-gate 	buses=256;
2957c478bd9Sstevel@tonic-gate 	for (bus = first_bus; bus < buses; ++bus) {
2967c478bd9Sstevel@tonic-gate 		for (devfn = first_devfn; devfn < 0xff; ++devfn, first_driver = 0) {
2977c478bd9Sstevel@tonic-gate 			if (PCI_FUNC (devfn) == 0)
2987c478bd9Sstevel@tonic-gate 				pcibios_read_config_byte(bus, devfn, PCI_HEADER_TYPE, &hdr_type);
2997c478bd9Sstevel@tonic-gate 			else if (!(hdr_type & 0x80))	/* not a multi-function device */
3007c478bd9Sstevel@tonic-gate 				continue;
3017c478bd9Sstevel@tonic-gate 			pcibios_read_config_dword(bus, devfn, PCI_VENDOR_ID, &l);
3027c478bd9Sstevel@tonic-gate 			/* some broken boards return 0 if a slot is empty: */
3037c478bd9Sstevel@tonic-gate 			if (l == 0xffffffff || l == 0x00000000) {
3047c478bd9Sstevel@tonic-gate 				continue;
3057c478bd9Sstevel@tonic-gate 			}
3067c478bd9Sstevel@tonic-gate 			vendor = l & 0xffff;
3077c478bd9Sstevel@tonic-gate 			device = (l >> 16) & 0xffff;
3087c478bd9Sstevel@tonic-gate 
3097c478bd9Sstevel@tonic-gate 			pcibios_read_config_dword(bus, devfn, PCI_REVISION, &l);
3107c478bd9Sstevel@tonic-gate 			class = (l >> 8) & 0xffffff;
3117c478bd9Sstevel@tonic-gate #if	DEBUG
3127c478bd9Sstevel@tonic-gate 		{
3137c478bd9Sstevel@tonic-gate 			int i;
3147c478bd9Sstevel@tonic-gate 			printf("%hhx:%hhx.%hhx [%hX/%hX] ---- ",
3157c478bd9Sstevel@tonic-gate 				bus, PCI_SLOT(devfn), PCI_FUNC(devfn),
3167c478bd9Sstevel@tonic-gate 				vendor, device);
3177c478bd9Sstevel@tonic-gate #if	DEBUG > 1
3187c478bd9Sstevel@tonic-gate 			for(i = 0; i < 256; i++) {
3197c478bd9Sstevel@tonic-gate 				unsigned char byte;
3207c478bd9Sstevel@tonic-gate 				if ((i & 0xf) == 0) {
3217c478bd9Sstevel@tonic-gate 					printf("%hhx: ", i);
3227c478bd9Sstevel@tonic-gate 				}
3237c478bd9Sstevel@tonic-gate 				pcibios_read_config_byte(bus, devfn, i, &byte);
3247c478bd9Sstevel@tonic-gate 				printf("%hhx ", byte);
3257c478bd9Sstevel@tonic-gate 				if ((i & 0xf) == 0xf) {
3267c478bd9Sstevel@tonic-gate 					printf("\n");
3277c478bd9Sstevel@tonic-gate 				}
3287c478bd9Sstevel@tonic-gate 			}
3297c478bd9Sstevel@tonic-gate #endif
3307c478bd9Sstevel@tonic-gate 
3317c478bd9Sstevel@tonic-gate 		}
3327c478bd9Sstevel@tonic-gate #endif
3337c478bd9Sstevel@tonic-gate 			scan_drivers(type, class, vendor, device, first_driver, dev);
3347c478bd9Sstevel@tonic-gate 			if (!dev->driver){
3357c478bd9Sstevel@tonic-gate #if DEBUG
3367c478bd9Sstevel@tonic-gate 				printf("No driver fit.\n");
3377c478bd9Sstevel@tonic-gate #endif
3387c478bd9Sstevel@tonic-gate 				continue;
3397c478bd9Sstevel@tonic-gate 			}
3407c478bd9Sstevel@tonic-gate #if DEBUG
3417c478bd9Sstevel@tonic-gate 			printf("Get Driver:\n");
3427c478bd9Sstevel@tonic-gate #endif
3437c478bd9Sstevel@tonic-gate 			dev->devfn = devfn;
3447c478bd9Sstevel@tonic-gate 			dev->bus = bus;
3457c478bd9Sstevel@tonic-gate 			dev->class = class;
3467c478bd9Sstevel@tonic-gate 			dev->vendor = vendor;
3477c478bd9Sstevel@tonic-gate 			dev->dev_id = device;
3487c478bd9Sstevel@tonic-gate 
3497c478bd9Sstevel@tonic-gate 
3507c478bd9Sstevel@tonic-gate 			/* Get the ROM base address */
3517c478bd9Sstevel@tonic-gate 			pcibios_read_config_dword(bus, devfn,
3527c478bd9Sstevel@tonic-gate 				PCI_ROM_ADDRESS, &romaddr);
3537c478bd9Sstevel@tonic-gate 			romaddr >>= 10;
3547c478bd9Sstevel@tonic-gate 			dev->romaddr = romaddr;
3557c478bd9Sstevel@tonic-gate 
3567c478bd9Sstevel@tonic-gate 			/* Get the ``membase'' */
3577c478bd9Sstevel@tonic-gate 			pcibios_read_config_dword(bus, devfn,
3587c478bd9Sstevel@tonic-gate 				PCI_BASE_ADDRESS_1, &membase);
3597c478bd9Sstevel@tonic-gate 			dev->membase = membase;
3607c478bd9Sstevel@tonic-gate 
3617c478bd9Sstevel@tonic-gate 			/* Get the ``ioaddr'' */
3627c478bd9Sstevel@tonic-gate 			for (reg = PCI_BASE_ADDRESS_0; reg <= PCI_BASE_ADDRESS_5; reg += 4) {
3637c478bd9Sstevel@tonic-gate 				pcibios_read_config_dword(bus, devfn, reg, &ioaddr);
3647c478bd9Sstevel@tonic-gate 				if ((ioaddr & PCI_BASE_ADDRESS_IO_MASK) == 0 || (ioaddr & PCI_BASE_ADDRESS_SPACE_IO) == 0)
3657c478bd9Sstevel@tonic-gate 					continue;
3667c478bd9Sstevel@tonic-gate 
3677c478bd9Sstevel@tonic-gate 
3687c478bd9Sstevel@tonic-gate 				/* Strip the I/O address out of the returned value */
3697c478bd9Sstevel@tonic-gate 				ioaddr &= PCI_BASE_ADDRESS_IO_MASK;
3707c478bd9Sstevel@tonic-gate 
3717c478bd9Sstevel@tonic-gate 				/* Take the first one or the one that matches in boot ROM address */
3727c478bd9Sstevel@tonic-gate 				dev->ioaddr = ioaddr;
3737c478bd9Sstevel@tonic-gate 			}
3747c478bd9Sstevel@tonic-gate #if DEBUG > 2
3757c478bd9Sstevel@tonic-gate 			printf("Found %s ROM address %#hx\n",
3767c478bd9Sstevel@tonic-gate 				dev->name, romaddr);
3777c478bd9Sstevel@tonic-gate #endif
3787c478bd9Sstevel@tonic-gate 			LeaveFunction("scan_pci_bus");
3797c478bd9Sstevel@tonic-gate 			return;
3807c478bd9Sstevel@tonic-gate 		}
3817c478bd9Sstevel@tonic-gate 		first_devfn = 0;
3827c478bd9Sstevel@tonic-gate 	}
3837c478bd9Sstevel@tonic-gate 	first_bus = 0;
3847c478bd9Sstevel@tonic-gate 	LeaveFunction("scan_pci_bus");
3857c478bd9Sstevel@tonic-gate }
3867c478bd9Sstevel@tonic-gate 
3877c478bd9Sstevel@tonic-gate 
3887c478bd9Sstevel@tonic-gate 
3897c478bd9Sstevel@tonic-gate /*
3907c478bd9Sstevel@tonic-gate  *	Set device to be a busmaster in case BIOS neglected to do so.
3917c478bd9Sstevel@tonic-gate  *	Also adjust PCI latency timer to a reasonable value, 32.
3927c478bd9Sstevel@tonic-gate  */
adjust_pci_device(struct pci_device * p)3937c478bd9Sstevel@tonic-gate void adjust_pci_device(struct pci_device *p)
3947c478bd9Sstevel@tonic-gate {
3957c478bd9Sstevel@tonic-gate 	unsigned short	new_command, pci_command;
3967c478bd9Sstevel@tonic-gate 	unsigned char	pci_latency;
3977c478bd9Sstevel@tonic-gate 
3987c478bd9Sstevel@tonic-gate 	pcibios_read_config_word(p->bus, p->devfn, PCI_COMMAND, &pci_command);
3997c478bd9Sstevel@tonic-gate 	new_command = pci_command | PCI_COMMAND_MASTER|PCI_COMMAND_IO;
4007c478bd9Sstevel@tonic-gate 	if (pci_command != new_command) {
4017c478bd9Sstevel@tonic-gate #if DEBUG > 0
4027c478bd9Sstevel@tonic-gate 		printf(
4037c478bd9Sstevel@tonic-gate 			"The PCI BIOS has not enabled this device!\n"
4047c478bd9Sstevel@tonic-gate 			"Updating PCI command %hX->%hX. pci_bus %hhX pci_device_fn %hhX\n",
4057c478bd9Sstevel@tonic-gate 			   pci_command, new_command, p->bus, p->devfn);
4067c478bd9Sstevel@tonic-gate #endif
4077c478bd9Sstevel@tonic-gate 		pcibios_write_config_word(p->bus, p->devfn, PCI_COMMAND, new_command);
4087c478bd9Sstevel@tonic-gate 	}
4097c478bd9Sstevel@tonic-gate 	pcibios_read_config_byte(p->bus, p->devfn, PCI_LATENCY_TIMER, &pci_latency);
4107c478bd9Sstevel@tonic-gate 	if (pci_latency < 32) {
4117c478bd9Sstevel@tonic-gate #if DEBUG > 0
4127c478bd9Sstevel@tonic-gate 		printf("PCI latency timer (CFLT) is unreasonably low at %d. Setting to 32 clocks.\n",
4137c478bd9Sstevel@tonic-gate 			pci_latency);
4147c478bd9Sstevel@tonic-gate #endif
4157c478bd9Sstevel@tonic-gate 		pcibios_write_config_byte(p->bus, p->devfn, PCI_LATENCY_TIMER, 32);
4167c478bd9Sstevel@tonic-gate 	}
4177c478bd9Sstevel@tonic-gate }
4187c478bd9Sstevel@tonic-gate 
4197c478bd9Sstevel@tonic-gate /*
4207c478bd9Sstevel@tonic-gate  * Find the start of a pci resource.
4217c478bd9Sstevel@tonic-gate  */
pci_bar_start(struct pci_device * dev,unsigned int index)4227c478bd9Sstevel@tonic-gate unsigned long pci_bar_start(struct pci_device *dev, unsigned int index)
4237c478bd9Sstevel@tonic-gate {
4247c478bd9Sstevel@tonic-gate 	uint32_t lo, hi;
4257c478bd9Sstevel@tonic-gate 	unsigned long bar;
4267c478bd9Sstevel@tonic-gate 	pci_read_config_dword(dev, index, &lo);
4277c478bd9Sstevel@tonic-gate 	if (lo & PCI_BASE_ADDRESS_SPACE_IO) {
4287c478bd9Sstevel@tonic-gate 		bar = lo & PCI_BASE_ADDRESS_IO_MASK;
4297c478bd9Sstevel@tonic-gate 	} else {
4307c478bd9Sstevel@tonic-gate 		bar = 0;
4317c478bd9Sstevel@tonic-gate 		if ((lo & PCI_BASE_ADDRESS_MEM_TYPE_MASK) == PCI_BASE_ADDRESS_MEM_TYPE_64) {
4327c478bd9Sstevel@tonic-gate 			pci_read_config_dword(dev, index + 4, &hi);
4337c478bd9Sstevel@tonic-gate 			if (hi) {
4347c478bd9Sstevel@tonic-gate 				if (sizeof(unsigned long) > sizeof(uint32_t)) {
4357c478bd9Sstevel@tonic-gate 					/* It's REALLY interesting:-) */
4367c478bd9Sstevel@tonic-gate 					bar = (uint64_t)hi << 32;
4377c478bd9Sstevel@tonic-gate 				}
4387c478bd9Sstevel@tonic-gate 				else {
4397c478bd9Sstevel@tonic-gate 					printf("Unhandled 64bit BAR\n");
4407c478bd9Sstevel@tonic-gate 					return -1UL;
4417c478bd9Sstevel@tonic-gate 				}
4427c478bd9Sstevel@tonic-gate 			}
4437c478bd9Sstevel@tonic-gate 		}
4447c478bd9Sstevel@tonic-gate 		bar |= lo & PCI_BASE_ADDRESS_MEM_MASK;
4457c478bd9Sstevel@tonic-gate 	}
4467c478bd9Sstevel@tonic-gate 	return bar + pcibios_bus_base(dev->bus);
4477c478bd9Sstevel@tonic-gate }
4487c478bd9Sstevel@tonic-gate 
4497c478bd9Sstevel@tonic-gate /*
4507c478bd9Sstevel@tonic-gate  * Find the size of a pci resource.
4517c478bd9Sstevel@tonic-gate  */
pci_bar_size(struct pci_device * dev,unsigned int bar)4527c478bd9Sstevel@tonic-gate unsigned long pci_bar_size(struct pci_device *dev, unsigned int bar)
4537c478bd9Sstevel@tonic-gate {
4547c478bd9Sstevel@tonic-gate 	uint32_t start, size;
4557c478bd9Sstevel@tonic-gate 	/* Save the original bar */
4567c478bd9Sstevel@tonic-gate 	pci_read_config_dword(dev, bar, &start);
4577c478bd9Sstevel@tonic-gate 	/* Compute which bits can be set */
4587c478bd9Sstevel@tonic-gate 	pci_write_config_dword(dev, bar, ~0);
4597c478bd9Sstevel@tonic-gate 	pci_read_config_dword(dev, bar, &size);
4607c478bd9Sstevel@tonic-gate 	/* Restore the original size */
4617c478bd9Sstevel@tonic-gate 	pci_write_config_dword(dev, bar, start);
4627c478bd9Sstevel@tonic-gate 	/* Find the significant bits */
4637c478bd9Sstevel@tonic-gate 	if (start & PCI_BASE_ADDRESS_SPACE_IO) {
4647c478bd9Sstevel@tonic-gate 		size &= PCI_BASE_ADDRESS_IO_MASK;
4657c478bd9Sstevel@tonic-gate 	} else {
4667c478bd9Sstevel@tonic-gate 		size &= PCI_BASE_ADDRESS_MEM_MASK;
4677c478bd9Sstevel@tonic-gate 	}
4687c478bd9Sstevel@tonic-gate 	/* Find the lowest bit set */
4697c478bd9Sstevel@tonic-gate 	size = size & ~(size - 1);
4707c478bd9Sstevel@tonic-gate 	return size;
4717c478bd9Sstevel@tonic-gate }
4727c478bd9Sstevel@tonic-gate 
4737c478bd9Sstevel@tonic-gate /**
4747c478bd9Sstevel@tonic-gate  * pci_find_capability - query for devices' capabilities
4757c478bd9Sstevel@tonic-gate  * @dev: PCI device to query
4767c478bd9Sstevel@tonic-gate  * @cap: capability code
4777c478bd9Sstevel@tonic-gate  *
4787c478bd9Sstevel@tonic-gate  * Tell if a device supports a given PCI capability.
4797c478bd9Sstevel@tonic-gate  * Returns the address of the requested capability structure within the
4807c478bd9Sstevel@tonic-gate  * device's PCI configuration space or 0 in case the device does not
4817c478bd9Sstevel@tonic-gate  * support it.  Possible values for @cap:
4827c478bd9Sstevel@tonic-gate  *
4837c478bd9Sstevel@tonic-gate  *  %PCI_CAP_ID_PM           Power Management
4847c478bd9Sstevel@tonic-gate  *
4857c478bd9Sstevel@tonic-gate  *  %PCI_CAP_ID_AGP          Accelerated Graphics Port
4867c478bd9Sstevel@tonic-gate  *
4877c478bd9Sstevel@tonic-gate  *  %PCI_CAP_ID_VPD          Vital Product Data
4887c478bd9Sstevel@tonic-gate  *
4897c478bd9Sstevel@tonic-gate  *  %PCI_CAP_ID_SLOTID       Slot Identification
4907c478bd9Sstevel@tonic-gate  *
4917c478bd9Sstevel@tonic-gate  *  %PCI_CAP_ID_MSI          Message Signalled Interrupts
4927c478bd9Sstevel@tonic-gate  *
4937c478bd9Sstevel@tonic-gate  *  %PCI_CAP_ID_CHSWP        CompactPCI HotSwap
4947c478bd9Sstevel@tonic-gate  */
pci_find_capability(struct pci_device * dev,int cap)4957c478bd9Sstevel@tonic-gate int pci_find_capability(struct pci_device *dev, int cap)
4967c478bd9Sstevel@tonic-gate {
4977c478bd9Sstevel@tonic-gate 	uint16_t status;
4987c478bd9Sstevel@tonic-gate 	uint8_t pos, id;
4997c478bd9Sstevel@tonic-gate 	uint8_t hdr_type;
5007c478bd9Sstevel@tonic-gate 	int ttl = 48;
5017c478bd9Sstevel@tonic-gate 
5027c478bd9Sstevel@tonic-gate 	pci_read_config_word(dev, PCI_STATUS, &status);
5037c478bd9Sstevel@tonic-gate 	if (!(status & PCI_STATUS_CAP_LIST))
5047c478bd9Sstevel@tonic-gate 		return 0;
5057c478bd9Sstevel@tonic-gate 	pci_read_config_byte(dev, PCI_HEADER_TYPE, &hdr_type);
5067c478bd9Sstevel@tonic-gate 	switch (hdr_type & 0x7F) {
5077c478bd9Sstevel@tonic-gate 	case PCI_HEADER_TYPE_NORMAL:
5087c478bd9Sstevel@tonic-gate 	case PCI_HEADER_TYPE_BRIDGE:
5097c478bd9Sstevel@tonic-gate 	default:
5107c478bd9Sstevel@tonic-gate 		pci_read_config_byte(dev, PCI_CAPABILITY_LIST, &pos);
5117c478bd9Sstevel@tonic-gate 		break;
5127c478bd9Sstevel@tonic-gate 	case PCI_HEADER_TYPE_CARDBUS:
5137c478bd9Sstevel@tonic-gate 		pci_read_config_byte(dev, PCI_CB_CAPABILITY_LIST, &pos);
5147c478bd9Sstevel@tonic-gate 		break;
5157c478bd9Sstevel@tonic-gate 	}
5167c478bd9Sstevel@tonic-gate 	while (ttl-- && pos >= 0x40) {
5177c478bd9Sstevel@tonic-gate 		pos &= ~3;
5187c478bd9Sstevel@tonic-gate 		pci_read_config_byte(dev, pos + PCI_CAP_LIST_ID, &id);
5197c478bd9Sstevel@tonic-gate #if	DEBUG > 0
5207c478bd9Sstevel@tonic-gate 		printf("Capability: %d\n", id);
5217c478bd9Sstevel@tonic-gate #endif
5227c478bd9Sstevel@tonic-gate 		if (id == 0xff)
5237c478bd9Sstevel@tonic-gate 			break;
5247c478bd9Sstevel@tonic-gate 		if (id == cap)
5257c478bd9Sstevel@tonic-gate 			return pos;
5267c478bd9Sstevel@tonic-gate 		pci_read_config_byte(dev, pos + PCI_CAP_LIST_NEXT, &pos);
5277c478bd9Sstevel@tonic-gate 	}
5287c478bd9Sstevel@tonic-gate 	return 0;
5297c478bd9Sstevel@tonic-gate }
5307c478bd9Sstevel@tonic-gate 
531