source: rtems/c/src/lib/libbsp/i386/shared/pci/pcibios.c @ 3b697232

5
Last change on this file since 3b697232 was 3b697232, checked in by Joel Sherrill <joel@…>, on 03/02/16 at 19:31:45

i386/shared/pci/pcibios.c: Remove unused pcib_find_by_class()

  • Property mode set to 100644
File size: 12.7 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>
[12c9dc8f]10#include <rtems/pci.h>
[0ebbf66]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 */
[0ebbf66]18static int pcibInitialized = 0;
19static unsigned int pcibEntry;
20
21/*
[00882105]22 * Array to pass data between c and __asm__ parts, at the time of
23 * writing I am not yet that familiar with extended __asm__ feature
[6266abe]24 * of gcc. This code is not on performance path, so we can care
25 * relatively little about performance here
[0ebbf66]26 */
27static volatile unsigned int pcibExchg[5];
28
29static int pcib_convert_err(int err);
30
[12c9dc8f]31/** @brief
32 * Make device signature from bus number, device numebr and function
33 * number
34 */
35#define PCIB_DEVSIG_MAKE(b,d,f) ((b<<8)|(d<<3)|(f))
36
37/** @brief
38 * Extract valrous part from device signature
39 */
40#define PCIB_DEVSIG_BUS(x) (((x)>>8) &0xff)
41#define PCIB_DEVSIG_DEV(x) (((x)>>3) & 0x1f)
42#define PCIB_DEVSIG_FUNC(x) ((x) & 0x7)
[0ebbf66]43/*
[6266abe]44 * Detects presense of PCI BIOS, returns
[0ebbf66]45 * error code
46 */
[6266abe]47int
[bdc2572]48pci_initialize(void)
[0ebbf66]49{
50  unsigned char *ucp;
51  unsigned char sum;
52  int      i;
53
54  pcibInitialized = 0;
55
56  /* First, we have to look for BIOS-32 */
[6266abe]57  for (ucp = (unsigned char *)0xE0000;
58       ucp < (unsigned char *)0xFFFFF;
59       ucp += 0x10) {
60    if (memcmp(ucp, "_32_", 4) != 0) {
61      continue;
62    }
[0ebbf66]63
64      /* Got signature, check length  */
[6266abe]65    if (*(ucp + 9) != 1) {
66      continue;
[0ebbf66]67    }
68
[6266abe]69    /* Verify checksum */
70    sum = 0;
71    for (i=0; i<16; i++) {
72      sum += *(ucp+i);
73    }
74
75    if (sum == 0) {
76      /* found */
77      break;
[0ebbf66]78    }
[6266abe]79  }
80
81  if (ucp >= (unsigned char *)0xFFFFF) {
82    /* BIOS-32 not found */
83    return PCIB_ERR_NOTPRESENT;
84  }
[0ebbf66]85
86  /* BIOS-32 found, let us find PCI BIOS */
87  ucp += 4;
88
89  pcibExchg[0] = *(unsigned int *)ucp;
90
[00882105]91  __asm__ ("    pusha");                  /* Push all registers */
92  __asm__ ("    movl pcibExchg, %edi");   /* Move entry point to esi */
93  __asm__ ("    movl $0x49435024, %eax"); /* Move signature to eax */
94  __asm__ ("    xorl %ebx, %ebx");        /* Zero ebx */
95  __asm__ ("    pushl %cs");
96  __asm__ ("    call *%edi");             /* Call entry */
97  __asm__ ("    movl %eax, pcibExchg");
98  __asm__ ("    movl %ebx, pcibExchg+4");
99  __asm__ ("    movl %ecx, pcibExchg+8");
100  __asm__ ("    movl %edx, pcibExchg+12");
101  __asm__ ("    popa");
[0ebbf66]102
[6266abe]103  if ((pcibExchg[0] & 0xff) != 0) {
104    /* Not found */
105    return PCIB_ERR_NOTPRESENT;
106  }
[0ebbf66]107
108  /* Found PCI entry point */
109  pcibEntry = pcibExchg[1] + pcibExchg[3];
110
111  /* Let us check whether PCI bios is present */
112  pcibExchg[0] = pcibEntry;
[6266abe]113
[00882105]114  __asm__ ("    pusha");
115  __asm__ ("    movl pcibExchg, %edi");
116  __asm__ ("    movb $0xb1, %ah");
117  __asm__ ("    movb $0x01, %al");
118  __asm__ ("    pushl %cs");
119  __asm__ ("    call *%edi");
120  __asm__ ("    movl %eax, pcibExchg");
121  __asm__ ("    movl %ebx, pcibExchg+4");
122  __asm__ ("    movl %ecx, pcibExchg+8");
123  __asm__ ("    movl %edx, pcibExchg+12");
124  __asm__ ("    popa");
[0ebbf66]125
[6266abe]126  if ((pcibExchg[0] & 0xff00) != 0) {
127    /* Not found */
128    return PCIB_ERR_NOTPRESENT;
129  }
[0ebbf66]130
[6266abe]131  if (pcibExchg[3] != 0x20494350) {
132    /* Signature does not match */
133    return PCIB_ERR_NOTPRESENT;
134  }
[0ebbf66]135
136  /* Success */
[6266abe]137
[0ebbf66]138  pcibInitialized = 1;
139  return PCIB_ERR_SUCCESS;
140}
141
[6266abe]142/*
143 * Find specified device and return its signature: combination
[0ebbf66]144 * of bus number, device number and function number
145 */
[32f2304a]146static int
[0ebbf66]147pcib_find_by_devid(int vendorId, int devId, int idx, int *sig)
148{
[6266abe]149  if (!pcibInitialized) {
150    return PCIB_ERR_UNINITIALIZED;
151  }
[0ebbf66]152
153  pcibExchg[0] = pcibEntry;
154  pcibExchg[1] = vendorId;
155  pcibExchg[2] = devId;
156  pcibExchg[3] = idx;
157
[00882105]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");
[0ebbf66]170
171  *sig = pcibExchg[1] & 0xffff;
172
173  return pcib_convert_err((pcibExchg[0] >> 8) & 0xff);
174}
175
[c2701a0]176int
177pci_find_device(
178  unsigned short vendorid,
179  unsigned short deviceid,
180  int instance,
181  int *pbus,
182  int *pdev,
183  int *pfun
184)
185{
186  int status;
[a6e2293]187  int sig = 0;
[c2701a0]188
189  status = pcib_find_by_devid( vendorid, deviceid, instance, &sig );
190
191  *pbus = PCIB_DEVSIG_BUS(sig);
192  *pdev = PCIB_DEVSIG_DEV(sig);
193  *pfun = PCIB_DEVSIG_FUNC(sig);
[b365d4d]194  return status ? -1 : 0;
[c2701a0]195}
196
[718c36d]197static uint8_t ucBusCount = 0xff;
[d7034e1]198
[bdc2572]199unsigned char
[f9abe50]200pci_bus_count(void)
[d7034e1]201{
[6266abe]202  if ( ucBusCount == 0xff ) {
203    unsigned char bus;
204    unsigned char dev;
[2573e69]205    unsigned char fun;
206    unsigned char nfn;
[6266abe]207    unsigned char hd = 0;
[8149a2de]208    uint32_t d = 0;
[6266abe]209
210    ucBusCount = 0;
211
212    for (bus=0; bus< 0xff; bus++) {
213      for (dev=0; dev<PCI_MAX_DEVICES; dev++) {
[12c9dc8f]214        pci_read_config_dword(bus, dev, fun, PCI_VENDOR_ID, &d);
[6266abe]215
[2573e69]216        if ( -1 == d ) {
217          continue;
218        }
219
[12c9dc8f]220        pci_read_config_byte(bus, dev, fun, PCI_HEADER_TYPE, &hd);
[2573e69]221        nfn = (hd & 0x80) ? PCI_MAX_FUNCTIONS : 1;
222
223        for ( fun=0; fun<nfn; fun++ ) {
224
[12c9dc8f]225          pci_read_config_dword(bus, dev, fun, PCI_VENDOR_ID, &d);
[2573e69]226          if ( -1 == d )
227            continue;
228
[12c9dc8f]229          pci_read_config_dword(bus, dev, fun, PCI_CLASS_REVISION, &d);
[2573e69]230
231          if ( (d >> 16) == PCI_CLASS_BRIDGE_PCI ) {
[12c9dc8f]232            pci_read_config_byte(bus, dev, fun, PCI_SUBORDINATE_BUS, &hd);
[6266abe]233
[2573e69]234            if ( hd > ucBusCount )
235              ucBusCount = hd;
236          }
[6266abe]237
238        }
[d7034e1]239      }
[6266abe]240    }
[d7034e1]241
[6266abe]242    if ( ucBusCount == 0 ) {
243      printk("pci_bus_count() found 0 busses, assuming 1\n");
244      ucBusCount = 1;
245    } else if ( ucBusCount == 0xff ) {
246      printk("pci_bus_count() found 0xff busses, assuming 1\n");
247      ucBusCount = 1;
248    }
249  }
[d7034e1]250
[6266abe]251  return ucBusCount;
[d7034e1]252}
253
[6266abe]254/*
[0ebbf66]255 * Read byte from config space
256 */
[12c9dc8f]257static int
[8149a2de]258pcib_conf_read8(int sig, int off, uint8_t *data)
[0ebbf66]259{
[6266abe]260  if (!pcibInitialized) {
261    return PCIB_ERR_UNINITIALIZED;
262  }
[0ebbf66]263
264  pcibExchg[0] = pcibEntry;
265  pcibExchg[1] = sig;
266  pcibExchg[2] = off;
267
[00882105]268  __asm__ ("    pusha");
269  __asm__ ("    movl pcibExchg, %esi");
270  __asm__ ("    movb $0xb1, %ah");
271  __asm__ ("    movb $0x08, %al");
272  __asm__ ("    movl pcibExchg+4, %ebx");
273  __asm__ ("    movl pcibExchg+8, %edi");
274  __asm__ ("    pushl %cs");
275  __asm__ ("    call *%esi");
276  __asm__ ("    movl %eax, pcibExchg");
277  __asm__ ("    movl %ecx, pcibExchg+4");
278  __asm__ ("    popa");
[0ebbf66]279
[6266abe]280  if ((pcibExchg[0] & 0xff00) != 0) {
281    return pcib_convert_err((pcibExchg[0] >> 8) & 0xff);
282  }
[0ebbf66]283
284  *data = (unsigned char)pcibExchg[1] & 0xff;
285
286  return PCIB_ERR_SUCCESS;
287}
288
[6266abe]289
290/*
[0ebbf66]291 * Read word from config space
292 */
[12c9dc8f]293static int
[8149a2de]294pcib_conf_read16(int sig, int off, uint16_t *data)
[0ebbf66]295{
[6266abe]296  if (!pcibInitialized) {
297    return PCIB_ERR_UNINITIALIZED;
298  }
[0ebbf66]299
300  pcibExchg[0] = pcibEntry;
301  pcibExchg[1] = sig;
302  pcibExchg[2] = off;
303
[00882105]304  __asm__ ("    pusha");
305  __asm__ ("    movl pcibExchg, %esi");
306  __asm__ ("    movb $0xb1, %ah");
307  __asm__ ("    movb $0x09, %al");
308  __asm__ ("    movl pcibExchg+4, %ebx");
309  __asm__ ("    movl pcibExchg+8, %edi");
310  __asm__ ("    pushl %cs");
311  __asm__ ("    call *%esi");
312  __asm__ ("    movl %eax, pcibExchg");
313  __asm__ ("    movl %ecx, pcibExchg+4");
314  __asm__ ("    popa");
[0ebbf66]315
[6266abe]316  if ((pcibExchg[0] & 0xff00) != 0) {
317    return pcib_convert_err((pcibExchg[0] >> 8) & 0xff);
318  }
[0ebbf66]319
320  *data = (unsigned short)pcibExchg[1] & 0xffff;
321
322  return PCIB_ERR_SUCCESS;
323}
324
[6266abe]325
326/*
[0ebbf66]327 * Read dword from config space
328 */
[12c9dc8f]329static int
[8149a2de]330pcib_conf_read32(int sig, int off, uint32_t *data)
[0ebbf66]331{
[6266abe]332  if (!pcibInitialized) {
333    return PCIB_ERR_UNINITIALIZED;
334  }
[0ebbf66]335
336  pcibExchg[0] = pcibEntry;
337  pcibExchg[1] = sig;
338  pcibExchg[2] = off;
339
[00882105]340  __asm__ ("    pusha");
341  __asm__ ("    movl pcibExchg, %esi");
342  __asm__ ("    movb $0xb1, %ah");
343  __asm__ ("    movb $0x0a, %al");
344  __asm__ ("    movl pcibExchg+4, %ebx");
345  __asm__ ("    movl pcibExchg+8, %edi");
346  __asm__ ("    pushl %cs");
347  __asm__ ("    call *%esi");
348  __asm__ ("    movl %eax, pcibExchg");
349  __asm__ ("    movl %ecx, pcibExchg+4");
350  __asm__ ("    popa");
[0ebbf66]351
[6266abe]352  if ((pcibExchg[0] & 0xff00) != 0) {
353    return pcib_convert_err((pcibExchg[0] >> 8) & 0xff);
354  }
[0ebbf66]355
356  *data = (unsigned int)pcibExchg[1];
357
358  return PCIB_ERR_SUCCESS;
359}
360
[6266abe]361
362/*
[0ebbf66]363 * Write byte into  config space
364 */
[12c9dc8f]365static int
[8149a2de]366pcib_conf_write8(int sig, int off, uint8_t data)
[0ebbf66]367{
[6266abe]368  if (!pcibInitialized) {
369    return PCIB_ERR_UNINITIALIZED;
370  }
[0ebbf66]371
372  pcibExchg[0] = pcibEntry;
373  pcibExchg[1] = sig;
374  pcibExchg[2] = off;
375  pcibExchg[3] = data & 0xff;
376
[00882105]377  __asm__ ("    pusha");
378  __asm__ ("    movl pcibExchg, %esi");
379  __asm__ ("    movb $0xb1, %ah");
380  __asm__ ("    movb $0x0b, %al");
381  __asm__ ("    movl pcibExchg+4, %ebx");
382  __asm__ ("    movl pcibExchg+8, %edi");
383  __asm__ ("    movl pcibExchg+12, %ecx");
384  __asm__ ("    pushl %cs");
385  __asm__ ("    call *%esi");
386  __asm__ ("    movl %eax, pcibExchg");
387  __asm__ ("    popa");
[0ebbf66]388
389  return pcib_convert_err((pcibExchg[0] >> 8) & 0xff);
390}
391
[6266abe]392/*
[0ebbf66]393 * Write word into config space
394 */
[12c9dc8f]395static int
[8149a2de]396pcib_conf_write16(int sig, int off, uint16_t data)
[0ebbf66]397{
[6266abe]398  if (!pcibInitialized) {
399    return PCIB_ERR_UNINITIALIZED;
400  }
[0ebbf66]401
402  pcibExchg[0] = pcibEntry;
403  pcibExchg[1] = sig;
404  pcibExchg[2] = off;
405  pcibExchg[3] = data & 0xffff;
406
[00882105]407  __asm__ ("    pusha");
408  __asm__ ("    movl pcibExchg, %esi");
409  __asm__ ("    movb $0xb1, %ah");
410  __asm__ ("    movb $0x0c, %al");
411  __asm__ ("    movl pcibExchg+4, %ebx");
412  __asm__ ("    movl pcibExchg+8, %edi");
413  __asm__ ("    movl pcibExchg+12, %ecx");
414  __asm__ ("    pushl %cs");
415  __asm__ ("    call *%esi");
416  __asm__ ("    movl %eax, pcibExchg");
417  __asm__ ("    popa");
[0ebbf66]418
419  return pcib_convert_err((pcibExchg[0] >> 8) & 0xff);
420}
421
[d7034e1]422
[6266abe]423
424/*
[0ebbf66]425 * Write dword into config space
426 */
[12c9dc8f]427static int
[8149a2de]428pcib_conf_write32(int sig, int off, uint32_t data)
[0ebbf66]429{
[6266abe]430  if (!pcibInitialized){
[0ebbf66]431      return PCIB_ERR_UNINITIALIZED;
[6266abe]432  }
[0ebbf66]433
434  pcibExchg[0] = pcibEntry;
435  pcibExchg[1] = sig;
436  pcibExchg[2] = off;
437  pcibExchg[3] = data;
438
[00882105]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");
[0ebbf66]450
451  return pcib_convert_err((pcibExchg[0] >> 8) & 0xff);
452}
[6266abe]453
[6128a4a]454
[0ebbf66]455static int
456pcib_convert_err(int err)
457{
[6266abe]458  switch(err & 0xff){
[0ebbf66]459    case 0:
460      return PCIB_ERR_SUCCESS;
461    case 0x81:
462      return PCIB_ERR_NOFUNC;
463    case 0x83:
464      return PCIB_ERR_BADVENDOR;
465    case 0x86:
466      return PCIB_ERR_DEVNOTFOUND;
467    case 0x87:
468      return PCIB_ERR_BADREG;
469    default:
470      break;
[6266abe]471  }
[0ebbf66]472  return PCIB_ERR_NOFUNC;
473}
[d7034e1]474
[6266abe]475static int
[60b728b5]476BSP_pci_read_config_byte(
[6266abe]477  unsigned char bus,
478  unsigned char slot,
479  unsigned char fun,
480  unsigned char offset,
481  unsigned char *val
[3495c57]482)
[6266abe]483{
484  int sig;
[d7034e1]485
[6266abe]486  sig = PCIB_DEVSIG_MAKE(bus,slot,fun);
487  pcib_conf_read8(sig, offset, val);
488  return PCIBIOS_SUCCESSFUL;
489}
[d7034e1]490
[6266abe]491static int
[60b728b5]492BSP_pci_read_config_word(
[6266abe]493  unsigned char bus,
494  unsigned char slot,
495  unsigned char fun,
496  unsigned char offset,
497  unsigned short *val
[3495c57]498)
[6266abe]499{
500  int sig;
[d7034e1]501
[6266abe]502  sig = PCIB_DEVSIG_MAKE(bus,slot,fun);
503  pcib_conf_read16(sig, offset, val);
504  return PCIBIOS_SUCCESSFUL;
505}
506
507static int
[60b728b5]508BSP_pci_read_config_dword(
[6266abe]509  unsigned char bus,
510  unsigned char slot,
511  unsigned char fun,
512  unsigned char offset,
[8149a2de]513  uint32_t     *val
[3495c57]514)
[6266abe]515{
516  int sig;
517
518  sig = PCIB_DEVSIG_MAKE(bus,slot,fun);
519  pcib_conf_read32(sig, offset, val);
520  return PCIBIOS_SUCCESSFUL;
521}
522
523static int
[60b728b5]524BSP_pci_write_config_byte(
[6266abe]525  unsigned char bus,
526  unsigned char slot,
527  unsigned char fun,
528  unsigned char offset,
529  unsigned char val
[3495c57]530)
[6266abe]531{
532  int sig;
533
534  sig = PCIB_DEVSIG_MAKE(bus,slot,fun);
535  pcib_conf_write8(sig, offset, val);
536  return PCIBIOS_SUCCESSFUL;
537}
538
539static int
[60b728b5]540BSP_pci_write_config_word(
[6266abe]541  unsigned char bus,
542  unsigned char slot,
543  unsigned char fun,
544  unsigned char offset,
545  unsigned short val
[3495c57]546)
[6266abe]547{
548  int sig;
549
550  sig = PCIB_DEVSIG_MAKE(bus,slot,fun);
551  pcib_conf_write16(sig, offset, val);
552  return PCIBIOS_SUCCESSFUL;
553}
554
555static int
[60b728b5]556BSP_pci_write_config_dword(
[6266abe]557  unsigned char bus,
558  unsigned char slot,
559  unsigned char fun,
560  unsigned char offset,
[8149a2de]561  uint32_t      val
[3495c57]562)
[6266abe]563{
564  int sig;
565
566  sig = PCIB_DEVSIG_MAKE(bus,slot,fun);
567  pcib_conf_write32(sig, offset, val);
568  return PCIBIOS_SUCCESSFUL;
569}
[d7034e1]570
[6266abe]571const pci_config_access_functions pci_indirect_functions = {
[60b728b5]572  BSP_pci_read_config_byte,
573  BSP_pci_read_config_word,
574  BSP_pci_read_config_dword,
575  BSP_pci_write_config_byte,
576  BSP_pci_write_config_word,
577  BSP_pci_write_config_dword
[6266abe]578};
579
[32c347d]580rtems_pci_config_t BSP_pci_configuration = {
[6266abe]581  (volatile unsigned char*)0,
582  (volatile unsigned char*)0,
583  &pci_indirect_functions
584};
Note: See TracBrowser for help on using the repository browser.