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

Last change on this file since 3b697232 was 3b697232, checked in by Joel Sherrill <joel@…>, on Mar 2, 2016 at 7:31:45 PM

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

  • Property mode set to 100644
File size: 12.7 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 <rtems/pci.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 */
18static int pcibInitialized = 0;
19static unsigned int pcibEntry;
20
21/*
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
24 * of gcc. This code is not on performance path, so we can care
25 * relatively little about performance here
26 */
27static volatile unsigned int pcibExchg[5];
28
29static int pcib_convert_err(int err);
30
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)
43/*
44 * Detects presense of PCI BIOS, returns
45 * error code
46 */
47int
48pci_initialize(void)
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 */
57  for (ucp = (unsigned char *)0xE0000;
58       ucp < (unsigned char *)0xFFFFF;
59       ucp += 0x10) {
60    if (memcmp(ucp, "_32_", 4) != 0) {
61      continue;
62    }
63
64      /* Got signature, check length  */
65    if (*(ucp + 9) != 1) {
66      continue;
67    }
68
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;
78    }
79  }
80
81  if (ucp >= (unsigned char *)0xFFFFF) {
82    /* BIOS-32 not found */
83    return PCIB_ERR_NOTPRESENT;
84  }
85
86  /* BIOS-32 found, let us find PCI BIOS */
87  ucp += 4;
88
89  pcibExchg[0] = *(unsigned int *)ucp;
90
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");
102
103  if ((pcibExchg[0] & 0xff) != 0) {
104    /* Not found */
105    return PCIB_ERR_NOTPRESENT;
106  }
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;
113
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");
125
126  if ((pcibExchg[0] & 0xff00) != 0) {
127    /* Not found */
128    return PCIB_ERR_NOTPRESENT;
129  }
130
131  if (pcibExchg[3] != 0x20494350) {
132    /* Signature does not match */
133    return PCIB_ERR_NOTPRESENT;
134  }
135
136  /* Success */
137
138  pcibInitialized = 1;
139  return PCIB_ERR_SUCCESS;
140}
141
142/*
143 * Find specified device and return its signature: combination
144 * of bus number, device number and function number
145 */
146static int
147pcib_find_by_devid(int vendorId, int devId, int idx, int *sig)
148{
149  if (!pcibInitialized) {
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
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;
187  int sig = 0;
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);
194  return status ? -1 : 0;
195}
196
197static uint8_t ucBusCount = 0xff;
198
199unsigned char
200pci_bus_count(void)
201{
202  if ( ucBusCount == 0xff ) {
203    unsigned char bus;
204    unsigned char dev;
205    unsigned char fun;
206    unsigned char nfn;
207    unsigned char hd = 0;
208    uint32_t d = 0;
209
210    ucBusCount = 0;
211
212    for (bus=0; bus< 0xff; bus++) {
213      for (dev=0; dev<PCI_MAX_DEVICES; dev++) {
214        pci_read_config_dword(bus, dev, fun, PCI_VENDOR_ID, &d);
215
216        if ( -1 == d ) {
217          continue;
218        }
219
220        pci_read_config_byte(bus, dev, fun, PCI_HEADER_TYPE, &hd);
221        nfn = (hd & 0x80) ? PCI_MAX_FUNCTIONS : 1;
222
223        for ( fun=0; fun<nfn; fun++ ) {
224
225          pci_read_config_dword(bus, dev, fun, PCI_VENDOR_ID, &d);
226          if ( -1 == d )
227            continue;
228
229          pci_read_config_dword(bus, dev, fun, PCI_CLASS_REVISION, &d);
230
231          if ( (d >> 16) == PCI_CLASS_BRIDGE_PCI ) {
232            pci_read_config_byte(bus, dev, fun, PCI_SUBORDINATE_BUS, &hd);
233
234            if ( hd > ucBusCount )
235              ucBusCount = hd;
236          }
237
238        }
239      }
240    }
241
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  }
250
251  return ucBusCount;
252}
253
254/*
255 * Read byte from config space
256 */
257static int
258pcib_conf_read8(int sig, int off, uint8_t *data)
259{
260  if (!pcibInitialized) {
261    return PCIB_ERR_UNINITIALIZED;
262  }
263
264  pcibExchg[0] = pcibEntry;
265  pcibExchg[1] = sig;
266  pcibExchg[2] = off;
267
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");
279
280  if ((pcibExchg[0] & 0xff00) != 0) {
281    return pcib_convert_err((pcibExchg[0] >> 8) & 0xff);
282  }
283
284  *data = (unsigned char)pcibExchg[1] & 0xff;
285
286  return PCIB_ERR_SUCCESS;
287}
288
289
290/*
291 * Read word from config space
292 */
293static int
294pcib_conf_read16(int sig, int off, uint16_t *data)
295{
296  if (!pcibInitialized) {
297    return PCIB_ERR_UNINITIALIZED;
298  }
299
300  pcibExchg[0] = pcibEntry;
301  pcibExchg[1] = sig;
302  pcibExchg[2] = off;
303
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");
315
316  if ((pcibExchg[0] & 0xff00) != 0) {
317    return pcib_convert_err((pcibExchg[0] >> 8) & 0xff);
318  }
319
320  *data = (unsigned short)pcibExchg[1] & 0xffff;
321
322  return PCIB_ERR_SUCCESS;
323}
324
325
326/*
327 * Read dword from config space
328 */
329static int
330pcib_conf_read32(int sig, int off, uint32_t *data)
331{
332  if (!pcibInitialized) {
333    return PCIB_ERR_UNINITIALIZED;
334  }
335
336  pcibExchg[0] = pcibEntry;
337  pcibExchg[1] = sig;
338  pcibExchg[2] = off;
339
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");
351
352  if ((pcibExchg[0] & 0xff00) != 0) {
353    return pcib_convert_err((pcibExchg[0] >> 8) & 0xff);
354  }
355
356  *data = (unsigned int)pcibExchg[1];
357
358  return PCIB_ERR_SUCCESS;
359}
360
361
362/*
363 * Write byte into  config space
364 */
365static int
366pcib_conf_write8(int sig, int off, uint8_t data)
367{
368  if (!pcibInitialized) {
369    return PCIB_ERR_UNINITIALIZED;
370  }
371
372  pcibExchg[0] = pcibEntry;
373  pcibExchg[1] = sig;
374  pcibExchg[2] = off;
375  pcibExchg[3] = data & 0xff;
376
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");
388
389  return pcib_convert_err((pcibExchg[0] >> 8) & 0xff);
390}
391
392/*
393 * Write word into config space
394 */
395static int
396pcib_conf_write16(int sig, int off, uint16_t data)
397{
398  if (!pcibInitialized) {
399    return PCIB_ERR_UNINITIALIZED;
400  }
401
402  pcibExchg[0] = pcibEntry;
403  pcibExchg[1] = sig;
404  pcibExchg[2] = off;
405  pcibExchg[3] = data & 0xffff;
406
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");
418
419  return pcib_convert_err((pcibExchg[0] >> 8) & 0xff);
420}
421
422
423
424/*
425 * Write dword into config space
426 */
427static int
428pcib_conf_write32(int sig, int off, uint32_t data)
429{
430  if (!pcibInitialized){
431      return PCIB_ERR_UNINITIALIZED;
432  }
433
434  pcibExchg[0] = pcibEntry;
435  pcibExchg[1] = sig;
436  pcibExchg[2] = off;
437  pcibExchg[3] = data;
438
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");
450
451  return pcib_convert_err((pcibExchg[0] >> 8) & 0xff);
452}
453
454
455static int
456pcib_convert_err(int err)
457{
458  switch(err & 0xff){
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;
471  }
472  return PCIB_ERR_NOFUNC;
473}
474
475static int
476BSP_pci_read_config_byte(
477  unsigned char bus,
478  unsigned char slot,
479  unsigned char fun,
480  unsigned char offset,
481  unsigned char *val
482)
483{
484  int sig;
485
486  sig = PCIB_DEVSIG_MAKE(bus,slot,fun);
487  pcib_conf_read8(sig, offset, val);
488  return PCIBIOS_SUCCESSFUL;
489}
490
491static int
492BSP_pci_read_config_word(
493  unsigned char bus,
494  unsigned char slot,
495  unsigned char fun,
496  unsigned char offset,
497  unsigned short *val
498)
499{
500  int sig;
501
502  sig = PCIB_DEVSIG_MAKE(bus,slot,fun);
503  pcib_conf_read16(sig, offset, val);
504  return PCIBIOS_SUCCESSFUL;
505}
506
507static int
508BSP_pci_read_config_dword(
509  unsigned char bus,
510  unsigned char slot,
511  unsigned char fun,
512  unsigned char offset,
513  uint32_t     *val
514)
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
524BSP_pci_write_config_byte(
525  unsigned char bus,
526  unsigned char slot,
527  unsigned char fun,
528  unsigned char offset,
529  unsigned char val
530)
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
540BSP_pci_write_config_word(
541  unsigned char bus,
542  unsigned char slot,
543  unsigned char fun,
544  unsigned char offset,
545  unsigned short val
546)
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
556BSP_pci_write_config_dword(
557  unsigned char bus,
558  unsigned char slot,
559  unsigned char fun,
560  unsigned char offset,
561  uint32_t      val
562)
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}
570
571const pci_config_access_functions pci_indirect_functions = {
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
578};
579
580rtems_pci_config_t BSP_pci_configuration = {
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.