source: rtems/c/src/lib/libbsp/i386/shared/pci/pcibios.c @ 734d1c5d

Last change on this file since 734d1c5d was 734d1c5d, checked in by Joel Sherrill <joel.sherrill@…>, on 07/18/03 at 15:51:38

2003-07-16 Greg Menke <gregory.menke@…>

PR 428/bsps
PR 432/bsps

  • pci/pcibios.c, pci/pcibios.h: Added BSP_pci_Find_Device() which is copied from motorola_shared.
  • Property mode set to 100644
File size: 11.5 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#define PCI_MULTI_FUNCTION       0x80
218#define PCI_MAX_DEVICES          16
219#define PCI_MAX_FUNCTIONS        8
220
221
222int
223BSP_pciFindDevice( unsigned short vendorid, unsigned short deviceid,
224                   int instance, int *pbus, int *pdev, int *pfun )
225{
226   int sig;
227   unsigned int d;
228   unsigned short s;
229   unsigned char bus,dev,fun,hd;
230
231   for (bus=0; bus<BusCountPCI(); bus++)
232   {
233      for (dev=0; dev<PCI_MAX_DEVICES; dev++)
234      {
235         sig = PCIB_DEVSIG_MAKE(bus,dev,0);
236
237         /* pci_read_config_byte(bus,dev,0, PCI_HEADER_TYPE, &hd); */
238         pcib_conf_read8(sig, 0xe, &hd);
239
240         hd = (hd & PCI_MULTI_FUNCTION ? PCI_MAX_FUNCTIONS : 1);
241
242         for (fun=0; fun<hd; fun++) {
243            /*
244             * The last devfn id/slot is special; must skip it
245             */
246            if( PCI_MAX_DEVICES-1 == dev && PCI_MAX_FUNCTIONS-1 == fun )
247               break;
248
249            /*pci_read_config_dword(bus,dev,fun,PCI_VENDOR_ID,&d); */
250            pcib_conf_read32(sig, 0, &d);
251            if( d == -1 )
252               continue;
253#ifdef PCI_DEBUG
254            printk("BSP_pciFindDevice: found 0x%08x at %d/%d/%d\n",d,bus,dev,fun);
255#endif
256            /* pci_read_config_word(bus,dev,fun,PCI_VENDOR_ID,&s); */
257            pcib_conf_read16(sig, 0, &s);
258            if (vendorid != s)
259               continue;
260
261            /* pci_read_config_word(bus,dev,fun,PCI_DEVICE_ID,&s); */
262            pcib_conf_read16(sig, 0x2, &s);
263            if (deviceid == s) {
264               if (instance--) continue;
265               *pbus=bus;
266               *pdev=dev;
267               *pfun=fun;
268               return 0;
269            }
270         }
271      }
272   }
273   return -1;
274}
275
276
277 
278
279/*
280 * Generate Special Cycle
281 */
282int
283pcib_special_cycle(int busNo, int data)
284{
285  if(!pcibInitialized)
286    {
287      return PCIB_ERR_UNINITIALIZED;
288    }
289
290  pcibExchg[0] = pcibEntry;
291  pcibExchg[1] = busNo << 8;
292  pcibExchg[2] = data;
293
294  asm("    pusha");
295  asm("    movl pcibExchg, %edi");
296  asm("    movb $0xb1, %ah");
297  asm("    movb $0x06, %al");
298  asm("    movl pcibExchg+4, %ebx");
299  asm("    movl pcibExchg+8, %edx");
300  asm("    pushl %cs");
301  asm("    call *%edi");
302  asm("    movl %eax, pcibExchg");
303  asm("    movl %ebx, pcibExchg+4");
304  asm("    popa");
305
306  return pcib_convert_err((pcibExchg[0] >> 8) & 0xff);
307}
308 
309
310/*
311 * Read byte from config space
312 */
313int
314pcib_conf_read8(int sig, int off, unsigned char *data)
315{
316  if(!pcibInitialized)
317    {
318      return PCIB_ERR_UNINITIALIZED;
319    }
320
321  pcibExchg[0] = pcibEntry;
322  pcibExchg[1] = sig;
323  pcibExchg[2] = off;
324
325  asm("    pusha");
326  asm("    movl pcibExchg, %esi");
327  asm("    movb $0xb1, %ah");
328  asm("    movb $0x08, %al");
329  asm("    movl pcibExchg+4, %ebx");
330  asm("    movl pcibExchg+8, %edi");
331  asm("    pushl %cs");
332  asm("    call *%esi");
333  asm("    movl %eax, pcibExchg");
334  asm("    movl %ecx, pcibExchg+4");
335  asm("    popa");
336
337  if((pcibExchg[0] & 0xff00) != 0)
338    {
339      return pcib_convert_err((pcibExchg[0] >> 8) & 0xff);
340    }
341
342  *data = (unsigned char)pcibExchg[1] & 0xff;
343
344  return PCIB_ERR_SUCCESS;
345}
346 
347
348/*
349 * Read word from config space
350 */
351int
352pcib_conf_read16(int sig, int off, unsigned short *data)
353{
354  if(!pcibInitialized)
355    {
356      return PCIB_ERR_UNINITIALIZED;
357    }
358
359  pcibExchg[0] = pcibEntry;
360  pcibExchg[1] = sig;
361  pcibExchg[2] = off;
362
363  asm("    pusha");
364  asm("    movl pcibExchg, %esi");
365  asm("    movb $0xb1, %ah");
366  asm("    movb $0x09, %al");
367  asm("    movl pcibExchg+4, %ebx");
368  asm("    movl pcibExchg+8, %edi");
369  asm("    pushl %cs");
370  asm("    call *%esi");
371  asm("    movl %eax, pcibExchg");
372  asm("    movl %ecx, pcibExchg+4");
373  asm("    popa");
374
375  if((pcibExchg[0] & 0xff00) != 0)
376    {
377      return pcib_convert_err((pcibExchg[0] >> 8) & 0xff);
378    }
379
380  *data = (unsigned short)pcibExchg[1] & 0xffff;
381
382  return PCIB_ERR_SUCCESS;
383}
384 
385
386/*
387 * Read dword from config space
388 */
389int
390pcib_conf_read32(int sig, int off, unsigned int *data)
391{
392  if(!pcibInitialized)
393    {
394      return PCIB_ERR_UNINITIALIZED;
395    }
396
397  pcibExchg[0] = pcibEntry;
398  pcibExchg[1] = sig;
399  pcibExchg[2] = off;
400
401  asm("    pusha");
402  asm("    movl pcibExchg, %esi");
403  asm("    movb $0xb1, %ah");
404  asm("    movb $0x0a, %al");
405  asm("    movl pcibExchg+4, %ebx");
406  asm("    movl pcibExchg+8, %edi");
407  asm("    pushl %cs");
408  asm("    call *%esi");
409  asm("    movl %eax, pcibExchg");
410  asm("    movl %ecx, pcibExchg+4");
411  asm("    popa");
412
413  if((pcibExchg[0] & 0xff00) != 0)
414    {
415      return pcib_convert_err((pcibExchg[0] >> 8) & 0xff);
416    }
417
418  *data = (unsigned int)pcibExchg[1];
419
420  return PCIB_ERR_SUCCESS;
421}
422 
423
424/*
425 * Write byte into  config space
426 */
427int
428pcib_conf_write8(int sig, int off, unsigned int data)
429{
430  if(!pcibInitialized)
431    {
432      return PCIB_ERR_UNINITIALIZED;
433    }
434
435  pcibExchg[0] = pcibEntry;
436  pcibExchg[1] = sig;
437  pcibExchg[2] = off;
438  pcibExchg[3] = data & 0xff;
439
440  asm("    pusha");
441  asm("    movl pcibExchg, %esi");
442  asm("    movb $0xb1, %ah");
443  asm("    movb $0x0b, %al");
444  asm("    movl pcibExchg+4, %ebx");
445  asm("    movl pcibExchg+8, %edi");
446  asm("    movl pcibExchg+12, %ecx");
447  asm("    pushl %cs");
448  asm("    call *%esi");
449  asm("    movl %eax, pcibExchg");
450  asm("    popa");
451
452  return pcib_convert_err((pcibExchg[0] >> 8) & 0xff);
453}
454
455/*
456 * Write word into config space
457 */
458int
459pcib_conf_write16(int sig, int off, unsigned int data)
460{
461  if(!pcibInitialized)
462    {
463      return PCIB_ERR_UNINITIALIZED;
464    }
465
466  pcibExchg[0] = pcibEntry;
467  pcibExchg[1] = sig;
468  pcibExchg[2] = off;
469  pcibExchg[3] = data & 0xffff;
470
471  asm("    pusha");
472  asm("    movl pcibExchg, %esi");
473  asm("    movb $0xb1, %ah");
474  asm("    movb $0x0c, %al");
475  asm("    movl pcibExchg+4, %ebx");
476  asm("    movl pcibExchg+8, %edi");
477  asm("    movl pcibExchg+12, %ecx");
478  asm("    pushl %cs");
479  asm("    call *%esi");
480  asm("    movl %eax, pcibExchg");
481  asm("    popa");
482
483  return pcib_convert_err((pcibExchg[0] >> 8) & 0xff);
484}
485 
486
487
488/*
489 * Write dword into config space
490 */
491int
492pcib_conf_write32(int sig, int off, unsigned int data)
493{
494  if(!pcibInitialized)
495    {
496      return PCIB_ERR_UNINITIALIZED;
497    }
498
499  pcibExchg[0] = pcibEntry;
500  pcibExchg[1] = sig;
501  pcibExchg[2] = off;
502  pcibExchg[3] = data;
503
504  asm("    pusha");
505  asm("    movl pcibExchg, %esi");
506  asm("    movb $0xb1, %ah");
507  asm("    movb $0x0d, %al");
508  asm("    movl pcibExchg+4, %ebx");
509  asm("    movl pcibExchg+8, %edi");
510  asm("    movl pcibExchg+12, %ecx");
511  asm("    pushl %cs");
512  asm("    call *%esi");
513  asm("    movl %eax, pcibExchg");
514  asm("    popa");
515
516  return pcib_convert_err((pcibExchg[0] >> 8) & 0xff);
517}
518 
519
520static int
521pcib_convert_err(int err)
522{
523  switch(err & 0xff)
524    {
525    case 0:
526      return PCIB_ERR_SUCCESS;
527    case 0x81:
528      return PCIB_ERR_NOFUNC;
529    case 0x83:
530      return PCIB_ERR_BADVENDOR;
531    case 0x86:
532      return PCIB_ERR_DEVNOTFOUND;
533    case 0x87:
534      return PCIB_ERR_BADREG;
535    default:
536      break;
537    }
538  return PCIB_ERR_NOFUNC;
539}
540       
541     
542
543
544 
545     
546 
547
548
549
Note: See TracBrowser for help on using the repository browser.