Deleted Added
full compact
pci_bus.c (10710) pci_bus.c (10735)
1/**************************************************************************
2**
1/**************************************************************************
2**
3** $Id: pcibus.c,v 1.10 1995/06/30 16:11:42 se Exp $
3** $Id: pcibus.c,v 1.11 1995/09/13 17:03:47 se Exp $
4**
5** pci bus subroutines for i386 architecture.
6**
7** FreeBSD
8**
9**-------------------------------------------------------------------------
10**
11** Copyright (c) 1994 Wolfgang Stanglmeier. All rights reserved.
12**
13** Redistribution and use in source and binary forms, with or without
14** modification, are permitted provided that the following conditions
15** are met:
16** 1. Redistributions of source code must retain the above copyright
17** notice, this list of conditions and the following disclaimer.
18** 2. Redistributions in binary form must reproduce the above copyright
19** notice, this list of conditions and the following disclaimer in the
20** documentation and/or other materials provided with the distribution.
21** 3. The name of the author may not be used to endorse or promote products
22** derived from this software without specific prior written permission.
23**
24** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
25** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
26** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
27** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
28** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
29** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
30** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
31** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
33** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34**
35***************************************************************************
36*/
37
38#define __PCIBUS_C___ "pl4 95/03/21"
39
40#include <sys/param.h>
41#include <sys/systm.h>
42#include <sys/kernel.h>
43
44#include <i386/isa/icu.h>
45#include <i386/isa/isa.h>
46#include <i386/isa/isa_device.h>
47
48#include <pci/pcivar.h>
49#include <pci/pcireg.h>
50#include <pci/pcibus.h>
51
52/*-----------------------------------------------------------------
53**
54** The following functions are provided by the pci bios.
55** They are used only by the pci configuration.
56**
57** pcibus_setup():
58** Probes for a pci system.
59** Sets pci_maxdevice and pci_mechanism.
60**
61** pcibus_tag():
62** Creates a handle for pci configuration space access.
63** This handle is given to the read/write functions.
64**
65** pcibus_ftag():
66** Creates a modified handle.
67**
68** pcibus_read():
69** Read a long word from the pci configuration space.
70** Requires a tag (from pcitag) and the register
71** number (should be a long word alligned one).
72**
73** pcibus_write():
74** Writes a long word to the pci configuration space.
75** Requires a tag (from pcitag), the register number
76** (should be a long word alligned one), and a value.
77**
78** pcibus_regirq():
79** Register an interupt handler for a pci device.
80** Requires a tag (from pcitag), the register number
81** (should be a long word alligned one), and a value.
82**
83**-----------------------------------------------------------------
84*/
85
4**
5** pci bus subroutines for i386 architecture.
6**
7** FreeBSD
8**
9**-------------------------------------------------------------------------
10**
11** Copyright (c) 1994 Wolfgang Stanglmeier. All rights reserved.
12**
13** Redistribution and use in source and binary forms, with or without
14** modification, are permitted provided that the following conditions
15** are met:
16** 1. Redistributions of source code must retain the above copyright
17** notice, this list of conditions and the following disclaimer.
18** 2. Redistributions in binary form must reproduce the above copyright
19** notice, this list of conditions and the following disclaimer in the
20** documentation and/or other materials provided with the distribution.
21** 3. The name of the author may not be used to endorse or promote products
22** derived from this software without specific prior written permission.
23**
24** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
25** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
26** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
27** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
28** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
29** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
30** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
31** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
33** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34**
35***************************************************************************
36*/
37
38#define __PCIBUS_C___ "pl4 95/03/21"
39
40#include <sys/param.h>
41#include <sys/systm.h>
42#include <sys/kernel.h>
43
44#include <i386/isa/icu.h>
45#include <i386/isa/isa.h>
46#include <i386/isa/isa_device.h>
47
48#include <pci/pcivar.h>
49#include <pci/pcireg.h>
50#include <pci/pcibus.h>
51
52/*-----------------------------------------------------------------
53**
54** The following functions are provided by the pci bios.
55** They are used only by the pci configuration.
56**
57** pcibus_setup():
58** Probes for a pci system.
59** Sets pci_maxdevice and pci_mechanism.
60**
61** pcibus_tag():
62** Creates a handle for pci configuration space access.
63** This handle is given to the read/write functions.
64**
65** pcibus_ftag():
66** Creates a modified handle.
67**
68** pcibus_read():
69** Read a long word from the pci configuration space.
70** Requires a tag (from pcitag) and the register
71** number (should be a long word alligned one).
72**
73** pcibus_write():
74** Writes a long word to the pci configuration space.
75** Requires a tag (from pcitag), the register number
76** (should be a long word alligned one), and a value.
77**
78** pcibus_regirq():
79** Register an interupt handler for a pci device.
80** Requires a tag (from pcitag), the register number
81** (should be a long word alligned one), and a value.
82**
83**-----------------------------------------------------------------
84*/
85
86static int
87pcibus_check (void);
88
86static void
87pcibus_setup (void);
88
89static pcici_t
90pcibus_tag (u_char bus, u_char device, u_char func);
91
92static pcici_t
93pcibus_ftag (pcici_t tag, u_char func);
94
95static u_long
96pcibus_read (pcici_t tag, u_long reg);
97
98static void
99pcibus_write (pcici_t tag, u_long reg, u_long data);
100
101static int
102pcibus_ihandler_attach (int irq, void(*ihandler)(), int arg, unsigned* maskp);
103
104static int
105pcibus_ihandler_detach (int irq, void(*handler)());
106
107static int
108pcibus_imask_include (int irq, unsigned* maskptr);
109
110static int
111pcibus_imask_exclude (int irq, unsigned* maskptr);
112
113struct pcibus i386pci = {
114 "pci",
115 pcibus_setup,
116 pcibus_tag,
117 pcibus_ftag,
118 pcibus_read,
119 pcibus_write,
120 ICU_LEN,
121 pcibus_ihandler_attach,
122 pcibus_ihandler_detach,
123 pcibus_imask_include,
124 pcibus_imask_exclude,
125};
126
127/*
128** Announce structure to generic driver
129*/
130
131DATA_SET (pcibus_set, i386pci);
132
133/*--------------------------------------------------------------------
134**
135** Determine configuration mode
136**
137**--------------------------------------------------------------------
138*/
139
140
141#define CONF1_ENABLE 0x80000000ul
142#define CONF1_ENABLE_CHK1 0xF0000000ul
143#define CONF1_ENABLE_CHK2 0xfffffffful
144#define CONF1_ENABLE_RES2 0x80fffffcul
145#define CONF1_ADDR_PORT 0x0cf8
146#define CONF1_DATA_PORT 0x0cfc
147
148
149#define CONF2_ENABLE_PORT 0x0cf8
150#define CONF2_FORWARD_PORT 0x0cfa
151
152
89static void
90pcibus_setup (void);
91
92static pcici_t
93pcibus_tag (u_char bus, u_char device, u_char func);
94
95static pcici_t
96pcibus_ftag (pcici_t tag, u_char func);
97
98static u_long
99pcibus_read (pcici_t tag, u_long reg);
100
101static void
102pcibus_write (pcici_t tag, u_long reg, u_long data);
103
104static int
105pcibus_ihandler_attach (int irq, void(*ihandler)(), int arg, unsigned* maskp);
106
107static int
108pcibus_ihandler_detach (int irq, void(*handler)());
109
110static int
111pcibus_imask_include (int irq, unsigned* maskptr);
112
113static int
114pcibus_imask_exclude (int irq, unsigned* maskptr);
115
116struct pcibus i386pci = {
117 "pci",
118 pcibus_setup,
119 pcibus_tag,
120 pcibus_ftag,
121 pcibus_read,
122 pcibus_write,
123 ICU_LEN,
124 pcibus_ihandler_attach,
125 pcibus_ihandler_detach,
126 pcibus_imask_include,
127 pcibus_imask_exclude,
128};
129
130/*
131** Announce structure to generic driver
132*/
133
134DATA_SET (pcibus_set, i386pci);
135
136/*--------------------------------------------------------------------
137**
138** Determine configuration mode
139**
140**--------------------------------------------------------------------
141*/
142
143
144#define CONF1_ENABLE 0x80000000ul
145#define CONF1_ENABLE_CHK1 0xF0000000ul
146#define CONF1_ENABLE_CHK2 0xfffffffful
147#define CONF1_ENABLE_RES2 0x80fffffcul
148#define CONF1_ADDR_PORT 0x0cf8
149#define CONF1_DATA_PORT 0x0cfc
150
151
152#define CONF2_ENABLE_PORT 0x0cf8
153#define CONF2_FORWARD_PORT 0x0cfa
154
155
156static int
157pcibus_check (void)
158{
159 u_char device;
160
161 for (device = 0; device < pci_maxdevice; device++) {
162 if (pcibus_read (pcibus_tag (0,device,0), 0) != 0xfffffffful)
163 return 1;
164 }
165 return 0;
166}
167
153static void
154pcibus_setup (void)
155{
156 u_long result, oldval;
157
158 /*---------------------------------------
159 ** Configuration mode 1 ?
160 **---------------------------------------
161 */
162
163 oldval = inl (CONF1_ADDR_PORT);
164 outl (CONF1_ADDR_PORT, CONF1_ENABLE_CHK1);
165 outb (CONF1_ADDR_PORT +3, 0);
166 result = inl (CONF1_ADDR_PORT);
167 outl (CONF1_ADDR_PORT, oldval);
168
169 if (result & CONF1_ENABLE) {
170 pci_mechanism = 1;
171 pci_maxdevice = 32;
168static void
169pcibus_setup (void)
170{
171 u_long result, oldval;
172
173 /*---------------------------------------
174 ** Configuration mode 1 ?
175 **---------------------------------------
176 */
177
178 oldval = inl (CONF1_ADDR_PORT);
179 outl (CONF1_ADDR_PORT, CONF1_ENABLE_CHK1);
180 outb (CONF1_ADDR_PORT +3, 0);
181 result = inl (CONF1_ADDR_PORT);
182 outl (CONF1_ADDR_PORT, oldval);
183
184 if (result & CONF1_ENABLE) {
185 pci_mechanism = 1;
186 pci_maxdevice = 32;
172 if (pcibus_read (pcibus_tag (0,0,0), 0) != 0xfffffffful)
187 if (pcibus_check())
173 return;
174 };
175
176 /*---------------------------------------
177 ** Configuration mode 2 ?
178 **---------------------------------------
179 */
180
181 outb (CONF2_ENABLE_PORT, 0);
182 outb (CONF2_FORWARD_PORT, 0);
183 if (!inb (CONF2_ENABLE_PORT) && !inb (CONF2_FORWARD_PORT)) {
184 pci_mechanism = 2;
185 pci_maxdevice = 16;
188 return;
189 };
190
191 /*---------------------------------------
192 ** Configuration mode 2 ?
193 **---------------------------------------
194 */
195
196 outb (CONF2_ENABLE_PORT, 0);
197 outb (CONF2_FORWARD_PORT, 0);
198 if (!inb (CONF2_ENABLE_PORT) && !inb (CONF2_FORWARD_PORT)) {
199 pci_mechanism = 2;
200 pci_maxdevice = 16;
186 if (pcibus_read (pcibus_tag (0,0,0), 0) != 0xfffffffful)
201 if (pcibus_check())
187 return;
188 };
189
190
191 /*-----------------------------------------------------
192 ** Well, is it Configuration mode 1, after all ?
193 **-----------------------------------------------------
194 */
195
196 oldval = inl (CONF1_ADDR_PORT);
197 outl (CONF1_ADDR_PORT, CONF1_ENABLE_CHK2);
198 result = inl (CONF1_ADDR_PORT);
199 outl (CONF1_ADDR_PORT, oldval);
200
201 if (result == CONF1_ENABLE_RES2) {
202 pci_mechanism = 1;
203 pci_maxdevice = 32;
202 return;
203 };
204
205
206 /*-----------------------------------------------------
207 ** Well, is it Configuration mode 1, after all ?
208 **-----------------------------------------------------
209 */
210
211 oldval = inl (CONF1_ADDR_PORT);
212 outl (CONF1_ADDR_PORT, CONF1_ENABLE_CHK2);
213 result = inl (CONF1_ADDR_PORT);
214 outl (CONF1_ADDR_PORT, oldval);
215
216 if (result == CONF1_ENABLE_RES2) {
217 pci_mechanism = 1;
218 pci_maxdevice = 32;
204 if (pcibus_read (pcibus_tag (0,0,0), 0) != 0xfffffffful)
219 if (pcibus_check())
205 return;
206 }
207 if (result != 0xfffffffful)
208 printf ("pcibus_setup: "
209 "wrote 0x%08x, read back 0x%08x, expected 0x%08x\n",
210 CONF1_ENABLE_CHK2, result, CONF1_ENABLE_RES2);
211
212 /*---------------------------------------
213 ** No PCI bus host bridge found
214 **---------------------------------------
215 */
216
217 pci_mechanism = 0;
218 pci_maxdevice = 0;
219}
220
221/*--------------------------------------------------------------------
222**
223** Build a pcitag from bus, device and function number
224**
225**--------------------------------------------------------------------
226*/
227
228static pcici_t
229pcibus_tag (unsigned char bus, unsigned char device, unsigned char func)
230{
231 pcici_t tag;
232
233 tag.cfg1 = 0;
234 if (device >= 32) return tag;
235 if (func >= 8) return tag;
236
237 switch (pci_mechanism) {
238
239 case 1:
240 tag.cfg1 = CONF1_ENABLE
241 | (((u_long) bus ) << 16ul)
242 | (((u_long) device) << 11ul)
243 | (((u_long) func ) << 8ul);
244 break;
245 case 2:
246 if (device >= 16) break;
247 tag.cfg2.port = 0xc000 | (device << 8ul);
248 tag.cfg2.enable = 0xf1 | (func << 1ul);
249 tag.cfg2.forward = bus;
250 break;
251 };
252 return tag;
253}
254
255static pcici_t
256pcibus_ftag (pcici_t tag, u_char func)
257{
258 switch (pci_mechanism) {
259
260 case 1:
261 tag.cfg1 &= ~0x700ul;
262 tag.cfg1 |= (((u_long) func) << 8ul);
263 break;
264 case 2:
265 tag.cfg2.enable = 0xf1 | (func << 1ul);
266 break;
267 };
268 return tag;
269}
270
271/*--------------------------------------------------------------------
272**
273** Read register from configuration space.
274**
275**--------------------------------------------------------------------
276*/
277
278static u_long
279pcibus_read (pcici_t tag, u_long reg)
280{
281 u_long addr, data = 0;
282
283 if (!tag.cfg1) return (0xfffffffful);
284
285 switch (pci_mechanism) {
286
287 case 1:
288 addr = tag.cfg1 | (reg & 0xfc);
289#ifdef PCI_DEBUG
290 printf ("pci_conf_read(1): addr=%x ", addr);
291#endif
292 outl (CONF1_ADDR_PORT, addr);
293 data = inl (CONF1_DATA_PORT);
294 outl (CONF1_ADDR_PORT, 0 );
295 break;
296
297 case 2:
298 addr = tag.cfg2.port | (reg & 0xfc);
299#ifdef PCI_DEBUG
300 printf ("pci_conf_read(2): addr=%x ", addr);
301#endif
302 outb (CONF2_ENABLE_PORT , tag.cfg2.enable );
303 outb (CONF2_FORWARD_PORT, tag.cfg2.forward);
304
305 data = inl ((u_short) addr);
306
307 outb (CONF2_ENABLE_PORT, 0);
308 outb (CONF2_FORWARD_PORT, 0);
309 break;
310 };
311
312#ifdef PCI_DEBUG
313 printf ("data=%x\n", data);
314#endif
315
316 return (data);
317}
318
319/*--------------------------------------------------------------------
320**
321** Write register into configuration space.
322**
323**--------------------------------------------------------------------
324*/
325
326static void
327pcibus_write (pcici_t tag, u_long reg, u_long data)
328{
329 u_long addr;
330
331 if (!tag.cfg1) return;
332
333 switch (pci_mechanism) {
334
335 case 1:
336 addr = tag.cfg1 | (reg & 0xfc);
337#ifdef PCI_DEBUG
338 printf ("pci_conf_write(1): addr=%x data=%x\n",
339 addr, data);
340#endif
341 outl (CONF1_ADDR_PORT, addr);
342 outl (CONF1_DATA_PORT, data);
343 outl (CONF1_ADDR_PORT, 0 );
344 break;
345
346 case 2:
347 addr = tag.cfg2.port | (reg & 0xfc);
348#ifdef PCI_DEBUG
349 printf ("pci_conf_write(2): addr=%x data=%x\n",
350 addr, data);
351#endif
352 outb (CONF2_ENABLE_PORT, tag.cfg2.enable);
353 outb (CONF2_FORWARD_PORT, tag.cfg2.forward);
354
355 outl ((u_short) addr, data);
356
357 outb (CONF2_ENABLE_PORT, 0);
358 outb (CONF2_FORWARD_PORT, 0);
359 break;
360 };
361}
362
363/*-----------------------------------------------------------------------
364**
365** Register an interupt handler for a pci device.
366**
367**-----------------------------------------------------------------------
368*/
369
370static int
371pcibus_ihandler_attach (int irq, void(*func)(), int arg, unsigned * maskptr)
372{
373 int result;
374 result = register_intr(
375 irq, /* isa irq */
376 0, /* deviced?? */
377 0, /* flags? */
378 (inthand2_t*) func, /* handler */
379 maskptr, /* mask pointer */
380 arg); /* handler arg */
381
382 if (result) {
383 printf ("@@@ pcibus_ihandler_attach: result=%d\n", result);
384 return (result);
385 };
386 update_intr_masks();
387
388 INTREN ((1ul<<irq));
389 return (0);
390}
391
392static int
393pcibus_ihandler_detach (int irq, void(*func)())
394{
395 int result;
396
397 INTRDIS ((1ul<<irq));
398
399 result = unregister_intr (irq, (inthand2_t*) func);
400
401 if (result)
402 printf ("@@@ pcibus_ihandler_detach: result=%d\n", result);
403
404 update_intr_masks();
405
406 return (result);
407}
408
409static int
410pcibus_imask_include (int irq, unsigned* maskptr)
411{
412 unsigned mask;
413
414 if (!maskptr) return (0);
415
416 mask = 1ul << irq;
417
418 if (*maskptr & mask)
419 return (-1);
420
421 INTRMASK (*maskptr, mask);
422 update_intr_masks();
423
424 return (0);
425}
426
427static int
428pcibus_imask_exclude (int irq, unsigned* maskptr)
429{
430 unsigned mask;
431
432 if (!maskptr) return (0);
433
434 mask = 1ul << irq;
435
436 if (! (*maskptr & mask))
437 return (-1);
438
439 *maskptr &= ~mask;
440 update_intr_masks();
441
442 return (0);
443}
220 return;
221 }
222 if (result != 0xfffffffful)
223 printf ("pcibus_setup: "
224 "wrote 0x%08x, read back 0x%08x, expected 0x%08x\n",
225 CONF1_ENABLE_CHK2, result, CONF1_ENABLE_RES2);
226
227 /*---------------------------------------
228 ** No PCI bus host bridge found
229 **---------------------------------------
230 */
231
232 pci_mechanism = 0;
233 pci_maxdevice = 0;
234}
235
236/*--------------------------------------------------------------------
237**
238** Build a pcitag from bus, device and function number
239**
240**--------------------------------------------------------------------
241*/
242
243static pcici_t
244pcibus_tag (unsigned char bus, unsigned char device, unsigned char func)
245{
246 pcici_t tag;
247
248 tag.cfg1 = 0;
249 if (device >= 32) return tag;
250 if (func >= 8) return tag;
251
252 switch (pci_mechanism) {
253
254 case 1:
255 tag.cfg1 = CONF1_ENABLE
256 | (((u_long) bus ) << 16ul)
257 | (((u_long) device) << 11ul)
258 | (((u_long) func ) << 8ul);
259 break;
260 case 2:
261 if (device >= 16) break;
262 tag.cfg2.port = 0xc000 | (device << 8ul);
263 tag.cfg2.enable = 0xf1 | (func << 1ul);
264 tag.cfg2.forward = bus;
265 break;
266 };
267 return tag;
268}
269
270static pcici_t
271pcibus_ftag (pcici_t tag, u_char func)
272{
273 switch (pci_mechanism) {
274
275 case 1:
276 tag.cfg1 &= ~0x700ul;
277 tag.cfg1 |= (((u_long) func) << 8ul);
278 break;
279 case 2:
280 tag.cfg2.enable = 0xf1 | (func << 1ul);
281 break;
282 };
283 return tag;
284}
285
286/*--------------------------------------------------------------------
287**
288** Read register from configuration space.
289**
290**--------------------------------------------------------------------
291*/
292
293static u_long
294pcibus_read (pcici_t tag, u_long reg)
295{
296 u_long addr, data = 0;
297
298 if (!tag.cfg1) return (0xfffffffful);
299
300 switch (pci_mechanism) {
301
302 case 1:
303 addr = tag.cfg1 | (reg & 0xfc);
304#ifdef PCI_DEBUG
305 printf ("pci_conf_read(1): addr=%x ", addr);
306#endif
307 outl (CONF1_ADDR_PORT, addr);
308 data = inl (CONF1_DATA_PORT);
309 outl (CONF1_ADDR_PORT, 0 );
310 break;
311
312 case 2:
313 addr = tag.cfg2.port | (reg & 0xfc);
314#ifdef PCI_DEBUG
315 printf ("pci_conf_read(2): addr=%x ", addr);
316#endif
317 outb (CONF2_ENABLE_PORT , tag.cfg2.enable );
318 outb (CONF2_FORWARD_PORT, tag.cfg2.forward);
319
320 data = inl ((u_short) addr);
321
322 outb (CONF2_ENABLE_PORT, 0);
323 outb (CONF2_FORWARD_PORT, 0);
324 break;
325 };
326
327#ifdef PCI_DEBUG
328 printf ("data=%x\n", data);
329#endif
330
331 return (data);
332}
333
334/*--------------------------------------------------------------------
335**
336** Write register into configuration space.
337**
338**--------------------------------------------------------------------
339*/
340
341static void
342pcibus_write (pcici_t tag, u_long reg, u_long data)
343{
344 u_long addr;
345
346 if (!tag.cfg1) return;
347
348 switch (pci_mechanism) {
349
350 case 1:
351 addr = tag.cfg1 | (reg & 0xfc);
352#ifdef PCI_DEBUG
353 printf ("pci_conf_write(1): addr=%x data=%x\n",
354 addr, data);
355#endif
356 outl (CONF1_ADDR_PORT, addr);
357 outl (CONF1_DATA_PORT, data);
358 outl (CONF1_ADDR_PORT, 0 );
359 break;
360
361 case 2:
362 addr = tag.cfg2.port | (reg & 0xfc);
363#ifdef PCI_DEBUG
364 printf ("pci_conf_write(2): addr=%x data=%x\n",
365 addr, data);
366#endif
367 outb (CONF2_ENABLE_PORT, tag.cfg2.enable);
368 outb (CONF2_FORWARD_PORT, tag.cfg2.forward);
369
370 outl ((u_short) addr, data);
371
372 outb (CONF2_ENABLE_PORT, 0);
373 outb (CONF2_FORWARD_PORT, 0);
374 break;
375 };
376}
377
378/*-----------------------------------------------------------------------
379**
380** Register an interupt handler for a pci device.
381**
382**-----------------------------------------------------------------------
383*/
384
385static int
386pcibus_ihandler_attach (int irq, void(*func)(), int arg, unsigned * maskptr)
387{
388 int result;
389 result = register_intr(
390 irq, /* isa irq */
391 0, /* deviced?? */
392 0, /* flags? */
393 (inthand2_t*) func, /* handler */
394 maskptr, /* mask pointer */
395 arg); /* handler arg */
396
397 if (result) {
398 printf ("@@@ pcibus_ihandler_attach: result=%d\n", result);
399 return (result);
400 };
401 update_intr_masks();
402
403 INTREN ((1ul<<irq));
404 return (0);
405}
406
407static int
408pcibus_ihandler_detach (int irq, void(*func)())
409{
410 int result;
411
412 INTRDIS ((1ul<<irq));
413
414 result = unregister_intr (irq, (inthand2_t*) func);
415
416 if (result)
417 printf ("@@@ pcibus_ihandler_detach: result=%d\n", result);
418
419 update_intr_masks();
420
421 return (result);
422}
423
424static int
425pcibus_imask_include (int irq, unsigned* maskptr)
426{
427 unsigned mask;
428
429 if (!maskptr) return (0);
430
431 mask = 1ul << irq;
432
433 if (*maskptr & mask)
434 return (-1);
435
436 INTRMASK (*maskptr, mask);
437 update_intr_masks();
438
439 return (0);
440}
441
442static int
443pcibus_imask_exclude (int irq, unsigned* maskptr)
444{
445 unsigned mask;
446
447 if (!maskptr) return (0);
448
449 mask = 1ul << irq;
450
451 if (! (*maskptr & mask))
452 return (-1);
453
454 *maskptr &= ~mask;
455 update_intr_masks();
456
457 return (0);
458}