summaryrefslogtreecommitdiffstats
path: root/sys/i386/pci/pci_pir.c
diff options
context:
space:
mode:
authorse <se@FreeBSD.org>1995-03-21 23:06:07 +0000
committerse <se@FreeBSD.org>1995-03-21 23:06:07 +0000
commit0cdd391c0583fc081ed2d75fb9f3baaa599de103 (patch)
treee93fa1f23f13abe8e75be2b0429e887dc8e1a5ba /sys/i386/pci/pci_pir.c
parent6e667246cd96976e175eec9db61940c42681a155 (diff)
downloadFreeBSD-src-0cdd391c0583fc081ed2d75fb9f3baaa599de103.zip
FreeBSD-src-0cdd391c0583fc081ed2d75fb9f3baaa599de103.tar.gz
New ISA specific PCI code.
Supports shared PCI interrupts. Submitted by: Wolfgang Stanglmeier <wolf@kintaro.cologne.de>
Diffstat (limited to 'sys/i386/pci/pci_pir.c')
-rw-r--r--sys/i386/pci/pci_pir.c356
1 files changed, 209 insertions, 147 deletions
diff --git a/sys/i386/pci/pci_pir.c b/sys/i386/pci/pci_pir.c
index f1cdd1e..b1fd217 100644
--- a/sys/i386/pci/pci_pir.c
+++ b/sys/i386/pci/pci_pir.c
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** $Id: pcibus.c,v 1.3 1995/02/25 17:51:18 se Exp $
+** $Id: pcibus.c,v 1.4 1995/02/26 05:14:51 bde Exp $
**
** pci bus subroutines for i386 architecture.
**
@@ -35,15 +35,7 @@
***************************************************************************
*/
-#ifndef __FreeBSD2__
-#if __FreeBSD__ >= 2
-#define __FreeBSD2__
-#endif
-#endif
-
-#ifdef __FreeBSD2__
-#define HAS_CPUFUNC_H
-#endif
+#define __PCIBUS_C___ "pl4 95/03/21"
#include <sys/param.h>
#include <sys/systm.h>
@@ -57,23 +49,89 @@
#include <pci/pcireg.h>
#include <pci/pcibus.h>
-static char pci_mode;
-
+extern int printf();
+
+#ifdef DENTARO
+
+#define SFAKE (32)
+
+static void
+dec21050 (u_int*reg) {
+ reg[0] = 0x00011011;
+ reg[1]&= 0x000001e7;
+ reg[2] = 0x06040001;
+ reg[3]&= 0x0000f8ff;
+ reg[3]|= 0x000100ff;
+ reg[4] = 0x00000000;
+ reg[5] = 0x00000000;
+ reg[6]&= 0xf8ffffff;
+ reg[7]&= 0x0000f0f0; /* io-limit */
+ reg[8]&= 0xfff0fff0; /* mem-limit, non prefatchable */
+ reg[9]&= 0xfff0fff0; /* mem-limit, prefetchable memory */
+ reg[10] = 0x00000000;
+ reg[11] = 0x00000000;
+ reg[12] = 0x00000000;
+ reg[13] = 0x00000000;
+ reg[14] = 0x00000000;
+ reg[15]&= 0x00ef0000;
+}
+
+static void
+dec21140 (u_int*reg) {
+ reg[0] = 0x00091011u;
+ reg[4]&= 0xfffffffdu;
+ reg[4]|= 0x00000001u;
+ reg[5]&= 0xffffff00u;
+}
+
+struct fake {
+ u_int tag;
+ void (*proc)(u_int*);
+};
+
+struct fake faketable [] = {
+{ 0xc70000f1, dec21050 },
+{ 0xc00001f1, dec21140 },
+{ 0xc40001f1, dec21140 },
+{ 0xc80001f1, dec21140 },
+{ 0xcc0001f1, dec21140 },
+};
+
+#define NFAKE (sizeof faketable / sizeof (struct fake))
+
+static u_int fakedata[NFAKE * SFAKE];
+
+u_int* findfake (pcici_t tag)
+{
+ u_int *p;
+ int i;
+ for (i=0; i<NFAKE; i++)
+ if (faketable[i].tag == tag.tag)
+ break;
+
+ if (i>=NFAKE)
+ return (0);
+ p = &fakedata[i*SFAKE];
+ (*faketable[i].proc)(p);
+ return (p);
+}
+#endif /*DENTARO*/
+
/*-----------------------------------------------------------------
**
** The following functions are provided by the pci bios.
** They are used only by the pci configuration.
**
-** pcibus_mode():
+** pcibus_setup():
** Probes for a pci system.
-** Returns 1 or 2 for pci configuration mechanism.
-** Returns 0 if no pci system.
+** Sets pci_maxdevice and pci_mechanism.
**
** pcibus_tag():
-** Gets a handle for accessing the pci configuration
-** space.
-** This handle is given to the mapping functions (see
-** above) or to the read/write functions.
+** Creates a handle for pci configuration space access.
+** This handle is given to the read/write functions.
+**
+** pcibus_ftag():
+** Creates a modified handle.
**
** pcibus_read():
** Read a long word from the pci configuration space.
@@ -93,12 +151,15 @@ static char pci_mode;
**-----------------------------------------------------------------
*/
-static int
-pcibus_mode (void);
+static void
+pcibus_setup (void);
static pcici_t
pcibus_tag (u_char bus, u_char device, u_char func);
+static pcici_t
+pcibus_ftag (pcici_t tag, u_char func);
+
static u_long
pcibus_read (pcici_t tag, u_long reg);
@@ -106,15 +167,29 @@ static void
pcibus_write (pcici_t tag, u_long reg, u_long data);
static int
-pcibus_regint (pcici_t tag, int(*func)(), void* arg, unsigned* maskptr);
+pcibus_ihandler_attach (int irq, void(*ihandler)(), int arg, unsigned* maskp);
+
+static int
+pcibus_ihandler_detach (int irq, void(*handler)());
+
+static int
+pcibus_imask_include (int irq, unsigned* maskptr);
+
+static int
+pcibus_imask_exclude (int irq, unsigned* maskptr);
struct pcibus i386pci = {
"pci",
- pcibus_mode,
+ pcibus_setup,
pcibus_tag,
+ pcibus_ftag,
pcibus_read,
pcibus_write,
- pcibus_regint,
+ ICU_LEN,
+ pcibus_ihandler_attach,
+ pcibus_ihandler_detach,
+ pcibus_imask_include,
+ pcibus_imask_exclude,
};
/*
@@ -122,41 +197,7 @@ struct pcibus i386pci = {
*/
DATA_SET (pcibus_set, i386pci);
-
-/*--------------------------------------------------------------------
-**
-** Port access
-**
-**--------------------------------------------------------------------
-*/
-
-#ifndef HAS_CPUFUNC_H
-#undef inl
-#define inl(port) \
-({ u_long data; \
- __asm __volatile("inl %1, %0": "=a" (data): "d" ((u_short)(port))); \
- data; })
-
-
-#undef outl
-#define outl(port, data) \
-{__asm __volatile("outl %0, %1"::"a" ((u_long)(data)), "d" ((u_short)(port)));}
-
-
-#undef inb
-#define inb(port) \
-({ u_char data; \
- __asm __volatile("inb %1, %0": "=a" (data): "d" ((u_short)(port))); \
- data; })
-
-
-#undef outb
-#define outb(port, data) \
-{__asm __volatile("outb %0, %1"::"a" ((u_char)(data)), "d" ((u_short)(port)));}
-
-#endif /* HAS_CPUFUNC_H */
-
/*--------------------------------------------------------------------
**
** Determine configuration mode
@@ -174,13 +215,9 @@ DATA_SET (pcibus_set, i386pci);
#define CONF2_FORWARD_PORT 0x0cfa
-static int
-pcibus_mode (void)
+static void
+pcibus_setup (void)
{
-#ifdef PCI_CONF_MODE
- pci_mode = PCI_CONF_MODE;
- return (PCI_CONF_MODE)
-#else /* PCI_CONF_MODE */
u_long result, oldval;
/*---------------------------------------
@@ -191,8 +228,8 @@ pcibus_mode (void)
outb (CONF2_ENABLE_PORT, 0);
outb (CONF2_FORWARD_PORT, 0);
if (!inb (CONF2_ENABLE_PORT) && !inb (CONF2_FORWARD_PORT)) {
- pci_mode = 2;
- return (2);
+ pci_mechanism = 2;
+ pci_maxdevice = 16;
};
/*---------------------------------------
@@ -206,18 +243,16 @@ pcibus_mode (void)
outl (CONF1_ADDR_PORT, oldval);
if (result == CONF1_ENABLE) {
- pci_mode = 1;
- return (1);
+ pci_mechanism = 1;
+ pci_maxdevice = 32;
};
/*---------------------------------------
** No PCI bus available.
**---------------------------------------
*/
- return (0);
-#endif /* PCI_CONF_MODE */
}
-
+
/*--------------------------------------------------------------------
**
** Build a pcitag from bus, device and function number
@@ -234,7 +269,7 @@ pcibus_tag (unsigned char bus, unsigned char device, unsigned char func)
if (device >= 32) return tag;
if (func >= 8) return tag;
- switch (pci_mode) {
+ switch (pci_mechanism) {
case 1:
tag.cfg1 = CONF1_ENABLE
@@ -251,7 +286,23 @@ pcibus_tag (unsigned char bus, unsigned char device, unsigned char func)
};
return tag;
}
-
+
+static pcici_t
+pcibus_ftag (pcici_t tag, u_char func)
+{
+ switch (pci_mechanism) {
+
+ case 1:
+ tag.cfg1 &= ~0x700ul;
+ tag.cfg1 |= (((u_long) func) << 8ul);
+ break;
+ case 2:
+ tag.cfg2.enable = 0xf1 | (func << 1ul);
+ break;
+ };
+ return tag;
+}
+
/*--------------------------------------------------------------------
**
** Read register from configuration space.
@@ -259,15 +310,25 @@ pcibus_tag (unsigned char bus, unsigned char device, unsigned char func)
**--------------------------------------------------------------------
*/
-
static u_long
pcibus_read (pcici_t tag, u_long reg)
{
u_long addr, data = 0;
+#ifdef DENTARO
+ u_int*p = findfake(tag);
+ if (p) {
+#if 0
+ printf ("fake conf_read (tag=%x reg=%d val=%08x).\n",
+ tag.tag, (unsigned) reg, (unsigned) p[reg/4]);
+#endif
+ return (p[reg/4]);
+ }
+#endif
+
if (!tag.cfg1) return (0xfffffffful);
- switch (pci_mode) {
+ switch (pci_mechanism) {
case 1:
addr = tag.cfg1 | (reg & 0xfc);
@@ -300,7 +361,7 @@ pcibus_read (pcici_t tag, u_long reg)
return (data);
}
-
+
/*--------------------------------------------------------------------
**
** Write register into configuration space.
@@ -308,15 +369,26 @@ pcibus_read (pcici_t tag, u_long reg)
**--------------------------------------------------------------------
*/
-
static void
pcibus_write (pcici_t tag, u_long reg, u_long data)
{
u_long addr;
+#ifdef DENTARO
+ u_int*p = findfake(tag);
+ if (p) {
+#if 0
+ printf ("fake conf_write (tag=%x reg=%d val=%08x).\n",
+ tag.tag, (unsigned) reg, (unsigned) data);
+#endif
+ p[reg/4]=data;
+ return;
+ }
+#endif
+
if (!tag.cfg1) return;
- switch (pci_mode) {
+ switch (pci_mechanism) {
case 1:
addr = tag.cfg1 | (reg & 0xfc);
@@ -345,7 +417,7 @@ pcibus_write (pcici_t tag, u_long reg, u_long data)
break;
};
}
-
+
/*-----------------------------------------------------------------------
**
** Register an interupt handler for a pci device.
@@ -353,87 +425,77 @@ pcibus_write (pcici_t tag, u_long reg, u_long data)
**-----------------------------------------------------------------------
*/
-#ifndef __FreeBSD2__
-/*
- * Type of the first (asm) part of an interrupt handler.
- */
-typedef void inthand_t __P((u_int cs, u_int ef, u_int esp, u_int ss));
-
-/*
- * Usual type of the second (C) part of an interrupt handler. Some bogus
- * ones need the arg to be the interrupt frame (and not a copy of it, which
- * is all that is possible in C).
- */
-typedef void inthand2_t __P((int unit));
+static int
+pcibus_ihandler_attach (int irq, void(*func)(), int arg, unsigned * maskptr)
+{
+ int result;
+ result = register_intr(
+ irq, /* isa irq */
+ 0, /* deviced?? */
+ 0, /* flags? */
+ (inthand2_t*) func, /* handler */
+ maskptr, /* mask pointer */
+ arg); /* handler arg */
+
+ if (result) {
+ printf ("@@@ pcibus_ihandler_attach: result=%d\n", result);
+ return (result);
+ };
+ update_intr_masks();
-/*
-** XXX @FreeBSD2@
-**
-** Unfortunately, the mptr argument is _no_ pointer in 2.0 FreeBSD.
-** We would prefer a pointer because it enables us to install
-** new interrupt handlers at any time.
-** (This is just going to be changed ... <se> :)
-** In 2.0 FreeBSD later installed interrupt handlers may change
-** the xyz_imask, but this would not be recognized by handlers
-** which are installed before.
-*/
+ INTREN ((1ul<<irq));
+ return (0);
+}
static int
-register_intr __P((int intr, int device_id, unsigned int flags,
- inthand2_t *handler, unsigned int * mptr, int unit));
-extern unsigned intr_mask[ICU_LEN];
+pcibus_ihandler_detach (int irq, void(*func)())
+{
+ int result;
-#endif /* !__FreeBSD2__ */
-static unsigned int pci_int_mask [16];
+ INTRDIS ((1ul<<irq));
-int pcibus_regint (pcici_t tag, int(*func)(), void* arg, unsigned* maskptr)
+ result = unregister_intr (irq, (inthand2_t*) func);
+
+ if (result)
+ printf ("@@@ pcibus_ihandler_detach: result=%d\n", result);
+
+ update_intr_masks();
+
+ return (result);
+}
+
+static int
+pcibus_imask_include (int irq, unsigned* maskptr)
{
- int irq;
- unsigned mask, oldmask;
+ unsigned mask;
- irq = PCI_INTERRUPT_LINE_EXTRACT(
- pci_conf_read (tag, PCI_INTERRUPT_REG));
+ if (!maskptr) return (0);
mask = 1ul << irq;
- if (!maskptr)
- maskptr = &pci_int_mask[irq];
- oldmask = *maskptr;
+ if (*maskptr & mask)
+ return (-1);
INTRMASK (*maskptr, mask);
+ update_intr_masks();
- register_intr(
- irq, /* isa irq */
- 0, /* deviced?? */
- 0, /* flags? */
- (inthand2_t*) func, /* handler */
- maskptr, /* mask pointer */
- (int) arg); /* handler arg */
-
-#ifdef __FreeBSD2__
- /*
- ** XXX See comment at beginning of file.
- **
- ** Have to update all the interrupt masks ... Grrrrr!!!
- */
- {
- unsigned * mp = &intr_mask[0];
- /*
- ** update the isa interrupt masks.
- */
- for (mp=&intr_mask[0]; mp<&intr_mask[ICU_LEN]; mp++)
- if ((~*mp & oldmask)==0)
- *mp |= mask;
- /*
- ** update the pci interrupt masks.
- */
- for (mp=&pci_int_mask[0]; mp<&pci_int_mask[16]; mp++)
- if ((~*mp & oldmask)==0)
- *mp |= mask;
- };
-#endif
+ return (0);
+}
- INTREN (mask);
+static int
+pcibus_imask_exclude (int irq, unsigned* maskptr)
+{
+ unsigned mask;
- return (1);
+ if (!maskptr) return (0);
+
+ mask = 1ul << irq;
+
+ if (! (*maskptr & mask))
+ return (-1);
+
+ *maskptr &= ~mask;
+ update_intr_masks();
+
+ return (0);
}
OpenPOWER on IntegriCloud