source: rtems/c/src/lib/libbsp/i386/shared/pci/pcibios.c @ 1ecb21d8

4.115
Last change on this file since 1ecb21d8 was 1ecb21d8, checked in by Joel Sherrill <joel.sherrill@…>, on 10/14/14 at 00:08:14

libbsp/i386/shared: Fix warnings

  • Property mode set to 100644
File size: 13.5 KB
RevLine 
[0ebbf66]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
[6266abe]12#include <string.h>  /* memcpy */
[6ce94bc3]13
[0ebbf66]14/*
15 * This is simpliest possible PCI BIOS, it assumes that addressing
[6266abe]16 * is flat and that stack is big enough
17 */
[d7034e1]18
[0ebbf66]19
20static int pcibInitialized = 0;
21static unsigned int pcibEntry;
22
23/*
[00882105]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
[6266abe]26 * of gcc. This code is not on performance path, so we can care
27 * relatively little about performance here
[0ebbf66]28 */
29static volatile unsigned int pcibExchg[5];
30
31static int pcib_convert_err(int err);
32
33/*
[6266abe]34 * Detects presense of PCI BIOS, returns
[0ebbf66]35 * error code
36 */
[6266abe]37int
[bdc2572]38pci_initialize(void)
[0ebbf66]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 */
[6266abe]47  for (ucp = (unsigned char *)0xE0000;
48       ucp < (unsigned char *)0xFFFFF;
49       ucp += 0x10) {
50    if (memcmp(ucp, "_32_", 4) != 0) {
51      continue;
52    }
[0ebbf66]53
54      /* Got signature, check length  */
[6266abe]55    if (*(ucp + 9) != 1) {
56      continue;
[0ebbf66]57    }
58
[6266abe]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;
[0ebbf66]68    }
[6266abe]69  }
70
71  if (ucp >= (unsigned char *)0xFFFFF) {
72    /* BIOS-32 not found */
73    return PCIB_ERR_NOTPRESENT;
74  }
[0ebbf66]75
76  /* BIOS-32 found, let us find PCI BIOS */
77  ucp += 4;
78
79  pcibExchg[0] = *(unsigned int *)ucp;
80
[00882105]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");
[0ebbf66]92
[6266abe]93  if ((pcibExchg[0] & 0xff) != 0) {
94    /* Not found */
95    return PCIB_ERR_NOTPRESENT;
96  }
[0ebbf66]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;
[6266abe]103
[00882105]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");
[0ebbf66]115
[6266abe]116  if ((pcibExchg[0] & 0xff00) != 0) {
117    /* Not found */
118    return PCIB_ERR_NOTPRESENT;
119  }
[0ebbf66]120
[6266abe]121  if (pcibExchg[3] != 0x20494350) {
122    /* Signature does not match */
123    return PCIB_ERR_NOTPRESENT;
124  }
[0ebbf66]125
126  /* Success */
[6266abe]127
[0ebbf66]128  pcibInitialized = 1;
129  return PCIB_ERR_SUCCESS;
130}
131
[6266abe]132/*
133 * Find specified device and return its signature: combination
[0ebbf66]134 * of bus number, device number and function number
135 */
[32f2304a]136static int
[0ebbf66]137pcib_find_by_devid(int vendorId, int devId, int idx, int *sig)
138{
[6266abe]139  if (!pcibInitialized) {
140    return PCIB_ERR_UNINITIALIZED;
141  }
[0ebbf66]142
143  pcibExchg[0] = pcibEntry;
144  pcibExchg[1] = vendorId;
145  pcibExchg[2] = devId;
146  pcibExchg[3] = idx;
147
[00882105]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");
[0ebbf66]160
161  *sig = pcibExchg[1] & 0xffff;
162
163  return pcib_convert_err((pcibExchg[0] >> 8) & 0xff);
164}
165
[c2701a0]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;
[a6e2293]177  int sig = 0;
[c2701a0]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);
[b365d4d]184  return status ? -1 : 0;
[c2701a0]185}
186
[6266abe]187/*
188 * Find specified class code return device signature: combination
[0ebbf66]189 * of bus number, device number and function number
190 */
191int
192pcib_find_by_class(int classCode, int idx, int *sig)
193{
[6266abe]194  if (!pcibInitialized) {
195    return PCIB_ERR_UNINITIALIZED;
196  }
[0ebbf66]197
198  pcibExchg[0] = pcibEntry;
199  pcibExchg[1] = classCode;
200  pcibExchg[2] = idx;
201
[00882105]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");
[0ebbf66]213
[6266abe]214  if ((pcibExchg[0] & 0xff00) != 0) {
215    return pcib_convert_err((pcibExchg[0] >> 8) & 0xff);
216  }
[0ebbf66]217
218  *sig = pcibExchg[1] & 0xffff;
219
220  return PCIB_ERR_SUCCESS;
221}
[6266abe]222
[718c36d]223static uint8_t ucBusCount = 0xff;
[d7034e1]224
[bdc2572]225unsigned char
[f9abe50]226pci_bus_count(void)
[d7034e1]227{
[6266abe]228  if ( ucBusCount == 0xff ) {
229    unsigned char bus;
230    unsigned char dev;
231    unsigned char hd = 0;
[8149a2de]232    uint32_t d = 0;
[6266abe]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        }
[d7034e1]252      }
[6266abe]253    }
[d7034e1]254
[6266abe]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  }
[d7034e1]263
[6266abe]264  return ucBusCount;
[d7034e1]265}
266
[6266abe]267/*
[0ebbf66]268 * Generate Special Cycle
269 */
270int
271pcib_special_cycle(int busNo, int data)
272{
[6266abe]273  if (!pcibInitialized) {
274    return PCIB_ERR_UNINITIALIZED;
275  }
[0ebbf66]276
277  pcibExchg[0] = pcibEntry;
278  pcibExchg[1] = busNo << 8;
279  pcibExchg[2] = data;
280
[00882105]281  __asm__ ("    pusha");
282  __asm__ ("    movl pcibExchg, %edi");
283  __asm__ ("    movb $0xb1, %ah");
284  __asm__ ("    movb $0x06, %al");
285  __asm__ ("    movl pcibExchg+4, %ebx");
286  __asm__ ("    movl pcibExchg+8, %edx");
287  __asm__ ("    pushl %cs");
288  __asm__ ("    call *%edi");
289  __asm__ ("    movl %eax, pcibExchg");
290  __asm__ ("    movl %ebx, pcibExchg+4");
291  __asm__ ("    popa");
[0ebbf66]292
293  return pcib_convert_err((pcibExchg[0] >> 8) & 0xff);
294}
295
[6266abe]296
297/*
[0ebbf66]298 * Read byte from config space
299 */
300int
[8149a2de]301pcib_conf_read8(int sig, int off, uint8_t *data)
[0ebbf66]302{
[6266abe]303  if (!pcibInitialized) {
304    return PCIB_ERR_UNINITIALIZED;
305  }
[0ebbf66]306
307  pcibExchg[0] = pcibEntry;
308  pcibExchg[1] = sig;
309  pcibExchg[2] = off;
310
[00882105]311  __asm__ ("    pusha");
312  __asm__ ("    movl pcibExchg, %esi");
313  __asm__ ("    movb $0xb1, %ah");
314  __asm__ ("    movb $0x08, %al");
315  __asm__ ("    movl pcibExchg+4, %ebx");
316  __asm__ ("    movl pcibExchg+8, %edi");
317  __asm__ ("    pushl %cs");
318  __asm__ ("    call *%esi");
319  __asm__ ("    movl %eax, pcibExchg");
320  __asm__ ("    movl %ecx, pcibExchg+4");
321  __asm__ ("    popa");
[0ebbf66]322
[6266abe]323  if ((pcibExchg[0] & 0xff00) != 0) {
324    return pcib_convert_err((pcibExchg[0] >> 8) & 0xff);
325  }
[0ebbf66]326
327  *data = (unsigned char)pcibExchg[1] & 0xff;
328
329  return PCIB_ERR_SUCCESS;
330}
331
[6266abe]332
333/*
[0ebbf66]334 * Read word from config space
335 */
336int
[8149a2de]337pcib_conf_read16(int sig, int off, uint16_t *data)
[0ebbf66]338{
[6266abe]339  if (!pcibInitialized) {
340    return PCIB_ERR_UNINITIALIZED;
341  }
[0ebbf66]342
343  pcibExchg[0] = pcibEntry;
344  pcibExchg[1] = sig;
345  pcibExchg[2] = off;
346
[00882105]347  __asm__ ("    pusha");
348  __asm__ ("    movl pcibExchg, %esi");
349  __asm__ ("    movb $0xb1, %ah");
350  __asm__ ("    movb $0x09, %al");
351  __asm__ ("    movl pcibExchg+4, %ebx");
352  __asm__ ("    movl pcibExchg+8, %edi");
353  __asm__ ("    pushl %cs");
354  __asm__ ("    call *%esi");
355  __asm__ ("    movl %eax, pcibExchg");
356  __asm__ ("    movl %ecx, pcibExchg+4");
357  __asm__ ("    popa");
[0ebbf66]358
[6266abe]359  if ((pcibExchg[0] & 0xff00) != 0) {
360    return pcib_convert_err((pcibExchg[0] >> 8) & 0xff);
361  }
[0ebbf66]362
363  *data = (unsigned short)pcibExchg[1] & 0xffff;
364
365  return PCIB_ERR_SUCCESS;
366}
367
[6266abe]368
369/*
[0ebbf66]370 * Read dword from config space
371 */
372int
[8149a2de]373pcib_conf_read32(int sig, int off, uint32_t *data)
[0ebbf66]374{
[6266abe]375  if (!pcibInitialized) {
376    return PCIB_ERR_UNINITIALIZED;
377  }
[0ebbf66]378
379  pcibExchg[0] = pcibEntry;
380  pcibExchg[1] = sig;
381  pcibExchg[2] = off;
382
[00882105]383  __asm__ ("    pusha");
384  __asm__ ("    movl pcibExchg, %esi");
385  __asm__ ("    movb $0xb1, %ah");
386  __asm__ ("    movb $0x0a, %al");
387  __asm__ ("    movl pcibExchg+4, %ebx");
388  __asm__ ("    movl pcibExchg+8, %edi");
389  __asm__ ("    pushl %cs");
390  __asm__ ("    call *%esi");
391  __asm__ ("    movl %eax, pcibExchg");
392  __asm__ ("    movl %ecx, pcibExchg+4");
393  __asm__ ("    popa");
[0ebbf66]394
[6266abe]395  if ((pcibExchg[0] & 0xff00) != 0) {
396    return pcib_convert_err((pcibExchg[0] >> 8) & 0xff);
397  }
[0ebbf66]398
399  *data = (unsigned int)pcibExchg[1];
400
401  return PCIB_ERR_SUCCESS;
402}
403
[6266abe]404
405/*
[0ebbf66]406 * Write byte into  config space
407 */
408int
[8149a2de]409pcib_conf_write8(int sig, int off, uint8_t data)
[0ebbf66]410{
[6266abe]411  if (!pcibInitialized) {
412    return PCIB_ERR_UNINITIALIZED;
413  }
[0ebbf66]414
415  pcibExchg[0] = pcibEntry;
416  pcibExchg[1] = sig;
417  pcibExchg[2] = off;
418  pcibExchg[3] = data & 0xff;
419
[00882105]420  __asm__ ("    pusha");
421  __asm__ ("    movl pcibExchg, %esi");
422  __asm__ ("    movb $0xb1, %ah");
423  __asm__ ("    movb $0x0b, %al");
424  __asm__ ("    movl pcibExchg+4, %ebx");
425  __asm__ ("    movl pcibExchg+8, %edi");
426  __asm__ ("    movl pcibExchg+12, %ecx");
427  __asm__ ("    pushl %cs");
428  __asm__ ("    call *%esi");
429  __asm__ ("    movl %eax, pcibExchg");
430  __asm__ ("    popa");
[0ebbf66]431
432  return pcib_convert_err((pcibExchg[0] >> 8) & 0xff);
433}
434
[6266abe]435/*
[0ebbf66]436 * Write word into config space
437 */
438int
[8149a2de]439pcib_conf_write16(int sig, int off, uint16_t data)
[0ebbf66]440{
[6266abe]441  if (!pcibInitialized) {
442    return PCIB_ERR_UNINITIALIZED;
443  }
[0ebbf66]444
445  pcibExchg[0] = pcibEntry;
446  pcibExchg[1] = sig;
447  pcibExchg[2] = off;
448  pcibExchg[3] = data & 0xffff;
449
[00882105]450  __asm__ ("    pusha");
451  __asm__ ("    movl pcibExchg, %esi");
452  __asm__ ("    movb $0xb1, %ah");
453  __asm__ ("    movb $0x0c, %al");
454  __asm__ ("    movl pcibExchg+4, %ebx");
455  __asm__ ("    movl pcibExchg+8, %edi");
456  __asm__ ("    movl pcibExchg+12, %ecx");
457  __asm__ ("    pushl %cs");
458  __asm__ ("    call *%esi");
459  __asm__ ("    movl %eax, pcibExchg");
460  __asm__ ("    popa");
[0ebbf66]461
462  return pcib_convert_err((pcibExchg[0] >> 8) & 0xff);
463}
464
[d7034e1]465
[6266abe]466
467/*
[0ebbf66]468 * Write dword into config space
469 */
470int
[8149a2de]471pcib_conf_write32(int sig, int off, uint32_t data)
[0ebbf66]472{
[6266abe]473  if (!pcibInitialized){
[0ebbf66]474      return PCIB_ERR_UNINITIALIZED;
[6266abe]475  }
[0ebbf66]476
477  pcibExchg[0] = pcibEntry;
478  pcibExchg[1] = sig;
479  pcibExchg[2] = off;
480  pcibExchg[3] = data;
481
[00882105]482  __asm__ ("    pusha");
483  __asm__ ("    movl pcibExchg, %esi");
484  __asm__ ("    movb $0xb1, %ah");
485  __asm__ ("    movb $0x0d, %al");
486  __asm__ ("    movl pcibExchg+4, %ebx");
487  __asm__ ("    movl pcibExchg+8, %edi");
488  __asm__ ("    movl pcibExchg+12, %ecx");
489  __asm__ ("    pushl %cs");
490  __asm__ ("    call *%esi");
491  __asm__ ("    movl %eax, pcibExchg");
492  __asm__ ("    popa");
[0ebbf66]493
494  return pcib_convert_err((pcibExchg[0] >> 8) & 0xff);
495}
[6266abe]496
[6128a4a]497
[0ebbf66]498static int
499pcib_convert_err(int err)
500{
[6266abe]501  switch(err & 0xff){
[0ebbf66]502    case 0:
503      return PCIB_ERR_SUCCESS;
504    case 0x81:
505      return PCIB_ERR_NOFUNC;
506    case 0x83:
507      return PCIB_ERR_BADVENDOR;
508    case 0x86:
509      return PCIB_ERR_DEVNOTFOUND;
510    case 0x87:
511      return PCIB_ERR_BADREG;
512    default:
513      break;
[6266abe]514  }
[0ebbf66]515  return PCIB_ERR_NOFUNC;
516}
[d7034e1]517
[6266abe]518static int
[60b728b5]519BSP_pci_read_config_byte(
[6266abe]520  unsigned char bus,
521  unsigned char slot,
522  unsigned char fun,
523  unsigned char offset,
524  unsigned char *val
[3495c57]525)
[6266abe]526{
527  int sig;
[d7034e1]528
[6266abe]529  sig = PCIB_DEVSIG_MAKE(bus,slot,fun);
530  pcib_conf_read8(sig, offset, val);
531  return PCIBIOS_SUCCESSFUL;
532}
[d7034e1]533
[6266abe]534static int
[60b728b5]535BSP_pci_read_config_word(
[6266abe]536  unsigned char bus,
537  unsigned char slot,
538  unsigned char fun,
539  unsigned char offset,
540  unsigned short *val
[3495c57]541)
[6266abe]542{
543  int sig;
[d7034e1]544
[6266abe]545  sig = PCIB_DEVSIG_MAKE(bus,slot,fun);
546  pcib_conf_read16(sig, offset, val);
547  return PCIBIOS_SUCCESSFUL;
548}
549
550static int
[60b728b5]551BSP_pci_read_config_dword(
[6266abe]552  unsigned char bus,
553  unsigned char slot,
554  unsigned char fun,
555  unsigned char offset,
[8149a2de]556  uint32_t     *val
[3495c57]557)
[6266abe]558{
559  int sig;
560
561  sig = PCIB_DEVSIG_MAKE(bus,slot,fun);
562  pcib_conf_read32(sig, offset, val);
563  return PCIBIOS_SUCCESSFUL;
564}
565
566static int
[60b728b5]567BSP_pci_write_config_byte(
[6266abe]568  unsigned char bus,
569  unsigned char slot,
570  unsigned char fun,
571  unsigned char offset,
572  unsigned char val
[3495c57]573)
[6266abe]574{
575  int sig;
576
577  sig = PCIB_DEVSIG_MAKE(bus,slot,fun);
578  pcib_conf_write8(sig, offset, val);
579  return PCIBIOS_SUCCESSFUL;
580}
581
582static int
[60b728b5]583BSP_pci_write_config_word(
[6266abe]584  unsigned char bus,
585  unsigned char slot,
586  unsigned char fun,
587  unsigned char offset,
588  unsigned short val
[3495c57]589)
[6266abe]590{
591  int sig;
592
593  sig = PCIB_DEVSIG_MAKE(bus,slot,fun);
594  pcib_conf_write16(sig, offset, val);
595  return PCIBIOS_SUCCESSFUL;
596}
597
598static int
[60b728b5]599BSP_pci_write_config_dword(
[6266abe]600  unsigned char bus,
601  unsigned char slot,
602  unsigned char fun,
603  unsigned char offset,
[8149a2de]604  uint32_t      val
[3495c57]605)
[6266abe]606{
607  int sig;
608
609  sig = PCIB_DEVSIG_MAKE(bus,slot,fun);
610  pcib_conf_write32(sig, offset, val);
611  return PCIBIOS_SUCCESSFUL;
612}
[d7034e1]613
[6266abe]614const pci_config_access_functions pci_indirect_functions = {
[60b728b5]615  BSP_pci_read_config_byte,
616  BSP_pci_read_config_word,
617  BSP_pci_read_config_dword,
618  BSP_pci_write_config_byte,
619  BSP_pci_write_config_word,
620  BSP_pci_write_config_dword
[6266abe]621};
622
[32c347d]623rtems_pci_config_t BSP_pci_configuration = {
[6266abe]624  (volatile unsigned char*)0,
625  (volatile unsigned char*)0,
626  &pci_indirect_functions
627};
Note: See TracBrowser for help on using the repository browser.