xref: /onnv-gate/usr/src/grub/grub-0.97/netboot/pci_io.c (revision 8044:b3af80bbf173)
1*8044SWilliam.Kucharski@Sun.COM /*
2*8044SWilliam.Kucharski@Sun.COM ** Support for NE2000 PCI clones added David Monro June 1997
3*8044SWilliam.Kucharski@Sun.COM ** Generalised to other NICs by Ken Yap July 1997
4*8044SWilliam.Kucharski@Sun.COM **
5*8044SWilliam.Kucharski@Sun.COM ** Most of this is taken from:
6*8044SWilliam.Kucharski@Sun.COM **
7*8044SWilliam.Kucharski@Sun.COM ** /usr/src/linux/drivers/pci/pci.c
8*8044SWilliam.Kucharski@Sun.COM ** /usr/src/linux/include/linux/pci.h
9*8044SWilliam.Kucharski@Sun.COM ** /usr/src/linux/arch/i386/bios32.c
10*8044SWilliam.Kucharski@Sun.COM ** /usr/src/linux/include/linux/bios32.h
11*8044SWilliam.Kucharski@Sun.COM ** /usr/src/linux/drivers/net/ne.c
12*8044SWilliam.Kucharski@Sun.COM */
13*8044SWilliam.Kucharski@Sun.COM #define PCBIOS
14*8044SWilliam.Kucharski@Sun.COM #include "grub.h"
15*8044SWilliam.Kucharski@Sun.COM #include "pci.h"
16*8044SWilliam.Kucharski@Sun.COM 
17*8044SWilliam.Kucharski@Sun.COM #ifdef	CONFIG_PCI_DIRECT
18*8044SWilliam.Kucharski@Sun.COM #define  PCIBIOS_SUCCESSFUL                0x00
19*8044SWilliam.Kucharski@Sun.COM 
20*8044SWilliam.Kucharski@Sun.COM #define DEBUG 0
21*8044SWilliam.Kucharski@Sun.COM 
22*8044SWilliam.Kucharski@Sun.COM /*
23*8044SWilliam.Kucharski@Sun.COM  * Functions for accessing PCI configuration space with type 1 accesses
24*8044SWilliam.Kucharski@Sun.COM  */
25*8044SWilliam.Kucharski@Sun.COM 
26*8044SWilliam.Kucharski@Sun.COM #define CONFIG_CMD(bus, device_fn, where)   (0x80000000 | (bus << 16) | (device_fn << 8) | (where & ~3))
27*8044SWilliam.Kucharski@Sun.COM 
pcibios_read_config_byte(unsigned int bus,unsigned int device_fn,unsigned int where,uint8_t * value)28*8044SWilliam.Kucharski@Sun.COM int pcibios_read_config_byte(unsigned int bus, unsigned int device_fn,
29*8044SWilliam.Kucharski@Sun.COM 			       unsigned int where, uint8_t *value)
30*8044SWilliam.Kucharski@Sun.COM {
31*8044SWilliam.Kucharski@Sun.COM     outl(CONFIG_CMD(bus,device_fn,where), 0xCF8);
32*8044SWilliam.Kucharski@Sun.COM     *value = inb(0xCFC + (where&3));
33*8044SWilliam.Kucharski@Sun.COM     return PCIBIOS_SUCCESSFUL;
34*8044SWilliam.Kucharski@Sun.COM }
35*8044SWilliam.Kucharski@Sun.COM 
pcibios_read_config_word(unsigned int bus,unsigned int device_fn,unsigned int where,uint16_t * value)36*8044SWilliam.Kucharski@Sun.COM int pcibios_read_config_word (unsigned int bus,
37*8044SWilliam.Kucharski@Sun.COM     unsigned int device_fn, unsigned int where, uint16_t *value)
38*8044SWilliam.Kucharski@Sun.COM {
39*8044SWilliam.Kucharski@Sun.COM     outl(CONFIG_CMD(bus,device_fn,where), 0xCF8);
40*8044SWilliam.Kucharski@Sun.COM     *value = inw(0xCFC + (where&2));
41*8044SWilliam.Kucharski@Sun.COM     return PCIBIOS_SUCCESSFUL;
42*8044SWilliam.Kucharski@Sun.COM }
43*8044SWilliam.Kucharski@Sun.COM 
pcibios_read_config_dword(unsigned int bus,unsigned int device_fn,unsigned int where,uint32_t * value)44*8044SWilliam.Kucharski@Sun.COM int pcibios_read_config_dword (unsigned int bus, unsigned int device_fn,
45*8044SWilliam.Kucharski@Sun.COM 				 unsigned int where, uint32_t *value)
46*8044SWilliam.Kucharski@Sun.COM {
47*8044SWilliam.Kucharski@Sun.COM     outl(CONFIG_CMD(bus,device_fn,where), 0xCF8);
48*8044SWilliam.Kucharski@Sun.COM     *value = inl(0xCFC);
49*8044SWilliam.Kucharski@Sun.COM     return PCIBIOS_SUCCESSFUL;
50*8044SWilliam.Kucharski@Sun.COM }
51*8044SWilliam.Kucharski@Sun.COM 
pcibios_write_config_byte(unsigned int bus,unsigned int device_fn,unsigned int where,uint8_t value)52*8044SWilliam.Kucharski@Sun.COM int pcibios_write_config_byte (unsigned int bus, unsigned int device_fn,
53*8044SWilliam.Kucharski@Sun.COM 				 unsigned int where, uint8_t value)
54*8044SWilliam.Kucharski@Sun.COM {
55*8044SWilliam.Kucharski@Sun.COM     outl(CONFIG_CMD(bus,device_fn,where), 0xCF8);
56*8044SWilliam.Kucharski@Sun.COM     outb(value, 0xCFC + (where&3));
57*8044SWilliam.Kucharski@Sun.COM     return PCIBIOS_SUCCESSFUL;
58*8044SWilliam.Kucharski@Sun.COM }
59*8044SWilliam.Kucharski@Sun.COM 
pcibios_write_config_word(unsigned int bus,unsigned int device_fn,unsigned int where,uint16_t value)60*8044SWilliam.Kucharski@Sun.COM int pcibios_write_config_word (unsigned int bus, unsigned int device_fn,
61*8044SWilliam.Kucharski@Sun.COM 				 unsigned int where, uint16_t value)
62*8044SWilliam.Kucharski@Sun.COM {
63*8044SWilliam.Kucharski@Sun.COM     outl(CONFIG_CMD(bus,device_fn,where), 0xCF8);
64*8044SWilliam.Kucharski@Sun.COM     outw(value, 0xCFC + (where&2));
65*8044SWilliam.Kucharski@Sun.COM     return PCIBIOS_SUCCESSFUL;
66*8044SWilliam.Kucharski@Sun.COM }
67*8044SWilliam.Kucharski@Sun.COM 
pcibios_write_config_dword(unsigned int bus,unsigned int device_fn,unsigned int where,uint32_t value)68*8044SWilliam.Kucharski@Sun.COM int pcibios_write_config_dword (unsigned int bus, unsigned int device_fn, unsigned int where, uint32_t value)
69*8044SWilliam.Kucharski@Sun.COM {
70*8044SWilliam.Kucharski@Sun.COM     outl(CONFIG_CMD(bus,device_fn,where), 0xCF8);
71*8044SWilliam.Kucharski@Sun.COM     outl(value, 0xCFC);
72*8044SWilliam.Kucharski@Sun.COM     return PCIBIOS_SUCCESSFUL;
73*8044SWilliam.Kucharski@Sun.COM }
74*8044SWilliam.Kucharski@Sun.COM 
75*8044SWilliam.Kucharski@Sun.COM #undef CONFIG_CMD
76*8044SWilliam.Kucharski@Sun.COM 
77*8044SWilliam.Kucharski@Sun.COM #else	 /* CONFIG_PCI_DIRECT  not defined */
78*8044SWilliam.Kucharski@Sun.COM 
79*8044SWilliam.Kucharski@Sun.COM #if !defined(PCBIOS)
80*8044SWilliam.Kucharski@Sun.COM #error "The pcibios can only be used when the PCBIOS support is compiled in"
81*8044SWilliam.Kucharski@Sun.COM #endif
82*8044SWilliam.Kucharski@Sun.COM 
83*8044SWilliam.Kucharski@Sun.COM 
84*8044SWilliam.Kucharski@Sun.COM #define KERN_CODE_SEG 0X8
85*8044SWilliam.Kucharski@Sun.COM /* Stuff for asm */
86*8044SWilliam.Kucharski@Sun.COM #define save_flags(x) \
87*8044SWilliam.Kucharski@Sun.COM __asm__ __volatile__("pushfl ; popl %0":"=g" (x): /* no input */ :"memory")
88*8044SWilliam.Kucharski@Sun.COM 
89*8044SWilliam.Kucharski@Sun.COM #define cli() __asm__ __volatile__ ("cli": : :"memory")
90*8044SWilliam.Kucharski@Sun.COM 
91*8044SWilliam.Kucharski@Sun.COM #define restore_flags(x) \
92*8044SWilliam.Kucharski@Sun.COM __asm__ __volatile__("pushl %0 ; popfl": /* no output */ :"g" (x):"memory")
93*8044SWilliam.Kucharski@Sun.COM 
94*8044SWilliam.Kucharski@Sun.COM 
95*8044SWilliam.Kucharski@Sun.COM 
96*8044SWilliam.Kucharski@Sun.COM static struct {
97*8044SWilliam.Kucharski@Sun.COM 	unsigned long address;
98*8044SWilliam.Kucharski@Sun.COM 	unsigned short segment;
99*8044SWilliam.Kucharski@Sun.COM } bios32_indirect = { 0, KERN_CODE_SEG };
100*8044SWilliam.Kucharski@Sun.COM 
101*8044SWilliam.Kucharski@Sun.COM static long pcibios_entry = 0;
102*8044SWilliam.Kucharski@Sun.COM static struct {
103*8044SWilliam.Kucharski@Sun.COM 	unsigned long address;
104*8044SWilliam.Kucharski@Sun.COM 	unsigned short segment;
105*8044SWilliam.Kucharski@Sun.COM } pci_indirect = { 0, KERN_CODE_SEG };
106*8044SWilliam.Kucharski@Sun.COM 
bios32_service(unsigned long service)107*8044SWilliam.Kucharski@Sun.COM static unsigned long bios32_service(unsigned long service)
108*8044SWilliam.Kucharski@Sun.COM {
109*8044SWilliam.Kucharski@Sun.COM 	unsigned char return_code;	/* %al */
110*8044SWilliam.Kucharski@Sun.COM 	unsigned long address;		/* %ebx */
111*8044SWilliam.Kucharski@Sun.COM 	unsigned long length;		/* %ecx */
112*8044SWilliam.Kucharski@Sun.COM 	unsigned long entry;		/* %edx */
113*8044SWilliam.Kucharski@Sun.COM 	unsigned long flags;
114*8044SWilliam.Kucharski@Sun.COM 
115*8044SWilliam.Kucharski@Sun.COM 	save_flags(flags);
116*8044SWilliam.Kucharski@Sun.COM 	__asm__(
117*8044SWilliam.Kucharski@Sun.COM #ifdef ABSOLUTE_WITHOUT_ASTERISK
118*8044SWilliam.Kucharski@Sun.COM 		"lcall (%%edi)"
119*8044SWilliam.Kucharski@Sun.COM #else
120*8044SWilliam.Kucharski@Sun.COM 		"lcall *(%%edi)"
121*8044SWilliam.Kucharski@Sun.COM #endif
122*8044SWilliam.Kucharski@Sun.COM 		: "=a" (return_code),
123*8044SWilliam.Kucharski@Sun.COM 		  "=b" (address),
124*8044SWilliam.Kucharski@Sun.COM 		  "=c" (length),
125*8044SWilliam.Kucharski@Sun.COM 		  "=d" (entry)
126*8044SWilliam.Kucharski@Sun.COM 		: "0" (service),
127*8044SWilliam.Kucharski@Sun.COM 		  "1" (0),
128*8044SWilliam.Kucharski@Sun.COM 		  "D" (&bios32_indirect));
129*8044SWilliam.Kucharski@Sun.COM 	restore_flags(flags);
130*8044SWilliam.Kucharski@Sun.COM 
131*8044SWilliam.Kucharski@Sun.COM 	switch (return_code) {
132*8044SWilliam.Kucharski@Sun.COM 		case 0:
133*8044SWilliam.Kucharski@Sun.COM 			return address + entry;
134*8044SWilliam.Kucharski@Sun.COM 		case 0x80:	/* Not present */
135*8044SWilliam.Kucharski@Sun.COM 			printf("bios32_service(%d) : not present\n", service);
136*8044SWilliam.Kucharski@Sun.COM 			return 0;
137*8044SWilliam.Kucharski@Sun.COM 		default: /* Shouldn't happen */
138*8044SWilliam.Kucharski@Sun.COM 			printf("bios32_service(%d) : returned %#X, mail drew@colorado.edu\n",
139*8044SWilliam.Kucharski@Sun.COM 				service, return_code);
140*8044SWilliam.Kucharski@Sun.COM 			return 0;
141*8044SWilliam.Kucharski@Sun.COM 	}
142*8044SWilliam.Kucharski@Sun.COM }
143*8044SWilliam.Kucharski@Sun.COM 
pcibios_read_config_byte(unsigned int bus,unsigned int device_fn,unsigned int where,uint8_t * value)144*8044SWilliam.Kucharski@Sun.COM int pcibios_read_config_byte(unsigned int bus,
145*8044SWilliam.Kucharski@Sun.COM         unsigned int device_fn, unsigned int where, uint8_t *value)
146*8044SWilliam.Kucharski@Sun.COM {
147*8044SWilliam.Kucharski@Sun.COM         unsigned long ret;
148*8044SWilliam.Kucharski@Sun.COM         unsigned long bx = (bus << 8) | device_fn;
149*8044SWilliam.Kucharski@Sun.COM         unsigned long flags;
150*8044SWilliam.Kucharski@Sun.COM 
151*8044SWilliam.Kucharski@Sun.COM         save_flags(flags);
152*8044SWilliam.Kucharski@Sun.COM         __asm__(
153*8044SWilliam.Kucharski@Sun.COM #ifdef ABSOLUTE_WITHOUT_ASTERISK
154*8044SWilliam.Kucharski@Sun.COM 		"lcall (%%esi)\n\t"
155*8044SWilliam.Kucharski@Sun.COM #else
156*8044SWilliam.Kucharski@Sun.COM 		"lcall *(%%esi)\n\t"
157*8044SWilliam.Kucharski@Sun.COM #endif
158*8044SWilliam.Kucharski@Sun.COM                 "jc 1f\n\t"
159*8044SWilliam.Kucharski@Sun.COM                 "xor %%ah, %%ah\n"
160*8044SWilliam.Kucharski@Sun.COM                 "1:"
161*8044SWilliam.Kucharski@Sun.COM                 : "=c" (*value),
162*8044SWilliam.Kucharski@Sun.COM                   "=a" (ret)
163*8044SWilliam.Kucharski@Sun.COM                 : "1" (PCIBIOS_READ_CONFIG_BYTE),
164*8044SWilliam.Kucharski@Sun.COM                   "b" (bx),
165*8044SWilliam.Kucharski@Sun.COM                   "D" ((long) where),
166*8044SWilliam.Kucharski@Sun.COM                   "S" (&pci_indirect));
167*8044SWilliam.Kucharski@Sun.COM         restore_flags(flags);
168*8044SWilliam.Kucharski@Sun.COM         return (int) (ret & 0xff00) >> 8;
169*8044SWilliam.Kucharski@Sun.COM }
170*8044SWilliam.Kucharski@Sun.COM 
pcibios_read_config_word(unsigned int bus,unsigned int device_fn,unsigned int where,uint16_t * value)171*8044SWilliam.Kucharski@Sun.COM int pcibios_read_config_word(unsigned int bus,
172*8044SWilliam.Kucharski@Sun.COM         unsigned int device_fn, unsigned int where, uint16_t *value)
173*8044SWilliam.Kucharski@Sun.COM {
174*8044SWilliam.Kucharski@Sun.COM         unsigned long ret;
175*8044SWilliam.Kucharski@Sun.COM         unsigned long bx = (bus << 8) | device_fn;
176*8044SWilliam.Kucharski@Sun.COM         unsigned long flags;
177*8044SWilliam.Kucharski@Sun.COM 
178*8044SWilliam.Kucharski@Sun.COM         save_flags(flags);
179*8044SWilliam.Kucharski@Sun.COM         __asm__(
180*8044SWilliam.Kucharski@Sun.COM #ifdef ABSOLUTE_WITHOUT_ASTERISK
181*8044SWilliam.Kucharski@Sun.COM 		"lcall (%%esi)\n\t"
182*8044SWilliam.Kucharski@Sun.COM #else
183*8044SWilliam.Kucharski@Sun.COM 		"lcall *(%%esi)\n\t"
184*8044SWilliam.Kucharski@Sun.COM #endif
185*8044SWilliam.Kucharski@Sun.COM                 "jc 1f\n\t"
186*8044SWilliam.Kucharski@Sun.COM                 "xor %%ah, %%ah\n"
187*8044SWilliam.Kucharski@Sun.COM                 "1:"
188*8044SWilliam.Kucharski@Sun.COM                 : "=c" (*value),
189*8044SWilliam.Kucharski@Sun.COM                   "=a" (ret)
190*8044SWilliam.Kucharski@Sun.COM                 : "1" (PCIBIOS_READ_CONFIG_WORD),
191*8044SWilliam.Kucharski@Sun.COM                   "b" (bx),
192*8044SWilliam.Kucharski@Sun.COM                   "D" ((long) where),
193*8044SWilliam.Kucharski@Sun.COM                   "S" (&pci_indirect));
194*8044SWilliam.Kucharski@Sun.COM         restore_flags(flags);
195*8044SWilliam.Kucharski@Sun.COM         return (int) (ret & 0xff00) >> 8;
196*8044SWilliam.Kucharski@Sun.COM }
197*8044SWilliam.Kucharski@Sun.COM 
pcibios_read_config_dword(unsigned int bus,unsigned int device_fn,unsigned int where,uint32_t * value)198*8044SWilliam.Kucharski@Sun.COM int pcibios_read_config_dword(unsigned int bus,
199*8044SWilliam.Kucharski@Sun.COM         unsigned int device_fn, unsigned int where, uint32_t *value)
200*8044SWilliam.Kucharski@Sun.COM {
201*8044SWilliam.Kucharski@Sun.COM         unsigned long ret;
202*8044SWilliam.Kucharski@Sun.COM         unsigned long bx = (bus << 8) | device_fn;
203*8044SWilliam.Kucharski@Sun.COM         unsigned long flags;
204*8044SWilliam.Kucharski@Sun.COM 
205*8044SWilliam.Kucharski@Sun.COM         save_flags(flags);
206*8044SWilliam.Kucharski@Sun.COM         __asm__(
207*8044SWilliam.Kucharski@Sun.COM #ifdef ABSOLUTE_WITHOUT_ASTERISK
208*8044SWilliam.Kucharski@Sun.COM 		"lcall (%%esi)\n\t"
209*8044SWilliam.Kucharski@Sun.COM #else
210*8044SWilliam.Kucharski@Sun.COM 		"lcall *(%%esi)\n\t"
211*8044SWilliam.Kucharski@Sun.COM #endif
212*8044SWilliam.Kucharski@Sun.COM                 "jc 1f\n\t"
213*8044SWilliam.Kucharski@Sun.COM                 "xor %%ah, %%ah\n"
214*8044SWilliam.Kucharski@Sun.COM                 "1:"
215*8044SWilliam.Kucharski@Sun.COM                 : "=c" (*value),
216*8044SWilliam.Kucharski@Sun.COM                   "=a" (ret)
217*8044SWilliam.Kucharski@Sun.COM                 : "1" (PCIBIOS_READ_CONFIG_DWORD),
218*8044SWilliam.Kucharski@Sun.COM                   "b" (bx),
219*8044SWilliam.Kucharski@Sun.COM                   "D" ((long) where),
220*8044SWilliam.Kucharski@Sun.COM                   "S" (&pci_indirect));
221*8044SWilliam.Kucharski@Sun.COM         restore_flags(flags);
222*8044SWilliam.Kucharski@Sun.COM         return (int) (ret & 0xff00) >> 8;
223*8044SWilliam.Kucharski@Sun.COM }
224*8044SWilliam.Kucharski@Sun.COM 
pcibios_write_config_byte(unsigned int bus,unsigned int device_fn,unsigned int where,uint8_t value)225*8044SWilliam.Kucharski@Sun.COM int pcibios_write_config_byte (unsigned int bus,
226*8044SWilliam.Kucharski@Sun.COM 	unsigned int device_fn, unsigned int where, uint8_t value)
227*8044SWilliam.Kucharski@Sun.COM {
228*8044SWilliam.Kucharski@Sun.COM 	unsigned long ret;
229*8044SWilliam.Kucharski@Sun.COM 	unsigned long bx = (bus << 8) | device_fn;
230*8044SWilliam.Kucharski@Sun.COM 	unsigned long flags;
231*8044SWilliam.Kucharski@Sun.COM 
232*8044SWilliam.Kucharski@Sun.COM 	save_flags(flags); cli();
233*8044SWilliam.Kucharski@Sun.COM 	__asm__(
234*8044SWilliam.Kucharski@Sun.COM #ifdef ABSOLUTE_WITHOUT_ASTERISK
235*8044SWilliam.Kucharski@Sun.COM 		"lcall (%%esi)\n\t"
236*8044SWilliam.Kucharski@Sun.COM #else
237*8044SWilliam.Kucharski@Sun.COM 		"lcall *(%%esi)\n\t"
238*8044SWilliam.Kucharski@Sun.COM #endif
239*8044SWilliam.Kucharski@Sun.COM 		"jc 1f\n\t"
240*8044SWilliam.Kucharski@Sun.COM 		"xor %%ah, %%ah\n"
241*8044SWilliam.Kucharski@Sun.COM 		"1:"
242*8044SWilliam.Kucharski@Sun.COM 		: "=a" (ret)
243*8044SWilliam.Kucharski@Sun.COM 		: "0" (PCIBIOS_WRITE_CONFIG_BYTE),
244*8044SWilliam.Kucharski@Sun.COM 		  "c" (value),
245*8044SWilliam.Kucharski@Sun.COM 		  "b" (bx),
246*8044SWilliam.Kucharski@Sun.COM 		  "D" ((long) where),
247*8044SWilliam.Kucharski@Sun.COM 		  "S" (&pci_indirect));
248*8044SWilliam.Kucharski@Sun.COM 	restore_flags(flags);
249*8044SWilliam.Kucharski@Sun.COM 	return (int) (ret & 0xff00) >> 8;
250*8044SWilliam.Kucharski@Sun.COM }
251*8044SWilliam.Kucharski@Sun.COM 
pcibios_write_config_word(unsigned int bus,unsigned int device_fn,unsigned int where,uint16_t value)252*8044SWilliam.Kucharski@Sun.COM int pcibios_write_config_word (unsigned int bus,
253*8044SWilliam.Kucharski@Sun.COM 	unsigned int device_fn, unsigned int where, uint16_t value)
254*8044SWilliam.Kucharski@Sun.COM {
255*8044SWilliam.Kucharski@Sun.COM 	unsigned long ret;
256*8044SWilliam.Kucharski@Sun.COM 	unsigned long bx = (bus << 8) | device_fn;
257*8044SWilliam.Kucharski@Sun.COM 	unsigned long flags;
258*8044SWilliam.Kucharski@Sun.COM 
259*8044SWilliam.Kucharski@Sun.COM 	save_flags(flags); cli();
260*8044SWilliam.Kucharski@Sun.COM 	__asm__(
261*8044SWilliam.Kucharski@Sun.COM #ifdef ABSOLUTE_WITHOUT_ASTERISK
262*8044SWilliam.Kucharski@Sun.COM 		"lcall (%%esi)\n\t"
263*8044SWilliam.Kucharski@Sun.COM #else
264*8044SWilliam.Kucharski@Sun.COM 		"lcall *(%%esi)\n\t"
265*8044SWilliam.Kucharski@Sun.COM #endif
266*8044SWilliam.Kucharski@Sun.COM 		"jc 1f\n\t"
267*8044SWilliam.Kucharski@Sun.COM 		"xor %%ah, %%ah\n"
268*8044SWilliam.Kucharski@Sun.COM 		"1:"
269*8044SWilliam.Kucharski@Sun.COM 		: "=a" (ret)
270*8044SWilliam.Kucharski@Sun.COM 		: "0" (PCIBIOS_WRITE_CONFIG_WORD),
271*8044SWilliam.Kucharski@Sun.COM 		  "c" (value),
272*8044SWilliam.Kucharski@Sun.COM 		  "b" (bx),
273*8044SWilliam.Kucharski@Sun.COM 		  "D" ((long) where),
274*8044SWilliam.Kucharski@Sun.COM 		  "S" (&pci_indirect));
275*8044SWilliam.Kucharski@Sun.COM 	restore_flags(flags);
276*8044SWilliam.Kucharski@Sun.COM 	return (int) (ret & 0xff00) >> 8;
277*8044SWilliam.Kucharski@Sun.COM }
278*8044SWilliam.Kucharski@Sun.COM 
pcibios_write_config_dword(unsigned int bus,unsigned int device_fn,unsigned int where,uint32_t value)279*8044SWilliam.Kucharski@Sun.COM int pcibios_write_config_dword (unsigned int bus,
280*8044SWilliam.Kucharski@Sun.COM 	unsigned int device_fn, unsigned int where, uint32_t value)
281*8044SWilliam.Kucharski@Sun.COM {
282*8044SWilliam.Kucharski@Sun.COM 	unsigned long ret;
283*8044SWilliam.Kucharski@Sun.COM 	unsigned long bx = (bus << 8) | device_fn;
284*8044SWilliam.Kucharski@Sun.COM 	unsigned long flags;
285*8044SWilliam.Kucharski@Sun.COM 
286*8044SWilliam.Kucharski@Sun.COM 	save_flags(flags); cli();
287*8044SWilliam.Kucharski@Sun.COM 	__asm__(
288*8044SWilliam.Kucharski@Sun.COM #ifdef ABSOLUTE_WITHOUT_ASTERISK
289*8044SWilliam.Kucharski@Sun.COM 		"lcall (%%esi)\n\t"
290*8044SWilliam.Kucharski@Sun.COM #else
291*8044SWilliam.Kucharski@Sun.COM 		"lcall *(%%esi)\n\t"
292*8044SWilliam.Kucharski@Sun.COM #endif
293*8044SWilliam.Kucharski@Sun.COM 		"jc 1f\n\t"
294*8044SWilliam.Kucharski@Sun.COM 		"xor %%ah, %%ah\n"
295*8044SWilliam.Kucharski@Sun.COM 		"1:"
296*8044SWilliam.Kucharski@Sun.COM 		: "=a" (ret)
297*8044SWilliam.Kucharski@Sun.COM 		: "0" (PCIBIOS_WRITE_CONFIG_DWORD),
298*8044SWilliam.Kucharski@Sun.COM 		  "c" (value),
299*8044SWilliam.Kucharski@Sun.COM 		  "b" (bx),
300*8044SWilliam.Kucharski@Sun.COM 		  "D" ((long) where),
301*8044SWilliam.Kucharski@Sun.COM 		  "S" (&pci_indirect));
302*8044SWilliam.Kucharski@Sun.COM 	restore_flags(flags);
303*8044SWilliam.Kucharski@Sun.COM 	return (int) (ret & 0xff00) >> 8;
304*8044SWilliam.Kucharski@Sun.COM }
305*8044SWilliam.Kucharski@Sun.COM 
check_pcibios(void)306*8044SWilliam.Kucharski@Sun.COM static void check_pcibios(void)
307*8044SWilliam.Kucharski@Sun.COM {
308*8044SWilliam.Kucharski@Sun.COM 	unsigned long signature;
309*8044SWilliam.Kucharski@Sun.COM 	unsigned char present_status;
310*8044SWilliam.Kucharski@Sun.COM 	unsigned char major_revision;
311*8044SWilliam.Kucharski@Sun.COM 	unsigned char minor_revision;
312*8044SWilliam.Kucharski@Sun.COM 	unsigned long flags;
313*8044SWilliam.Kucharski@Sun.COM 	int pack;
314*8044SWilliam.Kucharski@Sun.COM 
315*8044SWilliam.Kucharski@Sun.COM 	if ((pcibios_entry = bios32_service(PCI_SERVICE))) {
316*8044SWilliam.Kucharski@Sun.COM 		pci_indirect.address = pcibios_entry;
317*8044SWilliam.Kucharski@Sun.COM 
318*8044SWilliam.Kucharski@Sun.COM 		save_flags(flags);
319*8044SWilliam.Kucharski@Sun.COM 		__asm__(
320*8044SWilliam.Kucharski@Sun.COM #ifdef ABSOLUTE_WITHOUT_ASTERISK
321*8044SWilliam.Kucharski@Sun.COM 			"lcall (%%edi)\n\t"
322*8044SWilliam.Kucharski@Sun.COM #else
323*8044SWilliam.Kucharski@Sun.COM 			"lcall *(%%edi)\n\t"
324*8044SWilliam.Kucharski@Sun.COM #endif
325*8044SWilliam.Kucharski@Sun.COM 			"jc 1f\n\t"
326*8044SWilliam.Kucharski@Sun.COM 			"xor %%ah, %%ah\n"
327*8044SWilliam.Kucharski@Sun.COM 			"1:\tshl $8, %%eax\n\t"
328*8044SWilliam.Kucharski@Sun.COM 			"movw %%bx, %%ax"
329*8044SWilliam.Kucharski@Sun.COM 			: "=d" (signature),
330*8044SWilliam.Kucharski@Sun.COM 			  "=a" (pack)
331*8044SWilliam.Kucharski@Sun.COM 			: "1" (PCIBIOS_PCI_BIOS_PRESENT),
332*8044SWilliam.Kucharski@Sun.COM 			  "D" (&pci_indirect)
333*8044SWilliam.Kucharski@Sun.COM 			: "bx", "cx");
334*8044SWilliam.Kucharski@Sun.COM 		restore_flags(flags);
335*8044SWilliam.Kucharski@Sun.COM 
336*8044SWilliam.Kucharski@Sun.COM 		present_status = (pack >> 16) & 0xff;
337*8044SWilliam.Kucharski@Sun.COM 		major_revision = (pack >> 8) & 0xff;
338*8044SWilliam.Kucharski@Sun.COM 		minor_revision = pack & 0xff;
339*8044SWilliam.Kucharski@Sun.COM 		if (present_status || (signature != PCI_SIGNATURE)) {
340*8044SWilliam.Kucharski@Sun.COM 			printf("ERROR: BIOS32 says PCI BIOS, but no PCI "
341*8044SWilliam.Kucharski@Sun.COM 				"BIOS????\n");
342*8044SWilliam.Kucharski@Sun.COM 			pcibios_entry = 0;
343*8044SWilliam.Kucharski@Sun.COM 		}
344*8044SWilliam.Kucharski@Sun.COM #if	DEBUG
345*8044SWilliam.Kucharski@Sun.COM 		if (pcibios_entry) {
346*8044SWilliam.Kucharski@Sun.COM 			printf ("pcibios_init : PCI BIOS revision %hhX.%hhX"
347*8044SWilliam.Kucharski@Sun.COM 				" entry at %#X\n", major_revision,
348*8044SWilliam.Kucharski@Sun.COM 				minor_revision, pcibios_entry);
349*8044SWilliam.Kucharski@Sun.COM 		}
350*8044SWilliam.Kucharski@Sun.COM #endif
351*8044SWilliam.Kucharski@Sun.COM 	}
352*8044SWilliam.Kucharski@Sun.COM }
353*8044SWilliam.Kucharski@Sun.COM 
pcibios_init(void)354*8044SWilliam.Kucharski@Sun.COM static void pcibios_init(void)
355*8044SWilliam.Kucharski@Sun.COM {
356*8044SWilliam.Kucharski@Sun.COM 	union bios32 *check;
357*8044SWilliam.Kucharski@Sun.COM 	unsigned char sum;
358*8044SWilliam.Kucharski@Sun.COM 	int i, length;
359*8044SWilliam.Kucharski@Sun.COM 	unsigned long bios32_entry = 0;
360*8044SWilliam.Kucharski@Sun.COM 
361*8044SWilliam.Kucharski@Sun.COM 	EnterFunction("pcibios_init");
362*8044SWilliam.Kucharski@Sun.COM 	/*
363*8044SWilliam.Kucharski@Sun.COM 	 * Follow the standard procedure for locating the BIOS32 Service
364*8044SWilliam.Kucharski@Sun.COM 	 * directory by scanning the permissible address range from
365*8044SWilliam.Kucharski@Sun.COM 	 * 0xe0000 through 0xfffff for a valid BIOS32 structure.
366*8044SWilliam.Kucharski@Sun.COM 	 *
367*8044SWilliam.Kucharski@Sun.COM 	 */
368*8044SWilliam.Kucharski@Sun.COM 
369*8044SWilliam.Kucharski@Sun.COM 	for (check = (union bios32 *) 0xe0000; check <= (union bios32 *) 0xffff0; ++check) {
370*8044SWilliam.Kucharski@Sun.COM 		if (check->fields.signature != BIOS32_SIGNATURE)
371*8044SWilliam.Kucharski@Sun.COM 			continue;
372*8044SWilliam.Kucharski@Sun.COM 		length = check->fields.length * 16;
373*8044SWilliam.Kucharski@Sun.COM 		if (!length)
374*8044SWilliam.Kucharski@Sun.COM 			continue;
375*8044SWilliam.Kucharski@Sun.COM 		sum = 0;
376*8044SWilliam.Kucharski@Sun.COM 		for (i = 0; i < length ; ++i)
377*8044SWilliam.Kucharski@Sun.COM 			sum += check->chars[i];
378*8044SWilliam.Kucharski@Sun.COM 		if (sum != 0)
379*8044SWilliam.Kucharski@Sun.COM 			continue;
380*8044SWilliam.Kucharski@Sun.COM 		if (check->fields.revision != 0) {
381*8044SWilliam.Kucharski@Sun.COM 			printf("pcibios_init : unsupported revision %d at %#X, mail drew@colorado.edu\n",
382*8044SWilliam.Kucharski@Sun.COM 				check->fields.revision, check);
383*8044SWilliam.Kucharski@Sun.COM 			continue;
384*8044SWilliam.Kucharski@Sun.COM 		}
385*8044SWilliam.Kucharski@Sun.COM #if	DEBUG
386*8044SWilliam.Kucharski@Sun.COM 		printf("pcibios_init : BIOS32 Service Directory "
387*8044SWilliam.Kucharski@Sun.COM 			"structure at %#X\n", check);
388*8044SWilliam.Kucharski@Sun.COM #endif
389*8044SWilliam.Kucharski@Sun.COM 		if (!bios32_entry) {
390*8044SWilliam.Kucharski@Sun.COM 			if (check->fields.entry >= 0x100000) {
391*8044SWilliam.Kucharski@Sun.COM 				printf("pcibios_init: entry in high "
392*8044SWilliam.Kucharski@Sun.COM 					"memory, giving up\n");
393*8044SWilliam.Kucharski@Sun.COM 				return;
394*8044SWilliam.Kucharski@Sun.COM 			} else {
395*8044SWilliam.Kucharski@Sun.COM 				bios32_entry = check->fields.entry;
396*8044SWilliam.Kucharski@Sun.COM #if	DEBUG
397*8044SWilliam.Kucharski@Sun.COM 				printf("pcibios_init : BIOS32 Service Directory"
398*8044SWilliam.Kucharski@Sun.COM 					" entry at %#X\n", bios32_entry);
399*8044SWilliam.Kucharski@Sun.COM #endif
400*8044SWilliam.Kucharski@Sun.COM 				bios32_indirect.address = bios32_entry;
401*8044SWilliam.Kucharski@Sun.COM 			}
402*8044SWilliam.Kucharski@Sun.COM 		}
403*8044SWilliam.Kucharski@Sun.COM 	}
404*8044SWilliam.Kucharski@Sun.COM 	if (bios32_entry)
405*8044SWilliam.Kucharski@Sun.COM 		check_pcibios();
406*8044SWilliam.Kucharski@Sun.COM 	LeaveFunction("pcibios_init");
407*8044SWilliam.Kucharski@Sun.COM }
408*8044SWilliam.Kucharski@Sun.COM 
409*8044SWilliam.Kucharski@Sun.COM #endif	/* CONFIG_PCI_DIRECT not defined*/
410*8044SWilliam.Kucharski@Sun.COM 
pcibios_bus_base(unsigned int bus __unused)411*8044SWilliam.Kucharski@Sun.COM unsigned long pcibios_bus_base(unsigned int bus __unused)
412*8044SWilliam.Kucharski@Sun.COM {
413*8044SWilliam.Kucharski@Sun.COM 	/* architecturally this must be 0 */
414*8044SWilliam.Kucharski@Sun.COM 	return 0;
415*8044SWilliam.Kucharski@Sun.COM }
416*8044SWilliam.Kucharski@Sun.COM 
find_pci(int type,struct pci_device * dev)417*8044SWilliam.Kucharski@Sun.COM void find_pci(int type, struct pci_device *dev)
418*8044SWilliam.Kucharski@Sun.COM {
419*8044SWilliam.Kucharski@Sun.COM 	EnterFunction("find_pci");
420*8044SWilliam.Kucharski@Sun.COM #ifndef	CONFIG_PCI_DIRECT
421*8044SWilliam.Kucharski@Sun.COM 	if (!pcibios_entry) {
422*8044SWilliam.Kucharski@Sun.COM 		pcibios_init();
423*8044SWilliam.Kucharski@Sun.COM 	}
424*8044SWilliam.Kucharski@Sun.COM 	if (!pcibios_entry) {
425*8044SWilliam.Kucharski@Sun.COM 		printf("pci_init: no BIOS32 detected\n");
426*8044SWilliam.Kucharski@Sun.COM 		return;
427*8044SWilliam.Kucharski@Sun.COM 	}
428*8044SWilliam.Kucharski@Sun.COM #endif
429*8044SWilliam.Kucharski@Sun.COM 	LeaveFunction("find_pci");
430*8044SWilliam.Kucharski@Sun.COM 	return scan_pci_bus(type, dev);
431*8044SWilliam.Kucharski@Sun.COM }
432