source: rtems/c/src/lib/libbsp/i386/shared/pci/pcibios.c @ 6ce94bc3

4.104.114.84.95
Last change on this file since 6ce94bc3 was 6ce94bc3, checked in by Ralf Corsepius <ralf.corsepius@…>, on 09/02/02 at 06:15:21

2002-09-02 Ralf Corsepius <corsepiu@…>

  • pci/pcibios.c: #include <string.h>.
  • Property mode set to 100644
File size: 9.8 KB
Line 
1/*
2 * This software is Copyright (C) 1998 by T.sqware - all rights limited
3 * It is provided in to the public domain "as is", can be freely modified
4 * as far as this copyight notice is kept unchanged, but does not imply
5 * an endorsement by T.sqware of the product in which it is included.
6 *
7 *  $Id$
8 */
9
10#include <rtems.h>
11#include <bsp.h>
12#include <pcibios.h>
13
14#include <string.h>     /* memcpy */
15
16/*
17 * This is simpliest possible PCI BIOS, it assumes that addressing
18 * is flat and that stack is big enough
19 */
20
21
22static int pcibInitialized = 0;
23static unsigned int pcibEntry;
24
25/*
26 * Array to pass data between c and asm parts, at the time of
27 * writing I am not yet that familiar with extended asm feature
28 * of gcc. This code is not on performance path, so we can care
29 * relatively little about performance here
30 */
31static volatile unsigned int pcibExchg[5];
32
33static int pcib_convert_err(int err);
34
35/*
36 * Detects presense of PCI BIOS, returns
37 * error code
38 */
39int
40pcib_init(void)
41{
42  unsigned char *ucp;
43  unsigned char sum;
44  int      i;
45
46  pcibInitialized = 0;
47
48  /* First, we have to look for BIOS-32 */
49  for(ucp=(unsigned char *)0xE0000; ucp < (unsigned char *)0xFFFFF; ucp+=0x10)
50    {
51      if(memcmp(ucp, "_32_", 4) != 0)
52        {
53          continue;
54        }
55
56      /* Got signature, check length  */
57      if(*(ucp + 9) != 1)
58        {
59          continue;
60        }
61
62      /* Verify checksum */
63      sum = 0;
64      for(i=0; i<16; i++)
65        {
66          sum += *(ucp+i);
67        }
68
69      if(sum == 0)
70        {
71          /* found */
72          break;
73        }
74    }
75
76  if(ucp >= (unsigned char *)0xFFFFF)
77    {
78      /* BIOS-32 not found */
79      return PCIB_ERR_NOTPRESENT;
80    }
81
82  /* BIOS-32 found, let us find PCI BIOS */
83  ucp += 4;
84
85  pcibExchg[0] = *(unsigned int *)ucp;
86
87  asm ("    pusha");                  /* Push all registers */ 
88  asm ("    movl pcibExchg, %edi");   /* Move entry point to esi */
89  asm ("    movl $0x49435024, %eax"); /* Move signature to eax */
90  asm ("    xorl %ebx, %ebx");        /* Zero ebx */
91  asm ("    pushl %cs");
92  asm ("    call *%edi");             /* Call entry */
93  asm ("    movl %eax, pcibExchg");
94  asm ("    movl %ebx, pcibExchg+4");
95  asm ("    movl %ecx, pcibExchg+8");
96  asm ("    movl %edx, pcibExchg+12");
97  asm ("    popa");
98
99  if((pcibExchg[0] & 0xff) != 0)
100    {
101      /* Not found */
102      return PCIB_ERR_NOTPRESENT;
103    }
104
105  /* Found PCI entry point */
106  pcibEntry = pcibExchg[1] + pcibExchg[3];
107
108  /* Let us check whether PCI bios is present */
109  pcibExchg[0] = pcibEntry;
110 
111  asm("    pusha");
112  asm("    movl pcibExchg, %edi");
113  asm("    movb $0xb1, %ah");
114  asm("    movb $0x01, %al");
115  asm ("   pushl %cs");
116  asm("    call *%edi");
117  asm("    movl %eax, pcibExchg");
118  asm("    movl %ebx, pcibExchg+4");
119  asm("    movl %ecx, pcibExchg+8");
120  asm("    movl %edx, pcibExchg+12");
121  asm("    popa");
122
123  if((pcibExchg[0] & 0xff00) != 0)
124    {
125      /* Not found */
126      return PCIB_ERR_NOTPRESENT;
127    }
128
129  if(pcibExchg[3] != 0x20494350)
130    {
131      /* Signature does not match */
132      return PCIB_ERR_NOTPRESENT;
133    }
134
135  /* Success */
136 
137  pcibInitialized = 1;
138  return PCIB_ERR_SUCCESS;
139}
140
141/*
142 * Find specified device and return its signature: combination
143 * of bus number, device number and function number
144 */
145int
146pcib_find_by_devid(int vendorId, int devId, int idx, int *sig)
147{
148  if(!pcibInitialized)
149    {
150      return PCIB_ERR_UNINITIALIZED;
151    }
152
153  pcibExchg[0] = pcibEntry;
154  pcibExchg[1] = vendorId;
155  pcibExchg[2] = devId;
156  pcibExchg[3] = idx;
157
158  asm("    pusha");
159  asm("    movl pcibExchg, %edi");
160  asm("    movb $0xb1, %ah");
161  asm("    movb $0x02, %al");
162  asm("    movl pcibExchg+4, %edx");
163  asm("    movl pcibExchg+8, %ecx");
164  asm("    movl pcibExchg+12, %esi");
165  asm("    pushl %cs");
166  asm("    call *%edi");
167  asm("    movl %eax, pcibExchg");
168  asm("    movl %ebx, pcibExchg+4");
169  asm("    popa");
170
171  *sig = pcibExchg[1] & 0xffff;
172
173  return pcib_convert_err((pcibExchg[0] >> 8) & 0xff);
174}
175
176/*
177 * Find specified class code return device signature: combination
178 * of bus number, device number and function number
179 */
180int
181pcib_find_by_class(int classCode, int idx, int *sig)
182{
183  if(!pcibInitialized)
184    {
185      return PCIB_ERR_UNINITIALIZED;
186    }
187
188  pcibExchg[0] = pcibEntry;
189  pcibExchg[1] = classCode;
190  pcibExchg[2] = idx;
191
192  asm("    pusha");
193  asm("    movl pcibExchg, %edi");
194  asm("    movb $0xb1, %ah");
195  asm("    movb $0x03, %al");
196  asm("    movl pcibExchg+4, %ecx");
197  asm("    movl pcibExchg+8, %esi");
198  asm("    pushl %cs");
199  asm("    call *%edi");
200  asm("    movl %eax, pcibExchg");
201  asm("    movl %ebx, pcibExchg+4");
202  asm("    popa");
203
204  if((pcibExchg[0] & 0xff00) != 0)
205    {
206      return pcib_convert_err((pcibExchg[0] >> 8) & 0xff);
207    }
208
209  *sig = pcibExchg[1] & 0xffff;
210
211  return PCIB_ERR_SUCCESS;
212}
213 
214 
215
216/*
217 * Generate Special Cycle
218 */
219int
220pcib_special_cycle(int busNo, int data)
221{
222  if(!pcibInitialized)
223    {
224      return PCIB_ERR_UNINITIALIZED;
225    }
226
227  pcibExchg[0] = pcibEntry;
228  pcibExchg[1] = busNo << 8;
229  pcibExchg[2] = data;
230
231  asm("    pusha");
232  asm("    movl pcibExchg, %edi");
233  asm("    movb $0xb1, %ah");
234  asm("    movb $0x06, %al");
235  asm("    movl pcibExchg+4, %ebx");
236  asm("    movl pcibExchg+8, %edx");
237  asm("    pushl %cs");
238  asm("    call *%edi");
239  asm("    movl %eax, pcibExchg");
240  asm("    movl %ebx, pcibExchg+4");
241  asm("    popa");
242
243  return pcib_convert_err((pcibExchg[0] >> 8) & 0xff);
244}
245 
246
247/*
248 * Read byte from config space
249 */
250int
251pcib_conf_read8(int sig, int off, unsigned char *data)
252{
253  if(!pcibInitialized)
254    {
255      return PCIB_ERR_UNINITIALIZED;
256    }
257
258  pcibExchg[0] = pcibEntry;
259  pcibExchg[1] = sig;
260  pcibExchg[2] = off;
261
262  asm("    pusha");
263  asm("    movl pcibExchg, %esi");
264  asm("    movb $0xb1, %ah");
265  asm("    movb $0x08, %al");
266  asm("    movl pcibExchg+4, %ebx");
267  asm("    movl pcibExchg+8, %edi");
268  asm("    pushl %cs");
269  asm("    call *%esi");
270  asm("    movl %eax, pcibExchg");
271  asm("    movl %ecx, pcibExchg+4");
272  asm("    popa");
273
274  if((pcibExchg[0] & 0xff00) != 0)
275    {
276      return pcib_convert_err((pcibExchg[0] >> 8) & 0xff);
277    }
278
279  *data = (unsigned char)pcibExchg[1] & 0xff;
280
281  return PCIB_ERR_SUCCESS;
282}
283 
284
285/*
286 * Read word from config space
287 */
288int
289pcib_conf_read16(int sig, int off, unsigned short *data)
290{
291  if(!pcibInitialized)
292    {
293      return PCIB_ERR_UNINITIALIZED;
294    }
295
296  pcibExchg[0] = pcibEntry;
297  pcibExchg[1] = sig;
298  pcibExchg[2] = off;
299
300  asm("    pusha");
301  asm("    movl pcibExchg, %esi");
302  asm("    movb $0xb1, %ah");
303  asm("    movb $0x09, %al");
304  asm("    movl pcibExchg+4, %ebx");
305  asm("    movl pcibExchg+8, %edi");
306  asm("    pushl %cs");
307  asm("    call *%esi");
308  asm("    movl %eax, pcibExchg");
309  asm("    movl %ecx, pcibExchg+4");
310  asm("    popa");
311
312  if((pcibExchg[0] & 0xff00) != 0)
313    {
314      return pcib_convert_err((pcibExchg[0] >> 8) & 0xff);
315    }
316
317  *data = (unsigned short)pcibExchg[1] & 0xffff;
318
319  return PCIB_ERR_SUCCESS;
320}
321 
322
323/*
324 * Read dword from config space
325 */
326int
327pcib_conf_read32(int sig, int off, unsigned int *data)
328{
329  if(!pcibInitialized)
330    {
331      return PCIB_ERR_UNINITIALIZED;
332    }
333
334  pcibExchg[0] = pcibEntry;
335  pcibExchg[1] = sig;
336  pcibExchg[2] = off;
337
338  asm("    pusha");
339  asm("    movl pcibExchg, %esi");
340  asm("    movb $0xb1, %ah");
341  asm("    movb $0x0a, %al");
342  asm("    movl pcibExchg+4, %ebx");
343  asm("    movl pcibExchg+8, %edi");
344  asm("    pushl %cs");
345  asm("    call *%esi");
346  asm("    movl %eax, pcibExchg");
347  asm("    movl %ecx, pcibExchg+4");
348  asm("    popa");
349
350  if((pcibExchg[0] & 0xff00) != 0)
351    {
352      return pcib_convert_err((pcibExchg[0] >> 8) & 0xff);
353    }
354
355  *data = (unsigned int)pcibExchg[1];
356
357  return PCIB_ERR_SUCCESS;
358}
359 
360
361/*
362 * Write byte into  config space
363 */
364int
365pcib_conf_write8(int sig, int off, unsigned int data)
366{
367  if(!pcibInitialized)
368    {
369      return PCIB_ERR_UNINITIALIZED;
370    }
371
372  pcibExchg[0] = pcibEntry;
373  pcibExchg[1] = sig;
374  pcibExchg[2] = off;
375  pcibExchg[3] = data & 0xff;
376
377  asm("    pusha");
378  asm("    movl pcibExchg, %esi");
379  asm("    movb $0xb1, %ah");
380  asm("    movb $0x0b, %al");
381  asm("    movl pcibExchg+4, %ebx");
382  asm("    movl pcibExchg+8, %edi");
383  asm("    movl pcibExchg+12, %ecx");
384  asm("    pushl %cs");
385  asm("    call *%esi");
386  asm("    movl %eax, pcibExchg");
387  asm("    popa");
388
389  return pcib_convert_err((pcibExchg[0] >> 8) & 0xff);
390}
391
392/*
393 * Write word into config space
394 */
395int
396pcib_conf_write16(int sig, int off, unsigned int data)
397{
398  if(!pcibInitialized)
399    {
400      return PCIB_ERR_UNINITIALIZED;
401    }
402
403  pcibExchg[0] = pcibEntry;
404  pcibExchg[1] = sig;
405  pcibExchg[2] = off;
406  pcibExchg[3] = data & 0xffff;
407
408  asm("    pusha");
409  asm("    movl pcibExchg, %esi");
410  asm("    movb $0xb1, %ah");
411  asm("    movb $0x0c, %al");
412  asm("    movl pcibExchg+4, %ebx");
413  asm("    movl pcibExchg+8, %edi");
414  asm("    movl pcibExchg+12, %ecx");
415  asm("    pushl %cs");
416  asm("    call *%esi");
417  asm("    movl %eax, pcibExchg");
418  asm("    popa");
419
420  return pcib_convert_err((pcibExchg[0] >> 8) & 0xff);
421}
422 
423
424
425/*
426 * Write dword into config space
427 */
428int
429pcib_conf_write32(int sig, int off, unsigned int data)
430{
431  if(!pcibInitialized)
432    {
433      return PCIB_ERR_UNINITIALIZED;
434    }
435
436  pcibExchg[0] = pcibEntry;
437  pcibExchg[1] = sig;
438  pcibExchg[2] = off;
439  pcibExchg[3] = data;
440
441  asm("    pusha");
442  asm("    movl pcibExchg, %esi");
443  asm("    movb $0xb1, %ah");
444  asm("    movb $0x0d, %al");
445  asm("    movl pcibExchg+4, %ebx");
446  asm("    movl pcibExchg+8, %edi");
447  asm("    movl pcibExchg+12, %ecx");
448  asm("    pushl %cs");
449  asm("    call *%esi");
450  asm("    movl %eax, pcibExchg");
451  asm("    popa");
452
453  return pcib_convert_err((pcibExchg[0] >> 8) & 0xff);
454}
455 
456
457static int
458pcib_convert_err(int err)
459{
460  switch(err & 0xff)
461    {
462    case 0:
463      return PCIB_ERR_SUCCESS;
464    case 0x81:
465      return PCIB_ERR_NOFUNC;
466    case 0x83:
467      return PCIB_ERR_BADVENDOR;
468    case 0x86:
469      return PCIB_ERR_DEVNOTFOUND;
470    case 0x87:
471      return PCIB_ERR_BADREG;
472    default:
473      break;
474    }
475  return PCIB_ERR_NOFUNC;
476}
477       
478     
479
480
481 
482     
483 
484
485
486
Note: See TracBrowser for help on using the repository browser.