~peter-pearse/ubuntu/natty/pciutils/prop001

« back to all changes in this revision

Viewing changes to lib/generic.c

  • Committer: Bazaar Package Importer
  • Author(s): Remco van de Meent
  • Date: 2002-03-11 13:26:04 UTC
  • Revision ID: james.westby@ubuntu.com-20020311132604-7way9hqnt42hgmxd
Tags: upstream-2.1.9
ImportĀ upstreamĀ versionĀ 2.1.9

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 *      $Id: generic.c,v 1.6 2000/04/21 11:58:00 mj Exp $
 
3
 *
 
4
 *      The PCI Library -- Generic Direct Access Functions
 
5
 *
 
6
 *      Copyright (c) 1997--2000 Martin Mares <mj@atrey.karlin.mff.cuni.cz>
 
7
 *
 
8
 *      Can be freely distributed and used under the terms of the GNU GPL.
 
9
 */
 
10
 
 
11
#include <string.h>
 
12
 
 
13
#include "internal.h"
 
14
 
 
15
void
 
16
pci_generic_scan_bus(struct pci_access *a, byte *busmap, int bus)
 
17
{
 
18
  int dev, multi, ht;
 
19
  struct pci_dev *t = pci_alloc_dev(a);
 
20
 
 
21
  a->debug("Scanning bus %02x for devices...\n", bus);
 
22
  if (busmap[bus])
 
23
    {
 
24
      a->warning("Bus %02x seen twice (firmware bug). Ignored.", bus);
 
25
      return;
 
26
    }
 
27
  busmap[bus] = 1;
 
28
  t->bus = bus;
 
29
  for(dev=0; dev<32; dev++)
 
30
    {
 
31
      t->dev = dev;
 
32
      multi = 0;
 
33
      for(t->func=0; t->func<8; t->func++)
 
34
        {
 
35
          u32 vd = pci_read_long(t, PCI_VENDOR_ID);
 
36
          struct pci_dev *d;
 
37
 
 
38
          if (!vd || vd == 0xffffffff)
 
39
            break;
 
40
          ht = pci_read_byte(t, PCI_HEADER_TYPE);
 
41
          if (!t->func)
 
42
            multi = ht & 0x80;
 
43
          ht &= 0x7f;
 
44
          d = pci_alloc_dev(a);
 
45
          d->bus = t->bus;
 
46
          d->dev = t->dev;
 
47
          d->func = t->func;
 
48
          d->vendor_id = vd & 0xffff;
 
49
          d->device_id = vd >> 16U;
 
50
          d->known_fields = PCI_FILL_IDENT;
 
51
          d->hdrtype = ht;
 
52
          pci_link_dev(a, d);
 
53
          switch (ht)
 
54
            {
 
55
            case PCI_HEADER_TYPE_NORMAL:
 
56
              break;
 
57
            case PCI_HEADER_TYPE_BRIDGE:
 
58
            case PCI_HEADER_TYPE_CARDBUS:
 
59
              pci_generic_scan_bus(a, busmap, pci_read_byte(t, PCI_SECONDARY_BUS));
 
60
              break;
 
61
            default:
 
62
              a->debug("Device %02x:%02x.%d has unknown header type %02x.\n", d->bus, d->dev, d->func, ht);
 
63
            }
 
64
          if (!multi)
 
65
            break;
 
66
        }
 
67
    }
 
68
}
 
69
 
 
70
void
 
71
pci_generic_scan(struct pci_access *a)
 
72
{
 
73
  byte busmap[256];
 
74
 
 
75
  bzero(busmap, sizeof(busmap));
 
76
  pci_generic_scan_bus(a, busmap, 0);
 
77
}
 
78
 
 
79
int
 
80
pci_generic_fill_info(struct pci_dev *d, int flags)
 
81
{
 
82
  struct pci_access *a = d->access;
 
83
 
 
84
  if (flags & PCI_FILL_IDENT)
 
85
    {
 
86
      d->vendor_id = pci_read_word(d, PCI_VENDOR_ID);
 
87
      d->device_id = pci_read_word(d, PCI_DEVICE_ID);
 
88
    }
 
89
  if (flags & PCI_FILL_IRQ)
 
90
    d->irq = pci_read_byte(d, PCI_INTERRUPT_LINE);
 
91
  if (flags & PCI_FILL_BASES)
 
92
    {
 
93
      int cnt = 0, i;
 
94
      bzero(d->base_addr, sizeof(d->base_addr));
 
95
      switch (d->hdrtype)
 
96
        {
 
97
        case PCI_HEADER_TYPE_NORMAL:
 
98
          cnt = 6;
 
99
          break;
 
100
        case PCI_HEADER_TYPE_BRIDGE:
 
101
          cnt = 2;
 
102
          break;
 
103
        case PCI_HEADER_TYPE_CARDBUS:
 
104
          cnt = 1;
 
105
          break;
 
106
        }
 
107
      if (cnt)
 
108
        {
 
109
          u16 cmd = pci_read_word(d, PCI_COMMAND);
 
110
          for(i=0; i<cnt; i++)
 
111
            {
 
112
              u32 x = pci_read_long(d, PCI_BASE_ADDRESS_0 + i*4);
 
113
              if (!x || x == (u32) ~0)
 
114
                continue;
 
115
              d->base_addr[i] = x;
 
116
              if (x & PCI_BASE_ADDRESS_SPACE_IO)
 
117
                {
 
118
                  if (!a->buscentric && !(cmd & PCI_COMMAND_IO))
 
119
                    d->base_addr[i] = 0;
 
120
                }
 
121
              else if (a->buscentric || (cmd & PCI_COMMAND_MEMORY))
 
122
                {
 
123
                  if ((x & PCI_BASE_ADDRESS_MEM_TYPE_MASK) == PCI_BASE_ADDRESS_MEM_TYPE_64)
 
124
                    {
 
125
                      if (i >= cnt-1)
 
126
                        a->warning("%02x:%02x.%d: Invalid 64-bit address seen.", d->bus, d->dev, d->func);
 
127
                      else
 
128
                        {
 
129
                          u32 y = pci_read_long(d, PCI_BASE_ADDRESS_0 + (++i)*4);
 
130
#ifdef HAVE_64BIT_ADDRESS
 
131
                          d->base_addr[i-1] |= ((pciaddr_t) y) << 32;
 
132
#else
 
133
                          if (y)
 
134
                            {
 
135
                              a->warning("%02x:%02x.%d 64-bit device address ignored.", d->bus, d->dev, d->func);
 
136
                              d->base_addr[i-1] = 0;
 
137
                            }
 
138
#endif
 
139
                        }
 
140
                    }
 
141
                }
 
142
              else
 
143
                d->base_addr[i] = 0;
 
144
            }
 
145
        }
 
146
    }
 
147
  if (flags & PCI_FILL_ROM_BASE)
 
148
    {
 
149
      int reg = 0;
 
150
      d->rom_base_addr = 0;
 
151
      switch (d->hdrtype)
 
152
        {
 
153
        case PCI_HEADER_TYPE_NORMAL:
 
154
          reg = PCI_ROM_ADDRESS;
 
155
          break;
 
156
        case PCI_HEADER_TYPE_BRIDGE:
 
157
          reg = PCI_ROM_ADDRESS1;
 
158
          break;
 
159
        }
 
160
      if (reg)
 
161
        {
 
162
          u32 a = pci_read_long(d, reg);
 
163
          if (a & PCI_ROM_ADDRESS_ENABLE)
 
164
            d->rom_base_addr = a;
 
165
        }
 
166
    }
 
167
  return flags & ~PCI_FILL_SIZES;
 
168
}
 
169
 
 
170
static int
 
171
pci_generic_block_op(struct pci_dev *d, int pos, byte *buf, int len,
 
172
                 int (*r)(struct pci_dev *d, int pos, byte *buf, int len))
 
173
{
 
174
  if ((pos & 1) && len >= 1)
 
175
    {
 
176
      if (!r(d, pos, buf, 1))
 
177
        return 0;
 
178
      pos++; buf++; len--;
 
179
    }
 
180
  if ((pos & 3) && len >= 2)
 
181
    {
 
182
      if (!r(d, pos, buf, 2))
 
183
        return 0;
 
184
      pos += 2; buf += 2; len -= 2;
 
185
    }
 
186
  while (len >= 4)
 
187
    {
 
188
      if (!r(d, pos, buf, 4))
 
189
        return 0;
 
190
      pos += 4; buf += 4; len -= 4;
 
191
    }
 
192
  if (len >= 2)
 
193
    {
 
194
      if (!r(d, pos, buf, 2))
 
195
        return 0;
 
196
      pos += 2; buf += 2; len -= 2;
 
197
    }
 
198
  if (len && !r(d, pos, buf, 1))
 
199
    return 0;
 
200
  return 1;
 
201
}
 
202
 
 
203
int
 
204
pci_generic_block_read(struct pci_dev *d, int pos, byte *buf, int len)
 
205
{
 
206
  return pci_generic_block_op(d, pos, buf, len, d->access->methods->read);
 
207
}
 
208
 
 
209
int
 
210
pci_generic_block_write(struct pci_dev *d, int pos, byte *buf, int len)
 
211
{
 
212
  return pci_generic_block_op(d, pos, buf, len, d->access->methods->write);
 
213
}