OpenCores
URL https://opencores.org/ocsvn/openrisc_me/openrisc_me/trunk

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [rtos/] [rtems/] [c/] [src/] [lib/] [libbsp/] [powerpc/] [ppcn_60x/] [pci/] [pci.c] - Blame information for rev 173

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 30 unneback
/*
2
 *  COPYRIGHT (c) 1998 by Radstone Technology
3
 *
4
 *
5
 * THIS FILE IS PROVIDED TO YOU, THE USER, "AS IS", WITHOUT WARRANTY OF ANY
6
 * KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
7
 * IMPLIED WARRANTY OF FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK
8
 * AS TO THE QUALITY AND PERFORMANCE OF ALL CODE IN THIS FILE IS WITH YOU.
9
 *
10
 * You are hereby granted permission to use, copy, modify, and distribute
11
 * this file, provided that this notice, plus the above copyright notice
12
 * and disclaimer, appears in all copies. Radstone Technology will provide
13
 * no support for this code.
14
 *
15
 */
16
#include <bsp.h>
17
#include <pci.h>
18
 
19
/* SCE 97/4/9
20
 *
21
 * Use PCI configuration space access mechanism 1
22
 *
23
 * This is the preferred access mechanism and must be used when accessing
24
 * bridged PCI busses.
25
 *
26
 * The address to be written to the PCI_CONFIG_ADDRESS port is constructed
27
 * thus (the representation below is little endian):
28
 *
29
 *  31  30   24 23        16 15        11 10        8 7          2 1   0
30
 *  ----------------------------------------------------------------------
31
 * | 1 | Resvd | Bus Number | Dev Number | Fn Number | Reg Number | 0 | 0 |
32
 *  ----------------------------------------------------------------------
33
 *
34
 * On bus 0, the first 'real' device is at Device number 11, the Eagle being
35
 * device 0. On all other busses, device numbering starts at 0.
36
 */
37
/*
38
 * Normal PCI device numbering on busses other than 0 is such that
39
 * that the first device (0) is attached to AD16, second (1) to AD17 etc.
40
 */
41
#define CONFIG_ADDRESS(Bus, Device, Function, Offset) \
42
    (0x80000000 | (Bus<<16) | \
43
    ((Device+(((Bus==0)&&(Device>0)) ? 10 : 0))<<11) | \
44
    (Function<<8) | \
45
    (Offset&~0x03))
46
#define BYTE_LANE_OFFSET(Offset) ((Offset)&0x3)
47
 
48
/*
49
 * Private data
50
 */
51
static unsigned8 ucMaxPCIBus;
52
 
53
/*
54
 * Public routines
55
 */
56
rtems_status_code PCIConfigWrite8(
57
        unsigned8 ucBusNumber,
58
        unsigned8 ucSlotNumber,
59
        unsigned8 ucFunctionNumber,
60
        unsigned8 ucOffset,
61
        unsigned8 ucValue
62
)
63
{
64
        ISR_Level Irql;
65
 
66
        /*
67
         * Ensure that accesses to the addr/data ports are indivisible
68
         */
69
        _ISR_Disable(Irql);
70
 
71
        /*
72
         * Write to the configuration space address register
73
         */
74
        outport_32(PCI_CONFIG_ADDR,
75
                   CONFIG_ADDRESS(ucBusNumber, ucSlotNumber,
76
                                  ucFunctionNumber, ucOffset));
77
        /*
78
         * Write to the configuration space data register with the appropriate
79
         * offset
80
         */
81
        outport_byte(PCI_CONFIG_DATA+BYTE_LANE_OFFSET(ucOffset), ucValue);
82
 
83
         _ISR_Enable(Irql);
84
 
85
        return(RTEMS_SUCCESSFUL);
86
}
87
 
88
rtems_status_code PCIConfigWrite16(
89
        unsigned8 ucBusNumber,
90
        unsigned8 ucSlotNumber,
91
        unsigned8 ucFunctionNumber,
92
        unsigned8 ucOffset,
93
        unsigned16 usValue
94
)
95
{
96
        ISR_Level Irql;
97
 
98
        /*
99
         * Ensure that accesses to the addr/data ports are indivisible
100
         */
101
        _ISR_Disable(Irql);
102
 
103
        /*
104
         * Write to the configuration space address register
105
         */
106
        outport_32(PCI_CONFIG_ADDR,
107
                   CONFIG_ADDRESS(ucBusNumber, ucSlotNumber,
108
                                  ucFunctionNumber, ucOffset));
109
        /*
110
         * Write to the configuration space data register with the appropriate
111
         * offset
112
         */
113
        outport_16(PCI_CONFIG_DATA+BYTE_LANE_OFFSET(ucOffset), usValue);
114
 
115
        _ISR_Enable(Irql);
116
 
117
        return(RTEMS_SUCCESSFUL);
118
}
119
 
120
rtems_status_code PCIConfigWrite32(
121
        unsigned8 ucBusNumber,
122
        unsigned8 ucSlotNumber,
123
        unsigned8 ucFunctionNumber,
124
        unsigned8 ucOffset,
125
        unsigned32 ulValue
126
)
127
{
128
        ISR_Level Irql;
129
 
130
        /*
131
         * Ensure that accesses to the addr/data ports are indivisible
132
         */
133
        _ISR_Disable(Irql);
134
 
135
        /*
136
         * Write to the configuration space address register
137
         */
138
        outport_32(PCI_CONFIG_ADDR,
139
                   CONFIG_ADDRESS(ucBusNumber, ucSlotNumber,
140
                                  ucFunctionNumber, ucOffset));
141
        /*
142
         * Write to the configuration space data register with the appropriate
143
         * offset
144
         */
145
        outport_32(PCI_CONFIG_DATA, ulValue);
146
 
147
        _ISR_Enable(Irql);
148
 
149
        return(RTEMS_SUCCESSFUL);
150
}
151
 
152
rtems_status_code PCIConfigRead8(
153
        unsigned8 ucBusNumber,
154
        unsigned8 ucSlotNumber,
155
        unsigned8 ucFunctionNumber,
156
        unsigned8 ucOffset,
157
        unsigned8 *pucValue
158
)
159
{
160
        ISR_Level Irql;
161
 
162
        /*
163
         * Ensure that accesses to the addr/data ports are indivisible
164
         */
165
        _ISR_Disable(Irql);
166
 
167
        /*
168
         * Write to the configuration space address register
169
         */
170
        outport_32(PCI_CONFIG_ADDR,
171
                   CONFIG_ADDRESS(ucBusNumber, ucSlotNumber,
172
                                  ucFunctionNumber, ucOffset));
173
        /*
174
         * Read from the configuration space data register with the appropriate
175
         * offset
176
         */
177
        inport_byte(PCI_CONFIG_DATA+BYTE_LANE_OFFSET(ucOffset), *pucValue);
178
 
179
        _ISR_Enable(Irql);
180
 
181
        return(RTEMS_SUCCESSFUL);
182
}
183
 
184
rtems_status_code PCIConfigRead16(
185
        unsigned8 ucBusNumber,
186
        unsigned8 ucSlotNumber,
187
        unsigned8 ucFunctionNumber,
188
        unsigned8 ucOffset,
189
        unsigned16 *pusValue
190
)
191
{
192
        ISR_Level Irql;
193
 
194
        /*
195
         * Ensure that accesses to the addr/data ports are indivisible
196
         */
197
        _ISR_Disable(Irql);
198
 
199
        /*
200
         * Write to the configuration space address register
201
         */
202
        outport_32(PCI_CONFIG_ADDR,
203
                   CONFIG_ADDRESS(ucBusNumber, ucSlotNumber,
204
                                  ucFunctionNumber, ucOffset));
205
        /*
206
         * Read from the configuration space data register with the appropriate
207
         * offset
208
         */
209
        inport_16(PCI_CONFIG_DATA+BYTE_LANE_OFFSET(ucOffset), *pusValue);
210
 
211
        _ISR_Enable(Irql);
212
 
213
        return(RTEMS_SUCCESSFUL);
214
}
215
 
216
rtems_status_code PCIConfigRead32(
217
        unsigned8 ucBusNumber,
218
        unsigned8 ucSlotNumber,
219
        unsigned8 ucFunctionNumber,
220
        unsigned8 ucOffset,
221
        unsigned32 *pulValue
222
)
223
{
224
        ISR_Level Irql;
225
 
226
        /*
227
         * Ensure that accesses to the addr/data ports are indivisible
228
         */
229
        _ISR_Disable(Irql);
230
 
231
        /*
232
         * Write to the configuration space address register
233
         */
234
        outport_32(PCI_CONFIG_ADDR,
235
                   CONFIG_ADDRESS(ucBusNumber, ucSlotNumber,
236
                                  ucFunctionNumber, ucOffset));
237
        /*
238
         * Read from the configuration space data register with the appropriate
239
         * offset
240
         */
241
        inport_32(PCI_CONFIG_DATA, *pulValue);
242
 
243
        _ISR_Enable(Irql);
244
 
245
        return(RTEMS_SUCCESSFUL);
246
}
247
 
248
/*
249
 * This routine determines the maximum bus number in the system
250
 */
251
void InitializePCI()
252
{
253
        unsigned8 ucSlotNumber, ucFnNumber, ucNumFuncs;
254
        unsigned8 ucHeader;
255
        unsigned8 ucBaseClass, ucSubClass, ucMaxSubordinate;
256
        unsigned32 ulDeviceID;
257
 
258
        /*
259
         * Scan PCI bus 0 looking for PCI-PCI bridges
260
         */
261
        for(ucSlotNumber=0;ucSlotNumber<PCI_MAX_DEVICES;ucSlotNumber++)
262
        {
263
                (void)PCIConfigRead32(0,
264
                                      ucSlotNumber,
265
                                      0,
266
                                      PCI_CONFIG_VENDOR_LOW,
267
                                      &ulDeviceID);
268
                if(ulDeviceID==PCI_INVALID_VENDORDEVICEID)
269
                {
270
                        /*
271
                         * This slot is empty
272
                         */
273
                        continue;
274
                }
275
                (void)PCIConfigRead8(0,
276
                                     ucSlotNumber,
277
                                     0,
278
                                     PCI_CONFIG_HEADER_TYPE,
279
                                     &ucHeader);
280
                if(ucHeader&PCI_MULTI_FUNCTION)
281
                {
282
                        ucNumFuncs=PCI_MAX_FUNCTIONS;
283
                }
284
                else
285
                {
286
                        ucNumFuncs=1;
287
                }
288
                for(ucFnNumber=0;ucFnNumber<ucNumFuncs;ucFnNumber++)
289
                {
290
                        (void)PCIConfigRead32(0,
291
                                              ucSlotNumber,
292
                                              ucFnNumber,
293
                                              PCI_CONFIG_VENDOR_LOW,
294
                                              &ulDeviceID);
295
                        if(ulDeviceID==PCI_INVALID_VENDORDEVICEID)
296
                        {
297
                                /*
298
                                 * This slot/function is empty
299
                                 */
300
                                continue;
301
                        }
302
 
303
                        /*
304
                         * This slot/function has a device fitted.
305
                         */
306
                        (void)PCIConfigRead8(0,
307
                                             ucSlotNumber,
308
                                             ucFnNumber,
309
                                             PCI_CONFIG_CLASS_CODE_U,
310
                                             &ucBaseClass);
311
                        (void)PCIConfigRead8(0,
312
                                             ucSlotNumber,
313
                                             ucFnNumber,
314
                                             PCI_CONFIG_CLASS_CODE_M,
315
                                             &ucSubClass);
316
                        if((ucBaseClass==PCI_BASE_CLASS_BRIDGE) &&
317
                           (ucSubClass==PCI_SUB_CLASS_BRIDGE_PCI))
318
                        {
319
                                /*
320
                                 * We have found a PCI-PCI bridge
321
                                 */
322
                                (void)PCIConfigRead8(0,
323
                                                     ucSlotNumber,
324
                                                     ucFnNumber,
325
                                                     PCI_BRIDGE_SUBORDINATE_BUS,
326
                                                     &ucMaxSubordinate);
327
                                if(ucMaxSubordinate>ucMaxPCIBus)
328
                                {
329
                                        ucMaxPCIBus=ucMaxSubordinate;
330
                                }
331
                        }
332
                }
333
        }
334
}
335
 
336
/*
337
 * Return the number of PCI busses in the system
338
 */
339
unsigned8 BusCountPCI()
340
{
341
        return(ucMaxPCIBus+1);
342
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.