source: rtems/c/src/lib/libbsp/i386/shared/pci/pcibios.c @ 9b4422a2

4.115
Last change on this file since 9b4422a2 was 9b4422a2, checked in by Joel Sherrill <joel.sherrill@…>, on 05/03/12 at 15:09:24

Remove All CVS Id Strings Possible Using a Script

Script does what is expected and tries to do it as
smartly as possible.

+ remove occurrences of two blank comment lines

next to each other after Id string line removed.

+ remove entire comment blocks which only exited to

contain CVS Ids

+ If the processing left a blank line at the top of

a file, it was removed.

  • 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
223#define PCI_MULTI_FUNCTION      0x80
224
225static uint8_t ucBusCount = 0xff;
226
227unsigned char
228pci_bus_count(void)
229{
230  if ( ucBusCount == 0xff ) {
231    unsigned char bus;
232    unsigned char dev;
233    unsigned char hd = 0;
234    uint32_t d = 0;
235    int sig;
236
237    ucBusCount = 0;
238
239    for (bus=0; bus< 0xff; bus++) {
240      for (dev=0; dev<PCI_MAX_DEVICES; dev++) {
241        sig = PCIB_DEVSIG_MAKE(bus,dev,0);
242        pcib_conf_read32(sig, PCI_VENDOR_ID, &d);
243
244        if ( d != -1 ) {
245           pcib_conf_read32(sig, PCI_CLASS_REVISION, &d);
246
247           if ( (d >> 16) == PCI_CLASS_BRIDGE_PCI ) {
248             pcib_conf_read8(sig, PCI_SUBORDINATE_BUS, &hd);
249
250             if ( hd > ucBusCount )
251               ucBusCount = hd;
252           }
253        }
254      }
255    }
256
257    if ( ucBusCount == 0 ) {
258      printk("pci_bus_count() found 0 busses, assuming 1\n");
259      ucBusCount = 1;
260    } else if ( ucBusCount == 0xff ) {
261      printk("pci_bus_count() found 0xff busses, assuming 1\n");
262      ucBusCount = 1;
263    }
264  }
265
266  return ucBusCount;
267}
268
269
270int
271BSP_pciFindDevice( unsigned short vendorid, unsigned short deviceid,
272                   int instance, int *pbus, int *pdev, int *pfun )
273{
274   int sig, rval;
275
276   rval = pcib_find_by_devid(vendorid, deviceid, instance, &sig);
277
278   if ( PCIB_ERR_SUCCESS == rval ) {
279                *pbus = PCIB_DEVSIG_BUS(sig);
280                *pdev = PCIB_DEVSIG_DEV(sig);
281                *pfun = PCIB_DEVSIG_FUNC(sig);
282   }
283
284   return rval;
285}
286
287/*
288 * Generate Special Cycle
289 */
290int
291pcib_special_cycle(int busNo, int data)
292{
293  if (!pcibInitialized) {
294    return PCIB_ERR_UNINITIALIZED;
295  }
296
297  pcibExchg[0] = pcibEntry;
298  pcibExchg[1] = busNo << 8;
299  pcibExchg[2] = data;
300
301  __asm__ ("    pusha");
302  __asm__ ("    movl pcibExchg, %edi");
303  __asm__ ("    movb $0xb1, %ah");
304  __asm__ ("    movb $0x06, %al");
305  __asm__ ("    movl pcibExchg+4, %ebx");
306  __asm__ ("    movl pcibExchg+8, %edx");
307  __asm__ ("    pushl %cs");
308  __asm__ ("    call *%edi");
309  __asm__ ("    movl %eax, pcibExchg");
310  __asm__ ("    movl %ebx, pcibExchg+4");
311  __asm__ ("    popa");
312
313  return pcib_convert_err((pcibExchg[0] >> 8) & 0xff);
314}
315
316
317/*
318 * Read byte from config space
319 */
320int
321pcib_conf_read8(int sig, int off, uint8_t *data)
322{
323  if (!pcibInitialized) {
324    return PCIB_ERR_UNINITIALIZED;
325  }
326
327  pcibExchg[0] = pcibEntry;
328  pcibExchg[1] = sig;
329  pcibExchg[2] = off;
330
331  __asm__ ("    pusha");
332  __asm__ ("    movl pcibExchg, %esi");
333  __asm__ ("    movb $0xb1, %ah");
334  __asm__ ("    movb $0x08, %al");
335  __asm__ ("    movl pcibExchg+4, %ebx");
336  __asm__ ("    movl pcibExchg+8, %edi");
337  __asm__ ("    pushl %cs");
338  __asm__ ("    call *%esi");
339  __asm__ ("    movl %eax, pcibExchg");
340  __asm__ ("    movl %ecx, pcibExchg+4");
341  __asm__ ("    popa");
342
343  if ((pcibExchg[0] & 0xff00) != 0) {
344    return pcib_convert_err((pcibExchg[0] >> 8) & 0xff);
345  }
346
347  *data = (unsigned char)pcibExchg[1] & 0xff;
348
349  return PCIB_ERR_SUCCESS;
350}
351
352
353/*
354 * Read word from config space
355 */
356int
357pcib_conf_read16(int sig, int off, uint16_t *data)
358{
359  if (!pcibInitialized) {
360    return PCIB_ERR_UNINITIALIZED;
361  }
362
363  pcibExchg[0] = pcibEntry;
364  pcibExchg[1] = sig;
365  pcibExchg[2] = off;
366
367  __asm__ ("    pusha");
368  __asm__ ("    movl pcibExchg, %esi");
369  __asm__ ("    movb $0xb1, %ah");
370  __asm__ ("    movb $0x09, %al");
371  __asm__ ("    movl pcibExchg+4, %ebx");
372  __asm__ ("    movl pcibExchg+8, %edi");
373  __asm__ ("    pushl %cs");
374  __asm__ ("    call *%esi");
375  __asm__ ("    movl %eax, pcibExchg");
376  __asm__ ("    movl %ecx, pcibExchg+4");
377  __asm__ ("    popa");
378
379  if ((pcibExchg[0] & 0xff00) != 0) {
380    return pcib_convert_err((pcibExchg[0] >> 8) & 0xff);
381  }
382
383  *data = (unsigned short)pcibExchg[1] & 0xffff;
384
385  return PCIB_ERR_SUCCESS;
386}
387
388
389/*
390 * Read dword from config space
391 */
392int
393pcib_conf_read32(int sig, int off, uint32_t *data)
394{
395  if (!pcibInitialized) {
396    return PCIB_ERR_UNINITIALIZED;
397  }
398
399  pcibExchg[0] = pcibEntry;
400  pcibExchg[1] = sig;
401  pcibExchg[2] = off;
402
403  __asm__ ("    pusha");
404  __asm__ ("    movl pcibExchg, %esi");
405  __asm__ ("    movb $0xb1, %ah");
406  __asm__ ("    movb $0x0a, %al");
407  __asm__ ("    movl pcibExchg+4, %ebx");
408  __asm__ ("    movl pcibExchg+8, %edi");
409  __asm__ ("    pushl %cs");
410  __asm__ ("    call *%esi");
411  __asm__ ("    movl %eax, pcibExchg");
412  __asm__ ("    movl %ecx, pcibExchg+4");
413  __asm__ ("    popa");
414
415  if ((pcibExchg[0] & 0xff00) != 0) {
416    return pcib_convert_err((pcibExchg[0] >> 8) & 0xff);
417  }
418
419  *data = (unsigned int)pcibExchg[1];
420
421  return PCIB_ERR_SUCCESS;
422}
423
424
425/*
426 * Write byte into  config space
427 */
428int
429pcib_conf_write8(int sig, int off, uint8_t data)
430{
431  if (!pcibInitialized) {
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, uint16_t data)
460{
461  if (!pcibInitialized) {
462    return PCIB_ERR_UNINITIALIZED;
463  }
464
465  pcibExchg[0] = pcibEntry;
466  pcibExchg[1] = sig;
467  pcibExchg[2] = off;
468  pcibExchg[3] = data & 0xffff;
469
470  __asm__ ("    pusha");
471  __asm__ ("    movl pcibExchg, %esi");
472  __asm__ ("    movb $0xb1, %ah");
473  __asm__ ("    movb $0x0c, %al");
474  __asm__ ("    movl pcibExchg+4, %ebx");
475  __asm__ ("    movl pcibExchg+8, %edi");
476  __asm__ ("    movl pcibExchg+12, %ecx");
477  __asm__ ("    pushl %cs");
478  __asm__ ("    call *%esi");
479  __asm__ ("    movl %eax, pcibExchg");
480  __asm__ ("    popa");
481
482  return pcib_convert_err((pcibExchg[0] >> 8) & 0xff);
483}
484
485
486
487/*
488 * Write dword into config space
489 */
490int
491pcib_conf_write32(int sig, int off, uint32_t data)
492{
493  if (!pcibInitialized){
494      return PCIB_ERR_UNINITIALIZED;
495  }
496
497  pcibExchg[0] = pcibEntry;
498  pcibExchg[1] = sig;
499  pcibExchg[2] = off;
500  pcibExchg[3] = data;
501
502  __asm__ ("    pusha");
503  __asm__ ("    movl pcibExchg, %esi");
504  __asm__ ("    movb $0xb1, %ah");
505  __asm__ ("    movb $0x0d, %al");
506  __asm__ ("    movl pcibExchg+4, %ebx");
507  __asm__ ("    movl pcibExchg+8, %edi");
508  __asm__ ("    movl pcibExchg+12, %ecx");
509  __asm__ ("    pushl %cs");
510  __asm__ ("    call *%esi");
511  __asm__ ("    movl %eax, pcibExchg");
512  __asm__ ("    popa");
513
514  return pcib_convert_err((pcibExchg[0] >> 8) & 0xff);
515}
516
517
518static int
519pcib_convert_err(int err)
520{
521  switch(err & 0xff){
522    case 0:
523      return PCIB_ERR_SUCCESS;
524    case 0x81:
525      return PCIB_ERR_NOFUNC;
526    case 0x83:
527      return PCIB_ERR_BADVENDOR;
528    case 0x86:
529      return PCIB_ERR_DEVNOTFOUND;
530    case 0x87:
531      return PCIB_ERR_BADREG;
532    default:
533      break;
534  }
535  return PCIB_ERR_NOFUNC;
536}
537
538static int
539BSP_pci_read_config_byte(
540  unsigned char bus,
541  unsigned char slot,
542  unsigned char fun,
543  unsigned char offset,
544  unsigned char *val
545)
546{
547  int sig;
548
549  sig = PCIB_DEVSIG_MAKE(bus,slot,fun);
550  pcib_conf_read8(sig, offset, val);
551  return PCIBIOS_SUCCESSFUL;
552}
553
554static int
555BSP_pci_read_config_word(
556  unsigned char bus,
557  unsigned char slot,
558  unsigned char fun,
559  unsigned char offset,
560  unsigned short *val
561)
562{
563  int sig;
564
565  sig = PCIB_DEVSIG_MAKE(bus,slot,fun);
566  pcib_conf_read16(sig, offset, val);
567  return PCIBIOS_SUCCESSFUL;
568}
569
570static int
571BSP_pci_read_config_dword(
572  unsigned char bus,
573  unsigned char slot,
574  unsigned char fun,
575  unsigned char offset,
576  uint32_t     *val
577)
578{
579  int sig;
580
581  sig = PCIB_DEVSIG_MAKE(bus,slot,fun);
582  pcib_conf_read32(sig, offset, val);
583  return PCIBIOS_SUCCESSFUL;
584}
585
586static int
587BSP_pci_write_config_byte(
588  unsigned char bus,
589  unsigned char slot,
590  unsigned char fun,
591  unsigned char offset,
592  unsigned char val
593)
594{
595  int sig;
596
597  sig = PCIB_DEVSIG_MAKE(bus,slot,fun);
598  pcib_conf_write8(sig, offset, val);
599  return PCIBIOS_SUCCESSFUL;
600}
601
602static int
603BSP_pci_write_config_word(
604  unsigned char bus,
605  unsigned char slot,
606  unsigned char fun,
607  unsigned char offset,
608  unsigned short val
609)
610{
611  int sig;
612
613  sig = PCIB_DEVSIG_MAKE(bus,slot,fun);
614  pcib_conf_write16(sig, offset, val);
615  return PCIBIOS_SUCCESSFUL;
616}
617
618static int
619BSP_pci_write_config_dword(
620  unsigned char bus,
621  unsigned char slot,
622  unsigned char fun,
623  unsigned char offset,
624  uint32_t      val
625)
626{
627  int sig;
628
629  sig = PCIB_DEVSIG_MAKE(bus,slot,fun);
630  pcib_conf_write32(sig, offset, val);
631  return PCIBIOS_SUCCESSFUL;
632}
633
634const pci_config_access_functions pci_indirect_functions = {
635  BSP_pci_read_config_byte,
636  BSP_pci_read_config_word,
637  BSP_pci_read_config_dword,
638  BSP_pci_write_config_byte,
639  BSP_pci_write_config_word,
640  BSP_pci_write_config_dword
641};
642
643rtems_pci_config_t BSP_pci_configuration = {
644  (volatile unsigned char*)0,
645  (volatile unsigned char*)0,
646  &pci_indirect_functions
647};
Note: See TracBrowser for help on using the repository browser.