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

4.115
Last change on this file since 1ecb21d was 1ecb21d, checked in by Joel Sherrill <joel.sherrill@…>, on Oct 14, 2014 at 12:08:14 AM

libbsp/i386/shared: Fix warnings

  • Property mode set to 100644
File size: 13.5 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/*
268 * Generate Special Cycle
269 */
270int
271pcib_special_cycle(int busNo, int data)
272{
273  if (!pcibInitialized) {
274    return PCIB_ERR_UNINITIALIZED;
275  }
276
277  pcibExchg[0] = pcibEntry;
278  pcibExchg[1] = busNo << 8;
279  pcibExchg[2] = data;
280
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");
292
293  return pcib_convert_err((pcibExchg[0] >> 8) & 0xff);
294}
295
296
297/*
298 * Read byte from config space
299 */
300int
301pcib_conf_read8(int sig, int off, uint8_t *data)
302{
303  if (!pcibInitialized) {
304    return PCIB_ERR_UNINITIALIZED;
305  }
306
307  pcibExchg[0] = pcibEntry;
308  pcibExchg[1] = sig;
309  pcibExchg[2] = off;
310
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");
322
323  if ((pcibExchg[0] & 0xff00) != 0) {
324    return pcib_convert_err((pcibExchg[0] >> 8) & 0xff);
325  }
326
327  *data = (unsigned char)pcibExchg[1] & 0xff;
328
329  return PCIB_ERR_SUCCESS;
330}
331
332
333/*
334 * Read word from config space
335 */
336int
337pcib_conf_read16(int sig, int off, uint16_t *data)
338{
339  if (!pcibInitialized) {
340    return PCIB_ERR_UNINITIALIZED;
341  }
342
343  pcibExchg[0] = pcibEntry;
344  pcibExchg[1] = sig;
345  pcibExchg[2] = off;
346
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");
358
359  if ((pcibExchg[0] & 0xff00) != 0) {
360    return pcib_convert_err((pcibExchg[0] >> 8) & 0xff);
361  }
362
363  *data = (unsigned short)pcibExchg[1] & 0xffff;
364
365  return PCIB_ERR_SUCCESS;
366}
367
368
369/*
370 * Read dword from config space
371 */
372int
373pcib_conf_read32(int sig, int off, uint32_t *data)
374{
375  if (!pcibInitialized) {
376    return PCIB_ERR_UNINITIALIZED;
377  }
378
379  pcibExchg[0] = pcibEntry;
380  pcibExchg[1] = sig;
381  pcibExchg[2] = off;
382
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");
394
395  if ((pcibExchg[0] & 0xff00) != 0) {
396    return pcib_convert_err((pcibExchg[0] >> 8) & 0xff);
397  }
398
399  *data = (unsigned int)pcibExchg[1];
400
401  return PCIB_ERR_SUCCESS;
402}
403
404
405/*
406 * Write byte into  config space
407 */
408int
409pcib_conf_write8(int sig, int off, uint8_t data)
410{
411  if (!pcibInitialized) {
412    return PCIB_ERR_UNINITIALIZED;
413  }
414
415  pcibExchg[0] = pcibEntry;
416  pcibExchg[1] = sig;
417  pcibExchg[2] = off;
418  pcibExchg[3] = data & 0xff;
419
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");
431
432  return pcib_convert_err((pcibExchg[0] >> 8) & 0xff);
433}
434
435/*
436 * Write word into config space
437 */
438int
439pcib_conf_write16(int sig, int off, uint16_t data)
440{
441  if (!pcibInitialized) {
442    return PCIB_ERR_UNINITIALIZED;
443  }
444
445  pcibExchg[0] = pcibEntry;
446  pcibExchg[1] = sig;
447  pcibExchg[2] = off;
448  pcibExchg[3] = data & 0xffff;
449
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");
461
462  return pcib_convert_err((pcibExchg[0] >> 8) & 0xff);
463}
464
465
466
467/*
468 * Write dword into config space
469 */
470int
471pcib_conf_write32(int sig, int off, uint32_t data)
472{
473  if (!pcibInitialized){
474      return PCIB_ERR_UNINITIALIZED;
475  }
476
477  pcibExchg[0] = pcibEntry;
478  pcibExchg[1] = sig;
479  pcibExchg[2] = off;
480  pcibExchg[3] = data;
481
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");
493
494  return pcib_convert_err((pcibExchg[0] >> 8) & 0xff);
495}
496
497
498static int
499pcib_convert_err(int err)
500{
501  switch(err & 0xff){
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;
514  }
515  return PCIB_ERR_NOFUNC;
516}
517
518static int
519BSP_pci_read_config_byte(
520  unsigned char bus,
521  unsigned char slot,
522  unsigned char fun,
523  unsigned char offset,
524  unsigned char *val
525)
526{
527  int sig;
528
529  sig = PCIB_DEVSIG_MAKE(bus,slot,fun);
530  pcib_conf_read8(sig, offset, val);
531  return PCIBIOS_SUCCESSFUL;
532}
533
534static int
535BSP_pci_read_config_word(
536  unsigned char bus,
537  unsigned char slot,
538  unsigned char fun,
539  unsigned char offset,
540  unsigned short *val
541)
542{
543  int sig;
544
545  sig = PCIB_DEVSIG_MAKE(bus,slot,fun);
546  pcib_conf_read16(sig, offset, val);
547  return PCIBIOS_SUCCESSFUL;
548}
549
550static int
551BSP_pci_read_config_dword(
552  unsigned char bus,
553  unsigned char slot,
554  unsigned char fun,
555  unsigned char offset,
556  uint32_t     *val
557)
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
567BSP_pci_write_config_byte(
568  unsigned char bus,
569  unsigned char slot,
570  unsigned char fun,
571  unsigned char offset,
572  unsigned char val
573)
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
583BSP_pci_write_config_word(
584  unsigned char bus,
585  unsigned char slot,
586  unsigned char fun,
587  unsigned char offset,
588  unsigned short val
589)
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
599BSP_pci_write_config_dword(
600  unsigned char bus,
601  unsigned char slot,
602  unsigned char fun,
603  unsigned char offset,
604  uint32_t      val
605)
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}
613
614const pci_config_access_functions pci_indirect_functions = {
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
621};
622
623rtems_pci_config_t BSP_pci_configuration = {
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.