Subversion Repositories HelenOS

Rev

Rev 1301 | Rev 1324 | Go to most recent revision | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

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