Deleted Added
full compact
1/**************************************************************************
2**
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
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
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
120/*-----------------------------------------------------------------
121**
122** The following functions are provided by the pci bios.
123** They are used only by the pci configuration.
124**
125** pcibus_setup():
126** Probes for a pci system.
127** Sets pci_maxdevice and pci_mechanism.
128**
129** pcibus_tag():
130** Creates a handle for pci configuration space access.
131** This handle is given to the read/write functions.
132**
133** pcibus_ftag():
134** Creates a modified handle.
135**
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
154static void
155pcibus_setup (void);
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
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
170pcibus_ihandler_attach (int irq, void(*ihandler)(), int arg, unsigned* maskp);
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
181struct pcibus i386pci = {
182 "pci",
183 pcibus_setup,
184 pcibus_tag,
185 pcibus_ftag,
186 pcibus_read,
187 pcibus_write,
188 ICU_LEN,
189 pcibus_ihandler_attach,
190 pcibus_ihandler_detach,
191 pcibus_imask_include,
192 pcibus_imask_exclude,
193};
194
195/*
196** Announce structure to generic driver
197*/
198
199DATA_SET (pcibus_set, i386pci);
200
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
218static void
219pcibus_setup (void)
220{
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)) {
231 pci_mechanism = 2;
232 pci_maxdevice = 16;
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) {
246 pci_mechanism = 1;
247 pci_maxdevice = 32;
248 };
249
250 /*---------------------------------------
251 ** No PCI bus available.
252 **---------------------------------------
253 */
254}
255
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
272 switch (pci_mechanism) {
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}
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
306/*--------------------------------------------------------------------
307**
308** Read register from configuration space.
309**
310**--------------------------------------------------------------------
311*/
312
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
329 if (!tag.cfg1) return (0xfffffffful);
330
331 switch (pci_mechanism) {
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}
364
365/*--------------------------------------------------------------------
366**
367** Write register into configuration space.
368**
369**--------------------------------------------------------------------
370*/
371
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
389 if (!tag.cfg1) return;
390
391 switch (pci_mechanism) {
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}
420
421/*-----------------------------------------------------------------------
422**
423** Register an interupt handler for a pci device.
424**
425**-----------------------------------------------------------------------
426*/
427
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 */
439
440 if (result) {
441 printf ("@@@ pcibus_ihandler_attach: result=%d\n", result);
442 return (result);
443 };
444 update_intr_masks();
445
446 INTREN ((1ul<<irq));
447 return (0);
448}
449
450static int
451pcibus_ihandler_detach (int irq, void(*func)())
452{
453 int result;
454
455 INTRDIS ((1ul<<irq));
456
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)
469{
470 unsigned mask;
471
472 if (!maskptr) return (0);
473
474 mask = 1ul << irq;
475
476 if (*maskptr & mask)
477 return (-1);
478
479 INTRMASK (*maskptr, mask);
480 update_intr_masks();
481
482 return (0);
483}
484
485static int
486pcibus_imask_exclude (int irq, unsigned* maskptr)
487{
488 unsigned mask;
489
490 if (!maskptr) return (0);
491
492 mask = 1ul << irq;
493
494 if (! (*maskptr & mask))
495 return (-1);
496
497 *maskptr &= ~mask;
498 update_intr_masks();
499
500 return (0);
501}