source: rtems/c/src/lib/libbsp/i386/shared/pci/pcibios.c @ 12c9dc8f

5
Last change on this file since 12c9dc8f was 12c9dc8f, checked in by Joel Sherrill <joel@…>, on Mar 2, 2016 at 7:25:13 PM

pc386: Eliminate pcibios.h and begin removal obsolete PCI BIOS API uses

This first step eliminates the following as public APIs for the pc386
BSP:

+ pcib_conf_read8
+ pcib_conf_read16
+ pcib_conf_read32
+ pcib_conf_write8
+ pcib_conf_write16
+ pcib_conf_write32

The if_fxp.c driver uses these enough where I provided local macros
to allow the code to be mostly unmodified. On other architectures
these names have been used privately. It will take multiple patches
to completely eliminate these symbols from the RTEMS source tree.

The focus of the first effort is just to eliminate these as a public
pc386 API so support can be added for systems without legacy PCI BIOS.

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