source: rtems/c/src/lib/libbsp/i386/shared/pci/pcibios.c @ 0aa6384

4.104.114.84.95
Last change on this file since 0aa6384 was 6e242f0, checked in by Joel Sherrill <joel.sherrill@…>, on 08/05/02 at 20:13:45

2002-08-05 Eric Norum <eric.norum@…>

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