source: rtems/c/src/lib/libbsp/i386/shared/pci/pcibios.c @ 8bbf69e

4.115
Last change on this file since 8bbf69e was 8bbf69e, checked in by Joel Sherrill <joel.sherrill@…>, on 05/16/12 at 21:04:10

pci.h cleanup - Consolidate common defines to cpukit pci.h

+ libbsp/sparc/shared/include/pci.h was largely a copy of

an older version of the cpukit pci.h. Removed much of the
contents and included <rtems/pci.h>.

+ sparc/*/pci*.c - Move to <rtems/pci.h> required updating

to use uint32_t for dword accesses.

+ Rename PCI_MULTI_FUNCTION to PCI_HEADER_TYPE_MULTI_FUNCTION
+ Define PCI_HEADER_TYPE_MULTI_FUNCTION in cpukit pci.h and remove

PCI_MULTI_FUNCTION definitions in C files.

+ Move PCI_INVALID_VENDORDEVICEID definitions from various C files

to cpukit pci.h

  • Property mode set to 100644
File size: 13.9 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
8#include <rtems.h>
9#include <bsp.h>
10#include <pcibios.h>
11
12#include <string.h>  /* memcpy */
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
38pci_initialize(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;
48       ucp < (unsigned char *)0xFFFFF;
49       ucp += 0x10) {
50    if (memcmp(ucp, "_32_", 4) != 0) {
51      continue;
52    }
53
54      /* Got signature, check length  */
55    if (*(ucp + 9) != 1) {
56      continue;
57    }
58
59    /* Verify checksum */
60    sum = 0;
61    for (i=0; i<16; i++) {
62      sum += *(ucp+i);
63    }
64
65    if (sum == 0) {
66      /* found */
67      break;
68    }
69  }
70
71  if (ucp >= (unsigned char *)0xFFFFF) {
72    /* BIOS-32 not found */
73    return PCIB_ERR_NOTPRESENT;
74  }
75
76  /* BIOS-32 found, let us find PCI BIOS */
77  ucp += 4;
78
79  pcibExchg[0] = *(unsigned int *)ucp;
80
81  __asm__ ("    pusha");                  /* Push all registers */
82  __asm__ ("    movl pcibExchg, %edi");   /* Move entry point to esi */
83  __asm__ ("    movl $0x49435024, %eax"); /* Move signature to eax */
84  __asm__ ("    xorl %ebx, %ebx");        /* Zero ebx */
85  __asm__ ("    pushl %cs");
86  __asm__ ("    call *%edi");             /* Call entry */
87  __asm__ ("    movl %eax, pcibExchg");
88  __asm__ ("    movl %ebx, pcibExchg+4");
89  __asm__ ("    movl %ecx, pcibExchg+8");
90  __asm__ ("    movl %edx, pcibExchg+12");
91  __asm__ ("    popa");
92
93  if ((pcibExchg[0] & 0xff) != 0) {
94    /* Not found */
95    return PCIB_ERR_NOTPRESENT;
96  }
97
98  /* Found PCI entry point */
99  pcibEntry = pcibExchg[1] + pcibExchg[3];
100
101  /* Let us check whether PCI bios is present */
102  pcibExchg[0] = pcibEntry;
103
104  __asm__ ("    pusha");
105  __asm__ ("    movl pcibExchg, %edi");
106  __asm__ ("    movb $0xb1, %ah");
107  __asm__ ("    movb $0x01, %al");
108  __asm__ ("    pushl %cs");
109  __asm__ ("    call *%edi");
110  __asm__ ("    movl %eax, pcibExchg");
111  __asm__ ("    movl %ebx, pcibExchg+4");
112  __asm__ ("    movl %ecx, pcibExchg+8");
113  __asm__ ("    movl %edx, pcibExchg+12");
114  __asm__ ("    popa");
115
116  if ((pcibExchg[0] & 0xff00) != 0) {
117    /* Not found */
118    return PCIB_ERR_NOTPRESENT;
119  }
120
121  if (pcibExchg[3] != 0x20494350) {
122    /* Signature does not match */
123    return PCIB_ERR_NOTPRESENT;
124  }
125
126  /* Success */
127
128  pcibInitialized = 1;
129  return PCIB_ERR_SUCCESS;
130}
131
132/*
133 * Find specified device and return its signature: combination
134 * of bus number, device number and function number
135 */
136static int
137pcib_find_by_devid(int vendorId, int devId, int idx, int *sig)
138{
139  if (!pcibInitialized) {
140    return PCIB_ERR_UNINITIALIZED;
141  }
142
143  pcibExchg[0] = pcibEntry;
144  pcibExchg[1] = vendorId;
145  pcibExchg[2] = devId;
146  pcibExchg[3] = idx;
147
148  __asm__ ("    pusha");
149  __asm__ ("    movl pcibExchg, %edi");
150  __asm__ ("    movb $0xb1, %ah");
151  __asm__ ("    movb $0x02, %al");
152  __asm__ ("    movl pcibExchg+4, %edx");
153  __asm__ ("    movl pcibExchg+8, %ecx");
154  __asm__ ("    movl pcibExchg+12, %esi");
155  __asm__ ("    pushl %cs");
156  __asm__ ("    call *%edi");
157  __asm__ ("    movl %eax, pcibExchg");
158  __asm__ ("    movl %ebx, pcibExchg+4");
159  __asm__ ("    popa");
160
161  *sig = pcibExchg[1] & 0xffff;
162
163  return pcib_convert_err((pcibExchg[0] >> 8) & 0xff);
164}
165
166int
167pci_find_device(
168  unsigned short vendorid,
169  unsigned short deviceid,
170  int instance,
171  int *pbus,
172  int *pdev,
173  int *pfun
174)
175{
176  int status;
177  int sig = 0;
178
179  status = pcib_find_by_devid( vendorid, deviceid, instance, &sig );
180
181  *pbus = PCIB_DEVSIG_BUS(sig);
182  *pdev = PCIB_DEVSIG_DEV(sig);
183  *pfun = PCIB_DEVSIG_FUNC(sig);
184  return status ? -1 : 0;
185}
186
187/*
188 * Find specified class code return device signature: combination
189 * of bus number, device number and function number
190 */
191int
192pcib_find_by_class(int classCode, int idx, int *sig)
193{
194  if (!pcibInitialized) {
195    return PCIB_ERR_UNINITIALIZED;
196  }
197
198  pcibExchg[0] = pcibEntry;
199  pcibExchg[1] = classCode;
200  pcibExchg[2] = idx;
201
202  __asm__ ("    pusha");
203  __asm__ ("    movl pcibExchg, %edi");
204  __asm__ ("    movb $0xb1, %ah");
205  __asm__ ("    movb $0x03, %al");
206  __asm__ ("    movl pcibExchg+4, %ecx");
207  __asm__ ("    movl pcibExchg+8, %esi");
208  __asm__ ("    pushl %cs");
209  __asm__ ("    call *%edi");
210  __asm__ ("    movl %eax, pcibExchg");
211  __asm__ ("    movl %ebx, pcibExchg+4");
212  __asm__ ("    popa");
213
214  if ((pcibExchg[0] & 0xff00) != 0) {
215    return pcib_convert_err((pcibExchg[0] >> 8) & 0xff);
216  }
217
218  *sig = pcibExchg[1] & 0xffff;
219
220  return PCIB_ERR_SUCCESS;
221}
222
223static uint8_t ucBusCount = 0xff;
224
225unsigned char
226pci_bus_count(void)
227{
228  if ( ucBusCount == 0xff ) {
229    unsigned char bus;
230    unsigned char dev;
231    unsigned char hd = 0;
232    uint32_t d = 0;
233    int sig;
234
235    ucBusCount = 0;
236
237    for (bus=0; bus< 0xff; bus++) {
238      for (dev=0; dev<PCI_MAX_DEVICES; dev++) {
239        sig = PCIB_DEVSIG_MAKE(bus,dev,0);
240        pcib_conf_read32(sig, PCI_VENDOR_ID, &d);
241
242        if ( d != -1 ) {
243           pcib_conf_read32(sig, PCI_CLASS_REVISION, &d);
244
245           if ( (d >> 16) == PCI_CLASS_BRIDGE_PCI ) {
246             pcib_conf_read8(sig, PCI_SUBORDINATE_BUS, &hd);
247
248             if ( hd > ucBusCount )
249               ucBusCount = hd;
250           }
251        }
252      }
253    }
254
255    if ( ucBusCount == 0 ) {
256      printk("pci_bus_count() found 0 busses, assuming 1\n");
257      ucBusCount = 1;
258    } else if ( ucBusCount == 0xff ) {
259      printk("pci_bus_count() found 0xff busses, assuming 1\n");
260      ucBusCount = 1;
261    }
262  }
263
264  return ucBusCount;
265}
266
267
268int
269BSP_pciFindDevice( unsigned short vendorid, unsigned short deviceid,
270                   int instance, int *pbus, int *pdev, int *pfun )
271{
272   int sig, rval;
273
274   rval = pcib_find_by_devid(vendorid, deviceid, instance, &sig);
275
276   if ( PCIB_ERR_SUCCESS == rval ) {
277                *pbus = PCIB_DEVSIG_BUS(sig);
278                *pdev = PCIB_DEVSIG_DEV(sig);
279                *pfun = PCIB_DEVSIG_FUNC(sig);
280   }
281
282   return rval;
283}
284
285/*
286 * Generate Special Cycle
287 */
288int
289pcib_special_cycle(int busNo, int data)
290{
291  if (!pcibInitialized) {
292    return PCIB_ERR_UNINITIALIZED;
293  }
294
295  pcibExchg[0] = pcibEntry;
296  pcibExchg[1] = busNo << 8;
297  pcibExchg[2] = data;
298
299  __asm__ ("    pusha");
300  __asm__ ("    movl pcibExchg, %edi");
301  __asm__ ("    movb $0xb1, %ah");
302  __asm__ ("    movb $0x06, %al");
303  __asm__ ("    movl pcibExchg+4, %ebx");
304  __asm__ ("    movl pcibExchg+8, %edx");
305  __asm__ ("    pushl %cs");
306  __asm__ ("    call *%edi");
307  __asm__ ("    movl %eax, pcibExchg");
308  __asm__ ("    movl %ebx, pcibExchg+4");
309  __asm__ ("    popa");
310
311  return pcib_convert_err((pcibExchg[0] >> 8) & 0xff);
312}
313
314
315/*
316 * Read byte from config space
317 */
318int
319pcib_conf_read8(int sig, int off, uint8_t *data)
320{
321  if (!pcibInitialized) {
322    return PCIB_ERR_UNINITIALIZED;
323  }
324
325  pcibExchg[0] = pcibEntry;
326  pcibExchg[1] = sig;
327  pcibExchg[2] = off;
328
329  __asm__ ("    pusha");
330  __asm__ ("    movl pcibExchg, %esi");
331  __asm__ ("    movb $0xb1, %ah");
332  __asm__ ("    movb $0x08, %al");
333  __asm__ ("    movl pcibExchg+4, %ebx");
334  __asm__ ("    movl pcibExchg+8, %edi");
335  __asm__ ("    pushl %cs");
336  __asm__ ("    call *%esi");
337  __asm__ ("    movl %eax, pcibExchg");
338  __asm__ ("    movl %ecx, pcibExchg+4");
339  __asm__ ("    popa");
340
341  if ((pcibExchg[0] & 0xff00) != 0) {
342    return pcib_convert_err((pcibExchg[0] >> 8) & 0xff);
343  }
344
345  *data = (unsigned char)pcibExchg[1] & 0xff;
346
347  return PCIB_ERR_SUCCESS;
348}
349
350
351/*
352 * Read word from config space
353 */
354int
355pcib_conf_read16(int sig, int off, uint16_t *data)
356{
357  if (!pcibInitialized) {
358    return PCIB_ERR_UNINITIALIZED;
359  }
360
361  pcibExchg[0] = pcibEntry;
362  pcibExchg[1] = sig;
363  pcibExchg[2] = off;
364
365  __asm__ ("    pusha");
366  __asm__ ("    movl pcibExchg, %esi");
367  __asm__ ("    movb $0xb1, %ah");
368  __asm__ ("    movb $0x09, %al");
369  __asm__ ("    movl pcibExchg+4, %ebx");
370  __asm__ ("    movl pcibExchg+8, %edi");
371  __asm__ ("    pushl %cs");
372  __asm__ ("    call *%esi");
373  __asm__ ("    movl %eax, pcibExchg");
374  __asm__ ("    movl %ecx, pcibExchg+4");
375  __asm__ ("    popa");
376
377  if ((pcibExchg[0] & 0xff00) != 0) {
378    return pcib_convert_err((pcibExchg[0] >> 8) & 0xff);
379  }
380
381  *data = (unsigned short)pcibExchg[1] & 0xffff;
382
383  return PCIB_ERR_SUCCESS;
384}
385
386
387/*
388 * Read dword from config space
389 */
390int
391pcib_conf_read32(int sig, int off, uint32_t *data)
392{
393  if (!pcibInitialized) {
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    return pcib_convert_err((pcibExchg[0] >> 8) & 0xff);
415  }
416
417  *data = (unsigned int)pcibExchg[1];
418
419  return PCIB_ERR_SUCCESS;
420}
421
422
423/*
424 * Write byte into  config space
425 */
426int
427pcib_conf_write8(int sig, int off, uint8_t data)
428{
429  if (!pcibInitialized) {
430    return PCIB_ERR_UNINITIALIZED;
431  }
432
433  pcibExchg[0] = pcibEntry;
434  pcibExchg[1] = sig;
435  pcibExchg[2] = off;
436  pcibExchg[3] = data & 0xff;
437
438  __asm__ ("    pusha");
439  __asm__ ("    movl pcibExchg, %esi");
440  __asm__ ("    movb $0xb1, %ah");
441  __asm__ ("    movb $0x0b, %al");
442  __asm__ ("    movl pcibExchg+4, %ebx");
443  __asm__ ("    movl pcibExchg+8, %edi");
444  __asm__ ("    movl pcibExchg+12, %ecx");
445  __asm__ ("    pushl %cs");
446  __asm__ ("    call *%esi");
447  __asm__ ("    movl %eax, pcibExchg");
448  __asm__ ("    popa");
449
450  return pcib_convert_err((pcibExchg[0] >> 8) & 0xff);
451}
452
453/*
454 * Write word into config space
455 */
456int
457pcib_conf_write16(int sig, int off, uint16_t data)
458{
459  if (!pcibInitialized) {
460    return PCIB_ERR_UNINITIALIZED;
461  }
462
463  pcibExchg[0] = pcibEntry;
464  pcibExchg[1] = sig;
465  pcibExchg[2] = off;
466  pcibExchg[3] = data & 0xffff;
467
468  __asm__ ("    pusha");
469  __asm__ ("    movl pcibExchg, %esi");
470  __asm__ ("    movb $0xb1, %ah");
471  __asm__ ("    movb $0x0c, %al");
472  __asm__ ("    movl pcibExchg+4, %ebx");
473  __asm__ ("    movl pcibExchg+8, %edi");
474  __asm__ ("    movl pcibExchg+12, %ecx");
475  __asm__ ("    pushl %cs");
476  __asm__ ("    call *%esi");
477  __asm__ ("    movl %eax, pcibExchg");
478  __asm__ ("    popa");
479
480  return pcib_convert_err((pcibExchg[0] >> 8) & 0xff);
481}
482
483
484
485/*
486 * Write dword into config space
487 */
488int
489pcib_conf_write32(int sig, int off, uint32_t data)
490{
491  if (!pcibInitialized){
492      return PCIB_ERR_UNINITIALIZED;
493  }
494
495  pcibExchg[0] = pcibEntry;
496  pcibExchg[1] = sig;
497  pcibExchg[2] = off;
498  pcibExchg[3] = data;
499
500  __asm__ ("    pusha");
501  __asm__ ("    movl pcibExchg, %esi");
502  __asm__ ("    movb $0xb1, %ah");
503  __asm__ ("    movb $0x0d, %al");
504  __asm__ ("    movl pcibExchg+4, %ebx");
505  __asm__ ("    movl pcibExchg+8, %edi");
506  __asm__ ("    movl pcibExchg+12, %ecx");
507  __asm__ ("    pushl %cs");
508  __asm__ ("    call *%esi");
509  __asm__ ("    movl %eax, pcibExchg");
510  __asm__ ("    popa");
511
512  return pcib_convert_err((pcibExchg[0] >> 8) & 0xff);
513}
514
515
516static int
517pcib_convert_err(int err)
518{
519  switch(err & 0xff){
520    case 0:
521      return PCIB_ERR_SUCCESS;
522    case 0x81:
523      return PCIB_ERR_NOFUNC;
524    case 0x83:
525      return PCIB_ERR_BADVENDOR;
526    case 0x86:
527      return PCIB_ERR_DEVNOTFOUND;
528    case 0x87:
529      return PCIB_ERR_BADREG;
530    default:
531      break;
532  }
533  return PCIB_ERR_NOFUNC;
534}
535
536static int
537BSP_pci_read_config_byte(
538  unsigned char bus,
539  unsigned char slot,
540  unsigned char fun,
541  unsigned char offset,
542  unsigned char *val
543)
544{
545  int sig;
546
547  sig = PCIB_DEVSIG_MAKE(bus,slot,fun);
548  pcib_conf_read8(sig, offset, val);
549  return PCIBIOS_SUCCESSFUL;
550}
551
552static int
553BSP_pci_read_config_word(
554  unsigned char bus,
555  unsigned char slot,
556  unsigned char fun,
557  unsigned char offset,
558  unsigned short *val
559)
560{
561  int sig;
562
563  sig = PCIB_DEVSIG_MAKE(bus,slot,fun);
564  pcib_conf_read16(sig, offset, val);
565  return PCIBIOS_SUCCESSFUL;
566}
567
568static int
569BSP_pci_read_config_dword(
570  unsigned char bus,
571  unsigned char slot,
572  unsigned char fun,
573  unsigned char offset,
574  uint32_t     *val
575)
576{
577  int sig;
578
579  sig = PCIB_DEVSIG_MAKE(bus,slot,fun);
580  pcib_conf_read32(sig, offset, val);
581  return PCIBIOS_SUCCESSFUL;
582}
583
584static int
585BSP_pci_write_config_byte(
586  unsigned char bus,
587  unsigned char slot,
588  unsigned char fun,
589  unsigned char offset,
590  unsigned char val
591)
592{
593  int sig;
594
595  sig = PCIB_DEVSIG_MAKE(bus,slot,fun);
596  pcib_conf_write8(sig, offset, val);
597  return PCIBIOS_SUCCESSFUL;
598}
599
600static int
601BSP_pci_write_config_word(
602  unsigned char bus,
603  unsigned char slot,
604  unsigned char fun,
605  unsigned char offset,
606  unsigned short val
607)
608{
609  int sig;
610
611  sig = PCIB_DEVSIG_MAKE(bus,slot,fun);
612  pcib_conf_write16(sig, offset, val);
613  return PCIBIOS_SUCCESSFUL;
614}
615
616static int
617BSP_pci_write_config_dword(
618  unsigned char bus,
619  unsigned char slot,
620  unsigned char fun,
621  unsigned char offset,
622  uint32_t      val
623)
624{
625  int sig;
626
627  sig = PCIB_DEVSIG_MAKE(bus,slot,fun);
628  pcib_conf_write32(sig, offset, val);
629  return PCIBIOS_SUCCESSFUL;
630}
631
632const pci_config_access_functions pci_indirect_functions = {
633  BSP_pci_read_config_byte,
634  BSP_pci_read_config_word,
635  BSP_pci_read_config_dword,
636  BSP_pci_write_config_byte,
637  BSP_pci_write_config_word,
638  BSP_pci_write_config_dword
639};
640
641rtems_pci_config_t BSP_pci_configuration = {
642  (volatile unsigned char*)0,
643  (volatile unsigned char*)0,
644  &pci_indirect_functions
645};
Note: See TracBrowser for help on using the repository browser.