Deleted Added
full compact
pci_pir.c (6734) pci_pir.c (7234)
1/**************************************************************************
2**
1/**************************************************************************
2**
3** $Id: pcibus.c,v 1.3 1995/02/25 17:51:18 se Exp $
3** $Id: pcibus.c,v 1.4 1995/02/26 05:14:51 bde Exp $
4**
5** pci bus subroutines for i386 architecture.
6**
7** FreeBSD
8**
9**-------------------------------------------------------------------------
10**
11** Copyright (c) 1994 Wolfgang Stanglmeier. All rights reserved.

--- 18 unchanged lines hidden (view full) ---

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
4**
5** pci bus subroutines for i386 architecture.
6**
7** FreeBSD
8**
9**-------------------------------------------------------------------------
10**
11** Copyright (c) 1994 Wolfgang Stanglmeier. All rights reserved.

--- 18 unchanged lines hidden (view full) ---

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#ifndef __FreeBSD2__
39#if __FreeBSD__ >= 2
40#define __FreeBSD2__
41#endif
42#endif
38#define __PCIBUS_C___ "pl4 95/03/21"
43
39
44#ifdef __FreeBSD2__
45#define HAS_CPUFUNC_H
46#endif
47
48#include <sys/param.h>
49#include <sys/systm.h>
50#include <sys/kernel.h>
51
52#include <i386/isa/icu.h>
53#include <i386/isa/isa.h>
54#include <i386/isa/isa_device.h>
55
56#include <pci/pcivar.h>
57#include <pci/pcireg.h>
58#include <pci/pcibus.h>
59
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
60static char pci_mode;
61
52extern int printf();
53
54#ifdef DENTARO
55
56#define SFAKE (32)
57
58static void
59dec21050 (u_int*reg) {
60 reg[0] = 0x00011011;
61 reg[1]&= 0x000001e7;
62 reg[2] = 0x06040001;
63 reg[3]&= 0x0000f8ff;
64 reg[3]|= 0x000100ff;
65 reg[4] = 0x00000000;
66 reg[5] = 0x00000000;
67 reg[6]&= 0xf8ffffff;
68 reg[7]&= 0x0000f0f0; /* io-limit */
69 reg[8]&= 0xfff0fff0; /* mem-limit, non prefatchable */
70 reg[9]&= 0xfff0fff0; /* mem-limit, prefetchable memory */
71 reg[10] = 0x00000000;
72 reg[11] = 0x00000000;
73 reg[12] = 0x00000000;
74 reg[13] = 0x00000000;
75 reg[14] = 0x00000000;
76 reg[15]&= 0x00ef0000;
77}
78
79static void
80dec21140 (u_int*reg) {
81 reg[0] = 0x00091011u;
82 reg[4]&= 0xfffffffdu;
83 reg[4]|= 0x00000001u;
84 reg[5]&= 0xffffff00u;
85}
86
87struct fake {
88 u_int tag;
89 void (*proc)(u_int*);
90};
91
92struct fake faketable [] = {
93{ 0xc70000f1, dec21050 },
94{ 0xc00001f1, dec21140 },
95{ 0xc40001f1, dec21140 },
96{ 0xc80001f1, dec21140 },
97{ 0xcc0001f1, dec21140 },
98};
99
100#define NFAKE (sizeof faketable / sizeof (struct fake))
101
102static u_int fakedata[NFAKE * SFAKE];
103
104u_int* findfake (pcici_t tag)
105{
106 u_int *p;
107 int i;
108 for (i=0; i<NFAKE; i++)
109 if (faketable[i].tag == tag.tag)
110 break;
111
112 if (i>=NFAKE)
113 return (0);
114 p = &fakedata[i*SFAKE];
115 (*faketable[i].proc)(p);
116 return (p);
117}
118#endif /*DENTARO*/
119
62/*-----------------------------------------------------------------
63**
64** The following functions are provided by the pci bios.
65** They are used only by the pci configuration.
66**
120/*-----------------------------------------------------------------
121**
122** The following functions are provided by the pci bios.
123** They are used only by the pci configuration.
124**
67** pcibus_mode():
125** pcibus_setup():
68** Probes for a pci system.
126** Probes for a pci system.
69** Returns 1 or 2 for pci configuration mechanism.
70** Returns 0 if no pci system.
127** Sets pci_maxdevice and pci_mechanism.
71**
72** pcibus_tag():
128**
129** pcibus_tag():
73** Gets a handle for accessing the pci configuration
74** space.
75** This handle is given to the mapping functions (see
76** above) or to the read/write functions.
130** Creates a handle for pci configuration space access.
131** This handle is given to the read/write functions.
77**
132**
133** pcibus_ftag():
134** Creates a modified handle.
135**
78** pcibus_read():
79** Read a long word from the pci configuration space.
80** Requires a tag (from pcitag) and the register
81** number (should be a long word alligned one).
82**
83** pcibus_write():
84** Writes a long word to the pci configuration space.
85** Requires a tag (from pcitag), the register number
86** (should be a long word alligned one), and a value.
87**
88** pcibus_regirq():
89** Register an interupt handler for a pci device.
90** Requires a tag (from pcitag), the register number
91** (should be a long word alligned one), and a value.
92**
93**-----------------------------------------------------------------
94*/
95
136** pcibus_read():
137** Read a long word from the pci configuration space.
138** Requires a tag (from pcitag) and the register
139** number (should be a long word alligned one).
140**
141** pcibus_write():
142** Writes a long word to the pci configuration space.
143** Requires a tag (from pcitag), the register number
144** (should be a long word alligned one), and a value.
145**
146** pcibus_regirq():
147** Register an interupt handler for a pci device.
148** Requires a tag (from pcitag), the register number
149** (should be a long word alligned one), and a value.
150**
151**-----------------------------------------------------------------
152*/
153
96static int
97pcibus_mode (void);
154static void
155pcibus_setup (void);
98
99static pcici_t
100pcibus_tag (u_char bus, u_char device, u_char func);
101
156
157static pcici_t
158pcibus_tag (u_char bus, u_char device, u_char func);
159
160static pcici_t
161pcibus_ftag (pcici_t tag, u_char func);
162
102static u_long
103pcibus_read (pcici_t tag, u_long reg);
104
105static void
106pcibus_write (pcici_t tag, u_long reg, u_long data);
107
108static int
163static u_long
164pcibus_read (pcici_t tag, u_long reg);
165
166static void
167pcibus_write (pcici_t tag, u_long reg, u_long data);
168
169static int
109pcibus_regint (pcici_t tag, int(*func)(), void* arg, unsigned* maskptr);
170pcibus_ihandler_attach (int irq, void(*ihandler)(), int arg, unsigned* maskp);
110
171
172static int
173pcibus_ihandler_detach (int irq, void(*handler)());
174
175static int
176pcibus_imask_include (int irq, unsigned* maskptr);
177
178static int
179pcibus_imask_exclude (int irq, unsigned* maskptr);
180
111struct pcibus i386pci = {
112 "pci",
181struct pcibus i386pci = {
182 "pci",
113 pcibus_mode,
183 pcibus_setup,
114 pcibus_tag,
184 pcibus_tag,
185 pcibus_ftag,
115 pcibus_read,
116 pcibus_write,
186 pcibus_read,
187 pcibus_write,
117 pcibus_regint,
188 ICU_LEN,
189 pcibus_ihandler_attach,
190 pcibus_ihandler_detach,
191 pcibus_imask_include,
192 pcibus_imask_exclude,
118};
119
120/*
121** Announce structure to generic driver
122*/
123
124DATA_SET (pcibus_set, i386pci);
193};
194
195/*
196** Announce structure to generic driver
197*/
198
199DATA_SET (pcibus_set, i386pci);
125
126/*--------------------------------------------------------------------
127**
128** Port access
129**
130**--------------------------------------------------------------------
131*/
132
200
133#ifndef HAS_CPUFUNC_H
134
135#undef inl
136#define inl(port) \
137({ u_long data; \
138 __asm __volatile("inl %1, %0": "=a" (data): "d" ((u_short)(port))); \
139 data; })
140
141
142#undef outl
143#define outl(port, data) \
144{__asm __volatile("outl %0, %1"::"a" ((u_long)(data)), "d" ((u_short)(port)));}
145
146
147#undef inb
148#define inb(port) \
149({ u_char data; \
150 __asm __volatile("inb %1, %0": "=a" (data): "d" ((u_short)(port))); \
151 data; })
152
153
154#undef outb
155#define outb(port, data) \
156{__asm __volatile("outb %0, %1"::"a" ((u_char)(data)), "d" ((u_short)(port)));}
157
158#endif /* HAS_CPUFUNC_H */
159
160/*--------------------------------------------------------------------
161**
162** Determine configuration mode
163**
164**--------------------------------------------------------------------
165*/
166
167
168#define CONF1_ENABLE 0x80000000ul
169#define CONF1_ADDR_PORT 0x0cf8
170#define CONF1_DATA_PORT 0x0cfc
171
172
173#define CONF2_ENABLE_PORT 0x0cf8
174#define CONF2_FORWARD_PORT 0x0cfa
175
176
201/*--------------------------------------------------------------------
202**
203** Determine configuration mode
204**
205**--------------------------------------------------------------------
206*/
207
208
209#define CONF1_ENABLE 0x80000000ul
210#define CONF1_ADDR_PORT 0x0cf8
211#define CONF1_DATA_PORT 0x0cfc
212
213
214#define CONF2_ENABLE_PORT 0x0cf8
215#define CONF2_FORWARD_PORT 0x0cfa
216
217
177static int
178pcibus_mode (void)
218static void
219pcibus_setup (void)
179{
220{
180#ifdef PCI_CONF_MODE
181 pci_mode = PCI_CONF_MODE;
182 return (PCI_CONF_MODE)
183#else /* PCI_CONF_MODE */
184 u_long result, oldval;
185
186 /*---------------------------------------
187 ** Configuration mode 2 ?
188 **---------------------------------------
189 */
190
191 outb (CONF2_ENABLE_PORT, 0);
192 outb (CONF2_FORWARD_PORT, 0);
193 if (!inb (CONF2_ENABLE_PORT) && !inb (CONF2_FORWARD_PORT)) {
221 u_long result, oldval;
222
223 /*---------------------------------------
224 ** Configuration mode 2 ?
225 **---------------------------------------
226 */
227
228 outb (CONF2_ENABLE_PORT, 0);
229 outb (CONF2_FORWARD_PORT, 0);
230 if (!inb (CONF2_ENABLE_PORT) && !inb (CONF2_FORWARD_PORT)) {
194 pci_mode = 2;
195 return (2);
231 pci_mechanism = 2;
232 pci_maxdevice = 16;
196 };
197
198 /*---------------------------------------
199 ** Configuration mode 1 ?
200 **---------------------------------------
201 */
202
203 oldval = inl (CONF1_ADDR_PORT);
204 outl (CONF1_ADDR_PORT, CONF1_ENABLE);
205 result = inl (CONF1_ADDR_PORT);
206 outl (CONF1_ADDR_PORT, oldval);
207
208 if (result == CONF1_ENABLE) {
233 };
234
235 /*---------------------------------------
236 ** Configuration mode 1 ?
237 **---------------------------------------
238 */
239
240 oldval = inl (CONF1_ADDR_PORT);
241 outl (CONF1_ADDR_PORT, CONF1_ENABLE);
242 result = inl (CONF1_ADDR_PORT);
243 outl (CONF1_ADDR_PORT, oldval);
244
245 if (result == CONF1_ENABLE) {
209 pci_mode = 1;
210 return (1);
246 pci_mechanism = 1;
247 pci_maxdevice = 32;
211 };
212
213 /*---------------------------------------
214 ** No PCI bus available.
215 **---------------------------------------
216 */
248 };
249
250 /*---------------------------------------
251 ** No PCI bus available.
252 **---------------------------------------
253 */
217 return (0);
218#endif /* PCI_CONF_MODE */
219}
254}
220
255
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
256/*--------------------------------------------------------------------
257**
258** Build a pcitag from bus, device and function number
259**
260**--------------------------------------------------------------------
261*/
262
263static pcici_t
264pcibus_tag (unsigned char bus, unsigned char device, unsigned char func)
265{
266 pcici_t tag;
267
268 tag.cfg1 = 0;
269 if (device >= 32) return tag;
270 if (func >= 8) return tag;
271
237 switch (pci_mode) {
272 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}
273
274 case 1:
275 tag.cfg1 = CONF1_ENABLE
276 | (((u_long) bus ) << 16ul)
277 | (((u_long) device) << 11ul)
278 | (((u_long) func ) << 8ul);
279 break;
280 case 2:
281 if (device >= 16) break;
282 tag.cfg2.port = 0xc000 | (device << 8ul);
283 tag.cfg2.enable = 0xf1 | (func << 1ul);
284 tag.cfg2.forward = bus;
285 break;
286 };
287 return tag;
288}
254
289
290static pcici_t
291pcibus_ftag (pcici_t tag, u_char func)
292{
293 switch (pci_mechanism) {
294
295 case 1:
296 tag.cfg1 &= ~0x700ul;
297 tag.cfg1 |= (((u_long) func) << 8ul);
298 break;
299 case 2:
300 tag.cfg2.enable = 0xf1 | (func << 1ul);
301 break;
302 };
303 return tag;
304}
305
255/*--------------------------------------------------------------------
256**
257** Read register from configuration space.
258**
259**--------------------------------------------------------------------
260*/
261
306/*--------------------------------------------------------------------
307**
308** Read register from configuration space.
309**
310**--------------------------------------------------------------------
311*/
312
262
263static u_long
264pcibus_read (pcici_t tag, u_long reg)
265{
266 u_long addr, data = 0;
267
313static u_long
314pcibus_read (pcici_t tag, u_long reg)
315{
316 u_long addr, data = 0;
317
318#ifdef DENTARO
319 u_int*p = findfake(tag);
320 if (p) {
321#if 0
322 printf ("fake conf_read (tag=%x reg=%d val=%08x).\n",
323 tag.tag, (unsigned) reg, (unsigned) p[reg/4]);
324#endif
325 return (p[reg/4]);
326 }
327#endif
328
268 if (!tag.cfg1) return (0xfffffffful);
269
329 if (!tag.cfg1) return (0xfffffffful);
330
270 switch (pci_mode) {
331 switch (pci_mechanism) {
271
272 case 1:
273 addr = tag.cfg1 | (reg & 0xfc);
274#ifdef PCI_DEBUG
275 printf ("pci_conf_read(1): addr=%x ", addr);
276#endif
277 outl (CONF1_ADDR_PORT, addr);
278 data = inl (CONF1_DATA_PORT);

--- 16 unchanged lines hidden (view full) ---

295 };
296
297#ifdef PCI_DEBUG
298 printf ("data=%x\n", data);
299#endif
300
301 return (data);
302}
332
333 case 1:
334 addr = tag.cfg1 | (reg & 0xfc);
335#ifdef PCI_DEBUG
336 printf ("pci_conf_read(1): addr=%x ", addr);
337#endif
338 outl (CONF1_ADDR_PORT, addr);
339 data = inl (CONF1_DATA_PORT);

--- 16 unchanged lines hidden (view full) ---

356 };
357
358#ifdef PCI_DEBUG
359 printf ("data=%x\n", data);
360#endif
361
362 return (data);
363}
303
364
304/*--------------------------------------------------------------------
305**
306** Write register into configuration space.
307**
308**--------------------------------------------------------------------
309*/
310
365/*--------------------------------------------------------------------
366**
367** Write register into configuration space.
368**
369**--------------------------------------------------------------------
370*/
371
311
312static void
313pcibus_write (pcici_t tag, u_long reg, u_long data)
314{
315 u_long addr;
316
372static void
373pcibus_write (pcici_t tag, u_long reg, u_long data)
374{
375 u_long addr;
376
377#ifdef DENTARO
378 u_int*p = findfake(tag);
379 if (p) {
380#if 0
381 printf ("fake conf_write (tag=%x reg=%d val=%08x).\n",
382 tag.tag, (unsigned) reg, (unsigned) data);
383#endif
384 p[reg/4]=data;
385 return;
386 }
387#endif
388
317 if (!tag.cfg1) return;
318
389 if (!tag.cfg1) return;
390
319 switch (pci_mode) {
391 switch (pci_mechanism) {
320
321 case 1:
322 addr = tag.cfg1 | (reg & 0xfc);
323#ifdef PCI_DEBUG
324 printf ("pci_conf_write(1): addr=%x data=%x\n",
325 addr, data);
326#endif
327 outl (CONF1_ADDR_PORT, addr);

--- 12 unchanged lines hidden (view full) ---

340
341 outl ((u_short) addr, data);
342
343 outb (CONF2_ENABLE_PORT, 0);
344 outb (CONF2_FORWARD_PORT, 0);
345 break;
346 };
347}
392
393 case 1:
394 addr = tag.cfg1 | (reg & 0xfc);
395#ifdef PCI_DEBUG
396 printf ("pci_conf_write(1): addr=%x data=%x\n",
397 addr, data);
398#endif
399 outl (CONF1_ADDR_PORT, addr);

--- 12 unchanged lines hidden (view full) ---

412
413 outl ((u_short) addr, data);
414
415 outb (CONF2_ENABLE_PORT, 0);
416 outb (CONF2_FORWARD_PORT, 0);
417 break;
418 };
419}
348
420
349/*-----------------------------------------------------------------------
350**
351** Register an interupt handler for a pci device.
352**
353**-----------------------------------------------------------------------
354*/
355
421/*-----------------------------------------------------------------------
422**
423** Register an interupt handler for a pci device.
424**
425**-----------------------------------------------------------------------
426*/
427
356#ifndef __FreeBSD2__
357/*
358 * Type of the first (asm) part of an interrupt handler.
359 */
360typedef void inthand_t __P((u_int cs, u_int ef, u_int esp, u_int ss));
428static int
429pcibus_ihandler_attach (int irq, void(*func)(), int arg, unsigned * maskptr)
430{
431 int result;
432 result = register_intr(
433 irq, /* isa irq */
434 0, /* deviced?? */
435 0, /* flags? */
436 (inthand2_t*) func, /* handler */
437 maskptr, /* mask pointer */
438 arg); /* handler arg */
361
439
362/*
363 * Usual type of the second (C) part of an interrupt handler. Some bogus
364 * ones need the arg to be the interrupt frame (and not a copy of it, which
365 * is all that is possible in C).
366 */
367typedef void inthand2_t __P((int unit));
440 if (result) {
441 printf ("@@@ pcibus_ihandler_attach: result=%d\n", result);
442 return (result);
443 };
444 update_intr_masks();
368
445
369/*
370** XXX @FreeBSD2@
371**
372** Unfortunately, the mptr argument is _no_ pointer in 2.0 FreeBSD.
373** We would prefer a pointer because it enables us to install
374** new interrupt handlers at any time.
375** (This is just going to be changed ... <se> :)
376** In 2.0 FreeBSD later installed interrupt handlers may change
377** the xyz_imask, but this would not be recognized by handlers
378** which are installed before.
379*/
446 INTREN ((1ul<<irq));
447 return (0);
448}
380
381static int
449
450static int
382register_intr __P((int intr, int device_id, unsigned int flags,
383 inthand2_t *handler, unsigned int * mptr, int unit));
384extern unsigned intr_mask[ICU_LEN];
451pcibus_ihandler_detach (int irq, void(*func)())
452{
453 int result;
385
454
386#endif /* !__FreeBSD2__ */
387static unsigned int pci_int_mask [16];
455 INTRDIS ((1ul<<irq));
388
456
389int pcibus_regint (pcici_t tag, int(*func)(), void* arg, unsigned* maskptr)
457 result = unregister_intr (irq, (inthand2_t*) func);
458
459 if (result)
460 printf ("@@@ pcibus_ihandler_detach: result=%d\n", result);
461
462 update_intr_masks();
463
464 return (result);
465}
466
467static int
468pcibus_imask_include (int irq, unsigned* maskptr)
390{
469{
391 int irq;
392 unsigned mask, oldmask;
470 unsigned mask;
393
471
394 irq = PCI_INTERRUPT_LINE_EXTRACT(
395 pci_conf_read (tag, PCI_INTERRUPT_REG));
472 if (!maskptr) return (0);
396
397 mask = 1ul << irq;
398
473
474 mask = 1ul << irq;
475
399 if (!maskptr)
400 maskptr = &pci_int_mask[irq];
401 oldmask = *maskptr;
476 if (*maskptr & mask)
477 return (-1);
402
403 INTRMASK (*maskptr, mask);
478
479 INTRMASK (*maskptr, mask);
480 update_intr_masks();
404
481
405 register_intr(
406 irq, /* isa irq */
407 0, /* deviced?? */
408 0, /* flags? */
409 (inthand2_t*) func, /* handler */
410 maskptr, /* mask pointer */
411 (int) arg); /* handler arg */
482 return (0);
483}
412
484
413#ifdef __FreeBSD2__
414 /*
415 ** XXX See comment at beginning of file.
416 **
417 ** Have to update all the interrupt masks ... Grrrrr!!!
418 */
419 {
420 unsigned * mp = &intr_mask[0];
421 /*
422 ** update the isa interrupt masks.
423 */
424 for (mp=&intr_mask[0]; mp<&intr_mask[ICU_LEN]; mp++)
425 if ((~*mp & oldmask)==0)
426 *mp |= mask;
427 /*
428 ** update the pci interrupt masks.
429 */
430 for (mp=&pci_int_mask[0]; mp<&pci_int_mask[16]; mp++)
431 if ((~*mp & oldmask)==0)
432 *mp |= mask;
433 };
434#endif
485static int
486pcibus_imask_exclude (int irq, unsigned* maskptr)
487{
488 unsigned mask;
435
489
436 INTREN (mask);
490 if (!maskptr) return (0);
437
491
438 return (1);
492 mask = 1ul << irq;
493
494 if (! (*maskptr & mask))
495 return (-1);
496
497 *maskptr &= ~mask;
498 update_intr_masks();
499
500 return (0);
439}
501}