source: rtems/c/src/lib/libbsp/i386/shared/pci/pcibios.c @ 8ce16a4

Last change on this file since 8ce16a4 was 8ce16a4, checked in by Joel Sherrill <joel@…>, on Mar 2, 2016 at 7:30:27 PM

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

  • 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 <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 * Read byte from config space
292 */
293static int
294pcib_conf_read8(int sig, int off, uint8_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 $0x08, %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 char)pcibExchg[1] & 0xff;
321
322  return PCIB_ERR_SUCCESS;
323}
324
325
326/*
327 * Read word from config space
328 */
329static int
330pcib_conf_read16(int sig, int off, uint16_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 $0x09, %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 short)pcibExchg[1] & 0xffff;
357
358  return PCIB_ERR_SUCCESS;
359}
360
361
362/*
363 * Read dword from config space
364 */
365static int
366pcib_conf_read32(int sig, int off, uint32_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
376  __asm__ ("    pusha");
377  __asm__ ("    movl pcibExchg, %esi");
378  __asm__ ("    movb $0xb1, %ah");
379  __asm__ ("    movb $0x0a, %al");
380  __asm__ ("    movl pcibExchg+4, %ebx");
381  __asm__ ("    movl pcibExchg+8, %edi");
382  __asm__ ("    pushl %cs");
383  __asm__ ("    call *%esi");
384  __asm__ ("    movl %eax, pcibExchg");
385  __asm__ ("    movl %ecx, pcibExchg+4");
386  __asm__ ("    popa");
387
388  if ((pcibExchg[0] & 0xff00) != 0) {
389    return pcib_convert_err((pcibExchg[0] >> 8) & 0xff);
390  }
391
392  *data = (unsigned int)pcibExchg[1];
393
394  return PCIB_ERR_SUCCESS;
395}
396
397
398/*
399 * Write byte into  config space
400 */
401static int
402pcib_conf_write8(int sig, int off, uint8_t data)
403{
404  if (!pcibInitialized) {
405    return PCIB_ERR_UNINITIALIZED;
406  }
407
408  pcibExchg[0] = pcibEntry;
409  pcibExchg[1] = sig;
410  pcibExchg[2] = off;
411  pcibExchg[3] = data & 0xff;
412
413  __asm__ ("    pusha");
414  __asm__ ("    movl pcibExchg, %esi");
415  __asm__ ("    movb $0xb1, %ah");
416  __asm__ ("    movb $0x0b, %al");
417  __asm__ ("    movl pcibExchg+4, %ebx");
418  __asm__ ("    movl pcibExchg+8, %edi");
419  __asm__ ("    movl pcibExchg+12, %ecx");
420  __asm__ ("    pushl %cs");
421  __asm__ ("    call *%esi");
422  __asm__ ("    movl %eax, pcibExchg");
423  __asm__ ("    popa");
424
425  return pcib_convert_err((pcibExchg[0] >> 8) & 0xff);
426}
427
428/*
429 * Write word into config space
430 */
431static int
432pcib_conf_write16(int sig, int off, uint16_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 & 0xffff;
442
443  __asm__ ("    pusha");
444  __asm__ ("    movl pcibExchg, %esi");
445  __asm__ ("    movb $0xb1, %ah");
446  __asm__ ("    movb $0x0c, %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
460/*
461 * Write dword into config space
462 */
463static int
464pcib_conf_write32(int sig, int off, uint32_t data)
465{
466  if (!pcibInitialized){
467      return PCIB_ERR_UNINITIALIZED;
468  }
469
470  pcibExchg[0] = pcibEntry;
471  pcibExchg[1] = sig;
472  pcibExchg[2] = off;
473  pcibExchg[3] = data;
474
475  __asm__ ("    pusha");
476  __asm__ ("    movl pcibExchg, %esi");
477  __asm__ ("    movb $0xb1, %ah");
478  __asm__ ("    movb $0x0d, %al");
479  __asm__ ("    movl pcibExchg+4, %ebx");
480  __asm__ ("    movl pcibExchg+8, %edi");
481  __asm__ ("    movl pcibExchg+12, %ecx");
482  __asm__ ("    pushl %cs");
483  __asm__ ("    call *%esi");
484  __asm__ ("    movl %eax, pcibExchg");
485  __asm__ ("    popa");
486
487  return pcib_convert_err((pcibExchg[0] >> 8) & 0xff);
488}
489
490
491static int
492pcib_convert_err(int err)
493{
494  switch(err & 0xff){
495    case 0:
496      return PCIB_ERR_SUCCESS;
497    case 0x81:
498      return PCIB_ERR_NOFUNC;
499    case 0x83:
500      return PCIB_ERR_BADVENDOR;
501    case 0x86:
502      return PCIB_ERR_DEVNOTFOUND;
503    case 0x87:
504      return PCIB_ERR_BADREG;
505    default:
506      break;
507  }
508  return PCIB_ERR_NOFUNC;
509}
510
511static int
512BSP_pci_read_config_byte(
513  unsigned char bus,
514  unsigned char slot,
515  unsigned char fun,
516  unsigned char offset,
517  unsigned char *val
518)
519{
520  int sig;
521
522  sig = PCIB_DEVSIG_MAKE(bus,slot,fun);
523  pcib_conf_read8(sig, offset, val);
524  return PCIBIOS_SUCCESSFUL;
525}
526
527static int
528BSP_pci_read_config_word(
529  unsigned char bus,
530  unsigned char slot,
531  unsigned char fun,
532  unsigned char offset,
533  unsigned short *val
534)
535{
536  int sig;
537
538  sig = PCIB_DEVSIG_MAKE(bus,slot,fun);
539  pcib_conf_read16(sig, offset, val);
540  return PCIBIOS_SUCCESSFUL;
541}
542
543static int
544BSP_pci_read_config_dword(
545  unsigned char bus,
546  unsigned char slot,
547  unsigned char fun,
548  unsigned char offset,
549  uint32_t     *val
550)
551{
552  int sig;
553
554  sig = PCIB_DEVSIG_MAKE(bus,slot,fun);
555  pcib_conf_read32(sig, offset, val);
556  return PCIBIOS_SUCCESSFUL;
557}
558
559static int
560BSP_pci_write_config_byte(
561  unsigned char bus,
562  unsigned char slot,
563  unsigned char fun,
564  unsigned char offset,
565  unsigned char val
566)
567{
568  int sig;
569
570  sig = PCIB_DEVSIG_MAKE(bus,slot,fun);
571  pcib_conf_write8(sig, offset, val);
572  return PCIBIOS_SUCCESSFUL;
573}
574
575static int
576BSP_pci_write_config_word(
577  unsigned char bus,
578  unsigned char slot,
579  unsigned char fun,
580  unsigned char offset,
581  unsigned short val
582)
583{
584  int sig;
585
586  sig = PCIB_DEVSIG_MAKE(bus,slot,fun);
587  pcib_conf_write16(sig, offset, val);
588  return PCIBIOS_SUCCESSFUL;
589}
590
591static int
592BSP_pci_write_config_dword(
593  unsigned char bus,
594  unsigned char slot,
595  unsigned char fun,
596  unsigned char offset,
597  uint32_t      val
598)
599{
600  int sig;
601
602  sig = PCIB_DEVSIG_MAKE(bus,slot,fun);
603  pcib_conf_write32(sig, offset, val);
604  return PCIBIOS_SUCCESSFUL;
605}
606
607const pci_config_access_functions pci_indirect_functions = {
608  BSP_pci_read_config_byte,
609  BSP_pci_read_config_word,
610  BSP_pci_read_config_dword,
611  BSP_pci_write_config_byte,
612  BSP_pci_write_config_word,
613  BSP_pci_write_config_dword
614};
615
616rtems_pci_config_t BSP_pci_configuration = {
617  (volatile unsigned char*)0,
618  (volatile unsigned char*)0,
619  &pci_indirect_functions
620};
Note: See TracBrowser for help on using the repository browser.