17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate ** Support for NE2000 PCI clones added David Monro June 1997
37c478bd9Sstevel@tonic-gate ** Generalised to other NICs by Ken Yap July 1997
47c478bd9Sstevel@tonic-gate **
57c478bd9Sstevel@tonic-gate ** Most of this is taken from:
67c478bd9Sstevel@tonic-gate **
77c478bd9Sstevel@tonic-gate ** /usr/src/linux/drivers/pci/pci.c
87c478bd9Sstevel@tonic-gate ** /usr/src/linux/include/linux/pci.h
97c478bd9Sstevel@tonic-gate ** /usr/src/linux/arch/i386/bios32.c
107c478bd9Sstevel@tonic-gate ** /usr/src/linux/include/linux/bios32.h
117c478bd9Sstevel@tonic-gate ** /usr/src/linux/drivers/net/ne.c
127c478bd9Sstevel@tonic-gate */
137c478bd9Sstevel@tonic-gate #define PCBIOS
147c478bd9Sstevel@tonic-gate #include "grub.h"
157c478bd9Sstevel@tonic-gate #include "pci.h"
167c478bd9Sstevel@tonic-gate 
177c478bd9Sstevel@tonic-gate #ifdef	CONFIG_PCI_DIRECT
187c478bd9Sstevel@tonic-gate #define  PCIBIOS_SUCCESSFUL                0x00
197c478bd9Sstevel@tonic-gate 
207c478bd9Sstevel@tonic-gate #define DEBUG 0
217c478bd9Sstevel@tonic-gate 
227c478bd9Sstevel@tonic-gate /*
237c478bd9Sstevel@tonic-gate  * Functions for accessing PCI configuration space with type 1 accesses
247c478bd9Sstevel@tonic-gate  */
257c478bd9Sstevel@tonic-gate 
267c478bd9Sstevel@tonic-gate #define CONFIG_CMD(bus, device_fn, where)   (0x80000000 | (bus << 16) | (device_fn << 8) | (where & ~3))
277c478bd9Sstevel@tonic-gate 
pcibios_read_config_byte(unsigned int bus,unsigned int device_fn,unsigned int where,uint8_t * value)287c478bd9Sstevel@tonic-gate int pcibios_read_config_byte(unsigned int bus, unsigned int device_fn,
297c478bd9Sstevel@tonic-gate 			       unsigned int where, uint8_t *value)
307c478bd9Sstevel@tonic-gate {
317c478bd9Sstevel@tonic-gate     outl(CONFIG_CMD(bus,device_fn,where), 0xCF8);
327c478bd9Sstevel@tonic-gate     *value = inb(0xCFC + (where&3));
337c478bd9Sstevel@tonic-gate     return PCIBIOS_SUCCESSFUL;
347c478bd9Sstevel@tonic-gate }
357c478bd9Sstevel@tonic-gate 
pcibios_read_config_word(unsigned int bus,unsigned int device_fn,unsigned int where,uint16_t * value)367c478bd9Sstevel@tonic-gate int pcibios_read_config_word (unsigned int bus,
377c478bd9Sstevel@tonic-gate     unsigned int device_fn, unsigned int where, uint16_t *value)
387c478bd9Sstevel@tonic-gate {
397c478bd9Sstevel@tonic-gate     outl(CONFIG_CMD(bus,device_fn,where), 0xCF8);
407c478bd9Sstevel@tonic-gate     *value = inw(0xCFC + (where&2));
417c478bd9Sstevel@tonic-gate     return PCIBIOS_SUCCESSFUL;
427c478bd9Sstevel@tonic-gate }
437c478bd9Sstevel@tonic-gate 
pcibios_read_config_dword(unsigned int bus,unsigned int device_fn,unsigned int where,uint32_t * value)447c478bd9Sstevel@tonic-gate int pcibios_read_config_dword (unsigned int bus, unsigned int device_fn,
457c478bd9Sstevel@tonic-gate 				 unsigned int where, uint32_t *value)
467c478bd9Sstevel@tonic-gate {
477c478bd9Sstevel@tonic-gate     outl(CONFIG_CMD(bus,device_fn,where), 0xCF8);
487c478bd9Sstevel@tonic-gate     *value = inl(0xCFC);
497c478bd9Sstevel@tonic-gate     return PCIBIOS_SUCCESSFUL;
507c478bd9Sstevel@tonic-gate }
517c478bd9Sstevel@tonic-gate 
pcibios_write_config_byte(unsigned int bus,unsigned int device_fn,unsigned int where,uint8_t value)527c478bd9Sstevel@tonic-gate int pcibios_write_config_byte (unsigned int bus, unsigned int device_fn,
537c478bd9Sstevel@tonic-gate 				 unsigned int where, uint8_t value)
547c478bd9Sstevel@tonic-gate {
557c478bd9Sstevel@tonic-gate     outl(CONFIG_CMD(bus,device_fn,where), 0xCF8);
567c478bd9Sstevel@tonic-gate     outb(value, 0xCFC + (where&3));
577c478bd9Sstevel@tonic-gate     return PCIBIOS_SUCCESSFUL;
587c478bd9Sstevel@tonic-gate }
597c478bd9Sstevel@tonic-gate 
pcibios_write_config_word(unsigned int bus,unsigned int device_fn,unsigned int where,uint16_t value)607c478bd9Sstevel@tonic-gate int pcibios_write_config_word (unsigned int bus, unsigned int device_fn,
617c478bd9Sstevel@tonic-gate 				 unsigned int where, uint16_t value)
627c478bd9Sstevel@tonic-gate {
637c478bd9Sstevel@tonic-gate     outl(CONFIG_CMD(bus,device_fn,where), 0xCF8);
647c478bd9Sstevel@tonic-gate     outw(value, 0xCFC + (where&2));
657c478bd9Sstevel@tonic-gate     return PCIBIOS_SUCCESSFUL;
667c478bd9Sstevel@tonic-gate }
677c478bd9Sstevel@tonic-gate 
pcibios_write_config_dword(unsigned int bus,unsigned int device_fn,unsigned int where,uint32_t value)687c478bd9Sstevel@tonic-gate int pcibios_write_config_dword (unsigned int bus, unsigned int device_fn, unsigned int where, uint32_t value)
697c478bd9Sstevel@tonic-gate {
707c478bd9Sstevel@tonic-gate     outl(CONFIG_CMD(bus,device_fn,where), 0xCF8);
717c478bd9Sstevel@tonic-gate     outl(value, 0xCFC);
727c478bd9Sstevel@tonic-gate     return PCIBIOS_SUCCESSFUL;
737c478bd9Sstevel@tonic-gate }
747c478bd9Sstevel@tonic-gate 
757c478bd9Sstevel@tonic-gate #undef CONFIG_CMD
767c478bd9Sstevel@tonic-gate 
777c478bd9Sstevel@tonic-gate #else	 /* CONFIG_PCI_DIRECT  not defined */
787c478bd9Sstevel@tonic-gate 
797c478bd9Sstevel@tonic-gate #if !defined(PCBIOS)
807c478bd9Sstevel@tonic-gate #error "The pcibios can only be used when the PCBIOS support is compiled in"
817c478bd9Sstevel@tonic-gate #endif
827c478bd9Sstevel@tonic-gate 
837c478bd9Sstevel@tonic-gate 
847c478bd9Sstevel@tonic-gate #define KERN_CODE_SEG 0X8
857c478bd9Sstevel@tonic-gate /* Stuff for asm */
867c478bd9Sstevel@tonic-gate #define save_flags(x) \
877c478bd9Sstevel@tonic-gate __asm__ __volatile__("pushfl ; popl %0":"=g" (x): /* no input */ :"memory")
887c478bd9Sstevel@tonic-gate 
897c478bd9Sstevel@tonic-gate #define cli() __asm__ __volatile__ ("cli": : :"memory")
907c478bd9Sstevel@tonic-gate 
917c478bd9Sstevel@tonic-gate #define restore_flags(x) \
927c478bd9Sstevel@tonic-gate __asm__ __volatile__("pushl %0 ; popfl": /* no output */ :"g" (x):"memory")
937c478bd9Sstevel@tonic-gate 
947c478bd9Sstevel@tonic-gate 
957c478bd9Sstevel@tonic-gate 
967c478bd9Sstevel@tonic-gate static struct {
977c478bd9Sstevel@tonic-gate 	unsigned long address;
987c478bd9Sstevel@tonic-gate 	unsigned short segment;
997c478bd9Sstevel@tonic-gate } bios32_indirect = { 0, KERN_CODE_SEG };
1007c478bd9Sstevel@tonic-gate 
1017c478bd9Sstevel@tonic-gate static long pcibios_entry = 0;
1027c478bd9Sstevel@tonic-gate static struct {
1037c478bd9Sstevel@tonic-gate 	unsigned long address;
1047c478bd9Sstevel@tonic-gate 	unsigned short segment;
1057c478bd9Sstevel@tonic-gate } pci_indirect = { 0, KERN_CODE_SEG };
1067c478bd9Sstevel@tonic-gate 
bios32_service(unsigned long service)1077c478bd9Sstevel@tonic-gate static unsigned long bios32_service(unsigned long service)
1087c478bd9Sstevel@tonic-gate {
1097c478bd9Sstevel@tonic-gate 	unsigned char return_code;	/* %al */
1107c478bd9Sstevel@tonic-gate 	unsigned long address;		/* %ebx */
1117c478bd9Sstevel@tonic-gate 	unsigned long length;		/* %ecx */
1127c478bd9Sstevel@tonic-gate 	unsigned long entry;		/* %edx */
1137c478bd9Sstevel@tonic-gate 	unsigned long flags;
1147c478bd9Sstevel@tonic-gate 
1157c478bd9Sstevel@tonic-gate 	save_flags(flags);
1167c478bd9Sstevel@tonic-gate 	__asm__(
1177c478bd9Sstevel@tonic-gate #ifdef ABSOLUTE_WITHOUT_ASTERISK
1187c478bd9Sstevel@tonic-gate 		"lcall (%%edi)"
1197c478bd9Sstevel@tonic-gate #else
1207c478bd9Sstevel@tonic-gate 		"lcall *(%%edi)"
1217c478bd9Sstevel@tonic-gate #endif
1227c478bd9Sstevel@tonic-gate 		: "=a" (return_code),
1237c478bd9Sstevel@tonic-gate 		  "=b" (address),
1247c478bd9Sstevel@tonic-gate 		  "=c" (length),
1257c478bd9Sstevel@tonic-gate 		  "=d" (entry)
1267c478bd9Sstevel@tonic-gate 		: "0" (service),
1277c478bd9Sstevel@tonic-gate 		  "1" (0),
1287c478bd9Sstevel@tonic-gate 		  "D" (&bios32_indirect));
1297c478bd9Sstevel@tonic-gate 	restore_flags(flags);
1307c478bd9Sstevel@tonic-gate 
1317c478bd9Sstevel@tonic-gate 	switch (return_code) {
1327c478bd9Sstevel@tonic-gate 		case 0:
1337c478bd9Sstevel@tonic-gate 			return address + entry;
1347c478bd9Sstevel@tonic-gate 		case 0x80:	/* Not present */
1357c478bd9Sstevel@tonic-gate 			printf("bios32_service(%d) : not present\n", service);
1367c478bd9Sstevel@tonic-gate 			return 0;
1377c478bd9Sstevel@tonic-gate 		default: /* Shouldn't happen */
1387c478bd9Sstevel@tonic-gate 			printf("bios32_service(%d) : returned %#X, mail drew@colorado.edu\n",
1397c478bd9Sstevel@tonic-gate 				service, return_code);
1407c478bd9Sstevel@tonic-gate 			return 0;
1417c478bd9Sstevel@tonic-gate 	}
1427c478bd9Sstevel@tonic-gate }
1437c478bd9Sstevel@tonic-gate 
pcibios_read_config_byte(unsigned int bus,unsigned int device_fn,unsigned int where,uint8_t * value)1447c478bd9Sstevel@tonic-gate int pcibios_read_config_byte(unsigned int bus,
1457c478bd9Sstevel@tonic-gate         unsigned int device_fn, unsigned int where, uint8_t *value)
1467c478bd9Sstevel@tonic-gate {
1477c478bd9Sstevel@tonic-gate         unsigned long ret;
1487c478bd9Sstevel@tonic-gate         unsigned long bx = (bus << 8) | device_fn;
1497c478bd9Sstevel@tonic-gate         unsigned long flags;
1507c478bd9Sstevel@tonic-gate 
1517c478bd9Sstevel@tonic-gate         save_flags(flags);
1527c478bd9Sstevel@tonic-gate         __asm__(
1537c478bd9Sstevel@tonic-gate #ifdef ABSOLUTE_WITHOUT_ASTERISK
1547c478bd9Sstevel@tonic-gate 		"lcall (%%esi)\n\t"
1557c478bd9Sstevel@tonic-gate #else
1567c478bd9Sstevel@tonic-gate 		"lcall *(%%esi)\n\t"
1577c478bd9Sstevel@tonic-gate #endif
1587c478bd9Sstevel@tonic-gate                 "jc 1f\n\t"
1597c478bd9Sstevel@tonic-gate                 "xor %%ah, %%ah\n"
1607c478bd9Sstevel@tonic-gate                 "1:"
1617c478bd9Sstevel@tonic-gate                 : "=c" (*value),
1627c478bd9Sstevel@tonic-gate                   "=a" (ret)
1637c478bd9Sstevel@tonic-gate                 : "1" (PCIBIOS_READ_CONFIG_BYTE),
1647c478bd9Sstevel@tonic-gate                   "b" (bx),
1657c478bd9Sstevel@tonic-gate                   "D" ((long) where),
1667c478bd9Sstevel@tonic-gate                   "S" (&pci_indirect));
1677c478bd9Sstevel@tonic-gate         restore_flags(flags);
1687c478bd9Sstevel@tonic-gate         return (int) (ret & 0xff00) >> 8;
1697c478bd9Sstevel@tonic-gate }
1707c478bd9Sstevel@tonic-gate 
pcibios_read_config_word(unsigned int bus,unsigned int device_fn,unsigned int where,uint16_t * value)1717c478bd9Sstevel@tonic-gate int pcibios_read_config_word(unsigned int bus,
1727c478bd9Sstevel@tonic-gate         unsigned int device_fn, unsigned int where, uint16_t *value)
1737c478bd9Sstevel@tonic-gate {
1747c478bd9Sstevel@tonic-gate         unsigned long ret;
1757c478bd9Sstevel@tonic-gate         unsigned long bx = (bus << 8) | device_fn;
1767c478bd9Sstevel@tonic-gate         unsigned long flags;
1777c478bd9Sstevel@tonic-gate 
1787c478bd9Sstevel@tonic-gate         save_flags(flags);
1797c478bd9Sstevel@tonic-gate         __asm__(
1807c478bd9Sstevel@tonic-gate #ifdef ABSOLUTE_WITHOUT_ASTERISK
1817c478bd9Sstevel@tonic-gate 		"lcall (%%esi)\n\t"
1827c478bd9Sstevel@tonic-gate #else
1837c478bd9Sstevel@tonic-gate 		"lcall *(%%esi)\n\t"
1847c478bd9Sstevel@tonic-gate #endif
1857c478bd9Sstevel@tonic-gate                 "jc 1f\n\t"
1867c478bd9Sstevel@tonic-gate                 "xor %%ah, %%ah\n"
1877c478bd9Sstevel@tonic-gate                 "1:"
1887c478bd9Sstevel@tonic-gate                 : "=c" (*value),
1897c478bd9Sstevel@tonic-gate                   "=a" (ret)
1907c478bd9Sstevel@tonic-gate                 : "1" (PCIBIOS_READ_CONFIG_WORD),
1917c478bd9Sstevel@tonic-gate                   "b" (bx),
1927c478bd9Sstevel@tonic-gate                   "D" ((long) where),
1937c478bd9Sstevel@tonic-gate                   "S" (&pci_indirect));
1947c478bd9Sstevel@tonic-gate         restore_flags(flags);
1957c478bd9Sstevel@tonic-gate         return (int) (ret & 0xff00) >> 8;
1967c478bd9Sstevel@tonic-gate }
1977c478bd9Sstevel@tonic-gate 
pcibios_read_config_dword(unsigned int bus,unsigned int device_fn,unsigned int where,uint32_t * value)1987c478bd9Sstevel@tonic-gate int pcibios_read_config_dword(unsigned int bus,
1997c478bd9Sstevel@tonic-gate         unsigned int device_fn, unsigned int where, uint32_t *value)
2007c478bd9Sstevel@tonic-gate {
2017c478bd9Sstevel@tonic-gate         unsigned long ret;
2027c478bd9Sstevel@tonic-gate         unsigned long bx = (bus << 8) | device_fn;
2037c478bd9Sstevel@tonic-gate         unsigned long flags;
2047c478bd9Sstevel@tonic-gate 
2057c478bd9Sstevel@tonic-gate         save_flags(flags);
2067c478bd9Sstevel@tonic-gate         __asm__(
2077c478bd9Sstevel@tonic-gate #ifdef ABSOLUTE_WITHOUT_ASTERISK
2087c478bd9Sstevel@tonic-gate 		"lcall (%%esi)\n\t"
2097c478bd9Sstevel@tonic-gate #else
2107c478bd9Sstevel@tonic-gate 		"lcall *(%%esi)\n\t"
2117c478bd9Sstevel@tonic-gate #endif
2127c478bd9Sstevel@tonic-gate                 "jc 1f\n\t"
2137c478bd9Sstevel@tonic-gate                 "xor %%ah, %%ah\n"
2147c478bd9Sstevel@tonic-gate                 "1:"
2157c478bd9Sstevel@tonic-gate                 : "=c" (*value),
2167c478bd9Sstevel@tonic-gate                   "=a" (ret)
2177c478bd9Sstevel@tonic-gate                 : "1" (PCIBIOS_READ_CONFIG_DWORD),
2187c478bd9Sstevel@tonic-gate                   "b" (bx),
2197c478bd9Sstevel@tonic-gate                   "D" ((long) where),
2207c478bd9Sstevel@tonic-gate                   "S" (&pci_indirect));
2217c478bd9Sstevel@tonic-gate         restore_flags(flags);
2227c478bd9Sstevel@tonic-gate         return (int) (ret & 0xff00) >> 8;
2237c478bd9Sstevel@tonic-gate }
2247c478bd9Sstevel@tonic-gate 
pcibios_write_config_byte(unsigned int bus,unsigned int device_fn,unsigned int where,uint8_t value)2257c478bd9Sstevel@tonic-gate int pcibios_write_config_byte (unsigned int bus,
2267c478bd9Sstevel@tonic-gate 	unsigned int device_fn, unsigned int where, uint8_t value)
2277c478bd9Sstevel@tonic-gate {
2287c478bd9Sstevel@tonic-gate 	unsigned long ret;
2297c478bd9Sstevel@tonic-gate 	unsigned long bx = (bus << 8) | device_fn;
2307c478bd9Sstevel@tonic-gate 	unsigned long flags;
2317c478bd9Sstevel@tonic-gate 
2327c478bd9Sstevel@tonic-gate 	save_flags(flags); cli();
2337c478bd9Sstevel@tonic-gate 	__asm__(
2347c478bd9Sstevel@tonic-gate #ifdef ABSOLUTE_WITHOUT_ASTERISK
2357c478bd9Sstevel@tonic-gate 		"lcall (%%esi)\n\t"
2367c478bd9Sstevel@tonic-gate #else
2377c478bd9Sstevel@tonic-gate 		"lcall *(%%esi)\n\t"
2387c478bd9Sstevel@tonic-gate #endif
2397c478bd9Sstevel@tonic-gate 		"jc 1f\n\t"
2407c478bd9Sstevel@tonic-gate 		"xor %%ah, %%ah\n"
2417c478bd9Sstevel@tonic-gate 		"1:"
2427c478bd9Sstevel@tonic-gate 		: "=a" (ret)
2437c478bd9Sstevel@tonic-gate 		: "0" (PCIBIOS_WRITE_CONFIG_BYTE),
2447c478bd9Sstevel@tonic-gate 		  "c" (value),
2457c478bd9Sstevel@tonic-gate 		  "b" (bx),
2467c478bd9Sstevel@tonic-gate 		  "D" ((long) where),
2477c478bd9Sstevel@tonic-gate 		  "S" (&pci_indirect));
2487c478bd9Sstevel@tonic-gate 	restore_flags(flags);
2497c478bd9Sstevel@tonic-gate 	return (int) (ret & 0xff00) >> 8;
2507c478bd9Sstevel@tonic-gate }
2517c478bd9Sstevel@tonic-gate 
pcibios_write_config_word(unsigned int bus,unsigned int device_fn,unsigned int where,uint16_t value)2527c478bd9Sstevel@tonic-gate int pcibios_write_config_word (unsigned int bus,
2537c478bd9Sstevel@tonic-gate 	unsigned int device_fn, unsigned int where, uint16_t value)
2547c478bd9Sstevel@tonic-gate {
2557c478bd9Sstevel@tonic-gate 	unsigned long ret;
2567c478bd9Sstevel@tonic-gate 	unsigned long bx = (bus << 8) | device_fn;
2577c478bd9Sstevel@tonic-gate 	unsigned long flags;
2587c478bd9Sstevel@tonic-gate 
2597c478bd9Sstevel@tonic-gate 	save_flags(flags); cli();
2607c478bd9Sstevel@tonic-gate 	__asm__(
2617c478bd9Sstevel@tonic-gate #ifdef ABSOLUTE_WITHOUT_ASTERISK
2627c478bd9Sstevel@tonic-gate 		"lcall (%%esi)\n\t"
2637c478bd9Sstevel@tonic-gate #else
2647c478bd9Sstevel@tonic-gate 		"lcall *(%%esi)\n\t"
2657c478bd9Sstevel@tonic-gate #endif
2667c478bd9Sstevel@tonic-gate 		"jc 1f\n\t"
2677c478bd9Sstevel@tonic-gate 		"xor %%ah, %%ah\n"
2687c478bd9Sstevel@tonic-gate 		"1:"
2697c478bd9Sstevel@tonic-gate 		: "=a" (ret)
2707c478bd9Sstevel@tonic-gate 		: "0" (PCIBIOS_WRITE_CONFIG_WORD),
2717c478bd9Sstevel@tonic-gate 		  "c" (value),
2727c478bd9Sstevel@tonic-gate 		  "b" (bx),
2737c478bd9Sstevel@tonic-gate 		  "D" ((long) where),
2747c478bd9Sstevel@tonic-gate 		  "S" (&pci_indirect));
2757c478bd9Sstevel@tonic-gate 	restore_flags(flags);
2767c478bd9Sstevel@tonic-gate 	return (int) (ret & 0xff00) >> 8;
2777c478bd9Sstevel@tonic-gate }
2787c478bd9Sstevel@tonic-gate 
pcibios_write_config_dword(unsigned int bus,unsigned int device_fn,unsigned int where,uint32_t value)2797c478bd9Sstevel@tonic-gate int pcibios_write_config_dword (unsigned int bus,
2807c478bd9Sstevel@tonic-gate 	unsigned int device_fn, unsigned int where, uint32_t value)
2817c478bd9Sstevel@tonic-gate {
2827c478bd9Sstevel@tonic-gate 	unsigned long ret;
2837c478bd9Sstevel@tonic-gate 	unsigned long bx = (bus << 8) | device_fn;
2847c478bd9Sstevel@tonic-gate 	unsigned long flags;
2857c478bd9Sstevel@tonic-gate 
2867c478bd9Sstevel@tonic-gate 	save_flags(flags); cli();
2877c478bd9Sstevel@tonic-gate 	__asm__(
2887c478bd9Sstevel@tonic-gate #ifdef ABSOLUTE_WITHOUT_ASTERISK
2897c478bd9Sstevel@tonic-gate 		"lcall (%%esi)\n\t"
2907c478bd9Sstevel@tonic-gate #else
2917c478bd9Sstevel@tonic-gate 		"lcall *(%%esi)\n\t"
2927c478bd9Sstevel@tonic-gate #endif
2937c478bd9Sstevel@tonic-gate 		"jc 1f\n\t"
2947c478bd9Sstevel@tonic-gate 		"xor %%ah, %%ah\n"
2957c478bd9Sstevel@tonic-gate 		"1:"
2967c478bd9Sstevel@tonic-gate 		: "=a" (ret)
2977c478bd9Sstevel@tonic-gate 		: "0" (PCIBIOS_WRITE_CONFIG_DWORD),
2987c478bd9Sstevel@tonic-gate 		  "c" (value),
2997c478bd9Sstevel@tonic-gate 		  "b" (bx),
3007c478bd9Sstevel@tonic-gate 		  "D" ((long) where),
3017c478bd9Sstevel@tonic-gate 		  "S" (&pci_indirect));
3027c478bd9Sstevel@tonic-gate 	restore_flags(flags);
3037c478bd9Sstevel@tonic-gate 	return (int) (ret & 0xff00) >> 8;
3047c478bd9Sstevel@tonic-gate }
3057c478bd9Sstevel@tonic-gate 
check_pcibios(void)3067c478bd9Sstevel@tonic-gate static void check_pcibios(void)
3077c478bd9Sstevel@tonic-gate {
3087c478bd9Sstevel@tonic-gate 	unsigned long signature;
3097c478bd9Sstevel@tonic-gate 	unsigned char present_status;
3107c478bd9Sstevel@tonic-gate 	unsigned char major_revision;
3117c478bd9Sstevel@tonic-gate 	unsigned char minor_revision;
3127c478bd9Sstevel@tonic-gate 	unsigned long flags;
3137c478bd9Sstevel@tonic-gate 	int pack;
3147c478bd9Sstevel@tonic-gate 
3157c478bd9Sstevel@tonic-gate 	if ((pcibios_entry = bios32_service(PCI_SERVICE))) {
3167c478bd9Sstevel@tonic-gate 		pci_indirect.address = pcibios_entry;
3177c478bd9Sstevel@tonic-gate 
3187c478bd9Sstevel@tonic-gate 		save_flags(flags);
3197c478bd9Sstevel@tonic-gate 		__asm__(
3207c478bd9Sstevel@tonic-gate #ifdef ABSOLUTE_WITHOUT_ASTERISK
3217c478bd9Sstevel@tonic-gate 			"lcall (%%edi)\n\t"
3227c478bd9Sstevel@tonic-gate #else
3237c478bd9Sstevel@tonic-gate 			"lcall *(%%edi)\n\t"
3247c478bd9Sstevel@tonic-gate #endif
3257c478bd9Sstevel@tonic-gate 			"jc 1f\n\t"
3267c478bd9Sstevel@tonic-gate 			"xor %%ah, %%ah\n"
3277c478bd9Sstevel@tonic-gate 			"1:\tshl $8, %%eax\n\t"
3287c478bd9Sstevel@tonic-gate 			"movw %%bx, %%ax"
3297c478bd9Sstevel@tonic-gate 			: "=d" (signature),
3307c478bd9Sstevel@tonic-gate 			  "=a" (pack)
3317c478bd9Sstevel@tonic-gate 			: "1" (PCIBIOS_PCI_BIOS_PRESENT),
3327c478bd9Sstevel@tonic-gate 			  "D" (&pci_indirect)
3337c478bd9Sstevel@tonic-gate 			: "bx", "cx");
3347c478bd9Sstevel@tonic-gate 		restore_flags(flags);
3357c478bd9Sstevel@tonic-gate 
3367c478bd9Sstevel@tonic-gate 		present_status = (pack >> 16) & 0xff;
3377c478bd9Sstevel@tonic-gate 		major_revision = (pack >> 8) & 0xff;
3387c478bd9Sstevel@tonic-gate 		minor_revision = pack & 0xff;
3397c478bd9Sstevel@tonic-gate 		if (present_status || (signature != PCI_SIGNATURE)) {
3407c478bd9Sstevel@tonic-gate 			printf("ERROR: BIOS32 says PCI BIOS, but no PCI "
3417c478bd9Sstevel@tonic-gate 				"BIOS????\n");
3427c478bd9Sstevel@tonic-gate 			pcibios_entry = 0;
3437c478bd9Sstevel@tonic-gate 		}
3447c478bd9Sstevel@tonic-gate #if	DEBUG
3457c478bd9Sstevel@tonic-gate 		if (pcibios_entry) {
3467c478bd9Sstevel@tonic-gate 			printf ("pcibios_init : PCI BIOS revision %hhX.%hhX"
3477c478bd9Sstevel@tonic-gate 				" entry at %#X\n", major_revision,
3487c478bd9Sstevel@tonic-gate 				minor_revision, pcibios_entry);
3497c478bd9Sstevel@tonic-gate 		}
3507c478bd9Sstevel@tonic-gate #endif
3517c478bd9Sstevel@tonic-gate 	}
3527c478bd9Sstevel@tonic-gate }
3537c478bd9Sstevel@tonic-gate 
pcibios_init(void)3547c478bd9Sstevel@tonic-gate static void pcibios_init(void)
3557c478bd9Sstevel@tonic-gate {
3567c478bd9Sstevel@tonic-gate 	union bios32 *check;
3577c478bd9Sstevel@tonic-gate 	unsigned char sum;
3587c478bd9Sstevel@tonic-gate 	int i, length;
3597c478bd9Sstevel@tonic-gate 	unsigned long bios32_entry = 0;
3607c478bd9Sstevel@tonic-gate 
3617c478bd9Sstevel@tonic-gate 	EnterFunction("pcibios_init");
3627c478bd9Sstevel@tonic-gate 	/*
3637c478bd9Sstevel@tonic-gate 	 * Follow the standard procedure for locating the BIOS32 Service
3647c478bd9Sstevel@tonic-gate 	 * directory by scanning the permissible address range from
3657c478bd9Sstevel@tonic-gate 	 * 0xe0000 through 0xfffff for a valid BIOS32 structure.
3667c478bd9Sstevel@tonic-gate 	 *
3677c478bd9Sstevel@tonic-gate 	 */
3687c478bd9Sstevel@tonic-gate 
3697c478bd9Sstevel@tonic-gate 	for (check = (union bios32 *) 0xe0000; check <= (union bios32 *) 0xffff0; ++check) {
3707c478bd9Sstevel@tonic-gate 		if (check->fields.signature != BIOS32_SIGNATURE)
3717c478bd9Sstevel@tonic-gate 			continue;
3727c478bd9Sstevel@tonic-gate 		length = check->fields.length * 16;
3737c478bd9Sstevel@tonic-gate 		if (!length)
3747c478bd9Sstevel@tonic-gate 			continue;
3757c478bd9Sstevel@tonic-gate 		sum = 0;
3767c478bd9Sstevel@tonic-gate 		for (i = 0; i < length ; ++i)
3777c478bd9Sstevel@tonic-gate 			sum += check->chars[i];
3787c478bd9Sstevel@tonic-gate 		if (sum != 0)
3797c478bd9Sstevel@tonic-gate 			continue;
3807c478bd9Sstevel@tonic-gate 		if (check->fields.revision != 0) {
3817c478bd9Sstevel@tonic-gate 			printf("pcibios_init : unsupported revision %d at %#X, mail drew@colorado.edu\n",
3827c478bd9Sstevel@tonic-gate 				check->fields.revision, check);
3837c478bd9Sstevel@tonic-gate 			continue;
3847c478bd9Sstevel@tonic-gate 		}
3857c478bd9Sstevel@tonic-gate #if	DEBUG
3867c478bd9Sstevel@tonic-gate 		printf("pcibios_init : BIOS32 Service Directory "
3877c478bd9Sstevel@tonic-gate 			"structure at %#X\n", check);
3887c478bd9Sstevel@tonic-gate #endif
3897c478bd9Sstevel@tonic-gate 		if (!bios32_entry) {
3907c478bd9Sstevel@tonic-gate 			if (check->fields.entry >= 0x100000) {
3917c478bd9Sstevel@tonic-gate 				printf("pcibios_init: entry in high "
3927c478bd9Sstevel@tonic-gate 					"memory, giving up\n");
3937c478bd9Sstevel@tonic-gate 				return;
3947c478bd9Sstevel@tonic-gate 			} else {
3957c478bd9Sstevel@tonic-gate 				bios32_entry = check->fields.entry;
3967c478bd9Sstevel@tonic-gate #if	DEBUG
3977c478bd9Sstevel@tonic-gate 				printf("pcibios_init : BIOS32 Service Directory"
3987c478bd9Sstevel@tonic-gate 					" entry at %#X\n", bios32_entry);
3997c478bd9Sstevel@tonic-gate #endif
4007c478bd9Sstevel@tonic-gate 				bios32_indirect.address = bios32_entry;
4017c478bd9Sstevel@tonic-gate 			}
4027c478bd9Sstevel@tonic-gate 		}
4037c478bd9Sstevel@tonic-gate 	}
4047c478bd9Sstevel@tonic-gate 	if (bios32_entry)
4057c478bd9Sstevel@tonic-gate 		check_pcibios();
4067c478bd9Sstevel@tonic-gate 	LeaveFunction("pcibios_init");
4077c478bd9Sstevel@tonic-gate }
4087c478bd9Sstevel@tonic-gate 
4097c478bd9Sstevel@tonic-gate #endif	/* CONFIG_PCI_DIRECT not defined*/
4107c478bd9Sstevel@tonic-gate 
pcibios_bus_base(unsigned int bus __unused)4117c478bd9Sstevel@tonic-gate unsigned long pcibios_bus_base(unsigned int bus __unused)
4127c478bd9Sstevel@tonic-gate {
4137c478bd9Sstevel@tonic-gate 	/* architecturally this must be 0 */
4147c478bd9Sstevel@tonic-gate 	return 0;
4157c478bd9Sstevel@tonic-gate }
4167c478bd9Sstevel@tonic-gate 
find_pci(int type,struct pci_device * dev)4177c478bd9Sstevel@tonic-gate void find_pci(int type, struct pci_device *dev)
4187c478bd9Sstevel@tonic-gate {
4197c478bd9Sstevel@tonic-gate 	EnterFunction("find_pci");
4207c478bd9Sstevel@tonic-gate #ifndef	CONFIG_PCI_DIRECT
4217c478bd9Sstevel@tonic-gate 	if (!pcibios_entry) {
4227c478bd9Sstevel@tonic-gate 		pcibios_init();
4237c478bd9Sstevel@tonic-gate 	}
4247c478bd9Sstevel@tonic-gate 	if (!pcibios_entry) {
4257c478bd9Sstevel@tonic-gate 		printf("pci_init: no BIOS32 detected\n");
4267c478bd9Sstevel@tonic-gate 		return;
4277c478bd9Sstevel@tonic-gate 	}
4287c478bd9Sstevel@tonic-gate #endif
4297c478bd9Sstevel@tonic-gate 	LeaveFunction("find_pci");
4307c478bd9Sstevel@tonic-gate 	return scan_pci_bus(type, dev);
4317c478bd9Sstevel@tonic-gate }
432