summaryrefslogtreecommitdiffstats
path: root/sys/dev
diff options
context:
space:
mode:
authorse <se@FreeBSD.org>1994-10-12 02:33:23 +0000
committerse <se@FreeBSD.org>1994-10-12 02:33:23 +0000
commitbdd76ad243b9f88ad1b56b11f205255f509573f6 (patch)
treedb202e3f99921d3059a152bd1e6ab5f4e2429fbe /sys/dev
parent58cfb27b7ad4e22d870e30893ca490da961495c0 (diff)
downloadFreeBSD-src-bdd76ad243b9f88ad1b56b11f205255f509573f6.zip
FreeBSD-src-bdd76ad243b9f88ad1b56b11f205255f509573f6.tar.gz
Submitted by: Wolfgang Stanglmeier <wolf@dentaro.GUN.de>
Bug fixed, that caused system hang on first interrupt on some motherboards. New version of PCI bus configuration code, now supports dynamic interrupt configuration (using BIOS supplied values). NCR SCSI and DEC Ethernet driver patched to use this feature. *** Remove PCI IRQ specifications from your kernel config file ! ***
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/de/if_de.c79
-rw-r--r--sys/dev/pci/pci.c550
2 files changed, 345 insertions, 284 deletions
diff --git a/sys/dev/de/if_de.c b/sys/dev/de/if_de.c
index 2b9774e..2aeebfa 100644
--- a/sys/dev/de/if_de.c
+++ b/sys/dev/de/if_de.c
@@ -101,8 +101,7 @@
#include <pci.h>
#if NPCI > 0
-#include <i386/pci/pci.h>
-#include <i386/pci/pci_device.h>
+#include <i386/pci/pcireg.h>
#endif
#include <i386/isa/icu.h>
#include <i386/pci/dc21040.h>
@@ -310,7 +309,7 @@ tulip_init(
int unit)
{
tulip_softc_t *sc = tulips[unit];
- unsigned new_cmdmode;
+ /* XXX unsigned new_cmdmode; */
if (sc->tulip_if.if_flags & IFF_UP) {
sc->tulip_if.if_flags |= IFF_RUNNING;
@@ -332,7 +331,7 @@ tulip_init(
sc->tulip_intrmask &= ~TULIP_STS_RXSTOPPED;
tulip_start(&sc->tulip_if);
}
- tulip_cmdnode |= TULIP_CMD_THRSHLD160;
+ sc->tulip_cmdmode |= TULIP_CMD_THRSHLD160;
*sc->tulip_csrs.csr_intr = sc->tulip_intrmask;
*sc->tulip_csrs.csr_command = sc->tulip_cmdmode;
} else {
@@ -690,13 +689,12 @@ tulip_start(
static int
tulip_intr(
- int unit)
+ tulip_softc_t *sc)
{
- tulip_softc_t *sc = tulips[unit];
tulip_uint32_t csr;
unsigned spins = 0;
- tulip_intrs[unit]++;
+ /* XXX tulip_intrs[unit]++; */
while ((csr = *sc->tulip_csrs.csr_status) & (TULIP_STS_NORMALINTR|TULIP_STS_ABNRMLINTR)) {
*sc->tulip_csrs.csr_status = csr & sc->tulip_intrmask;
@@ -706,7 +704,7 @@ tulip_intr(
if ((csr & TULIP_STS_ERRORMASK) == TULIP_STS_ERR_PARITY) {
TULIP_RESET(sc);
tulip_init(sc->tulip_unit);
- return unit;
+ return (1);
}
}
if (csr & TULIP_STS_RXINTR)
@@ -723,7 +721,7 @@ tulip_intr(
}
if (spins > sc->tulip_high_intrspins)
sc->tulip_high_intrspins = spins;
- return unit;
+ return (1);
}
/*
@@ -777,6 +775,7 @@ tulip_read_macaddr(
return 0;
}
+#ifdef MULTICAST
static unsigned
tulip_mchash(
unsigned char *mca)
@@ -794,20 +793,24 @@ tulip_mchash(
#endif
return crc & 0x1FF;
}
+#endif MULTICAST
static void
tulip_addr_filter(
tulip_softc_t *sc)
{
tulip_uint32_t *sp = sc->tulip_setupdata;
+#ifdef MULTICAST
struct ether_multistep step;
struct ether_multi *enm;
+#endif
int i;
sc->tulip_flags &= ~TULIP_WANTHASH;
sc->tulip_flags |= TULIP_WANTSETUP;
sc->tulip_cmdmode &= ~TULIP_CMD_RXRUN;
sc->tulip_intrmask &= ~TULIP_STS_RXSTOPPED;
+#ifdef MULTICAST
if (sc->tulip_ac.ac_multicnt > 14) {
unsigned hash;
/*
@@ -830,10 +833,12 @@ tulip_addr_filter(
sp[41] = ((u_short *) sc->tulip_ac.ac_enaddr)[1];
sp[42] = ((u_short *) sc->tulip_ac.ac_enaddr)[2];
} else {
+#endif
/*
* Else can get perfect filtering for 16 addresses.
*/
i = 0;
+#ifdef MULTICAST
ETHER_FIRST_MULTI(step, &sc->tulip_ac, enm);
for (; enm != NULL; i++) {
*sp++ = ((u_short *) enm->enm_addrlo)[0];
@@ -841,6 +846,7 @@ tulip_addr_filter(
*sp++ = ((u_short *) enm->enm_addrlo)[2];
ETHER_NEXT_MULTI(step, enm);
}
+#endif
/*
* If an IP address is enabled, turn on broadcast
*/
@@ -858,7 +864,9 @@ tulip_addr_filter(
*sp++ = ((u_short *) sc->tulip_ac.ac_enaddr)[1];
*sp++ = ((u_short *) sc->tulip_ac.ac_enaddr)[2];
}
+#ifdef MULTICAST
}
+#endif
}
static int
@@ -931,6 +939,7 @@ tulip_ioctl(
break;
}
+#ifdef MULTICAST
case SIOCADDMULTI:
case SIOCDELMULTI: {
/*
@@ -948,6 +957,7 @@ tulip_ioctl(
}
break;
}
+#endif /* MULTICAST */
default: {
error = EINVAL;
@@ -968,7 +978,9 @@ tulip_attach(
int cnt;
ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS;
+#ifdef MULTICAST
ifp->if_flags |= IFF_MULTICAST;
+#endif /* MULTICAST */
*sc->tulip_csrs.csr_sia_connectivity = 0;
*sc->tulip_csrs.csr_sia_connectivity = TULIP_SIACONN_10BASET;
@@ -1066,18 +1078,14 @@ tulip_initring(
* on both EISA and PCI boards, one must be careful in how defines the
* DC21040 in the config file.
*/
-static int tulip_pci_probe(pcici_t config_id);
-static int tulip_pci_attach(pcici_t config_id);
+static char* tulip_pci_probe (pcici_t config_id, pcidi_t device_id);
+static void tulip_pci_attach(pcici_t config_id, int unit);
+static u_long tulip_count;
struct pci_driver dedevice = {
tulip_pci_probe,
tulip_pci_attach,
- 0x00021011ul,
-#if __FreeBSD__ == 1
- "de",
-#endif
- "digital dc21040 ethernet",
- tulip_intr
+ &tulip_count,
};
#define PCI_CFID 0x00 /* Configuration ID */
@@ -1090,39 +1098,41 @@ struct pci_driver dedevice = {
#define PCI_CFDA 0x40 /* Configuration Driver Area */
#define TULIP_PCI_CSRSIZE (8 / sizeof(tulip_uint32_t))
-static int
+static char*
tulip_pci_probe(
- pcici_t config_id)
+ pcici_t config_id,
+ pcidi_t device_id)
{
int idx;
+ if (device_id != 0x00021011ul)
+ return (NULL);
for (idx = 0; idx < NDE; idx++)
if (tulips[idx] == NULL)
- return idx;
- return -1;
+ return ("digital dc21040 ethernet");
+ return (NULL);
}
-static int
+static void
tulip_pci_attach(
- pcici_t config_id)
+ pcici_t config_id,
+ int unit)
{
tulip_softc_t *sc;
- int retval, idx, revinfo, unit;
- signed int csr;
+ int retval, idx /* XXX , revinfo, */;
+ /* XXX signed int csr; */
vm_offset_t va_csrs, pa_csrs;
- int result;
+ /* XXX int result;*/
tulip_desc_t *rxdescs, *txdescs;
- unit = tulip_pci_probe(config_id);
-
sc = (tulip_softc_t *) malloc(sizeof(*sc), M_DEVBUF, M_NOWAIT);
if (sc == NULL)
- return -1;
+ return;
rxdescs = (tulip_desc_t *)
malloc(sizeof(tulip_desc_t) * TULIP_RXDESCS, M_DEVBUF, M_NOWAIT);
if (rxdescs == NULL) {
free((caddr_t) sc, M_DEVBUF);
- return -1;
+ return;
}
txdescs = (tulip_desc_t *)
@@ -1130,7 +1140,7 @@ tulip_pci_attach(
if (txdescs == NULL) {
free((caddr_t) rxdescs, M_DEVBUF);
free((caddr_t) sc, M_DEVBUF);
- return -1;
+ return;
}
bzero(sc, sizeof(sc)); /* Zero out the softc*/
@@ -1148,13 +1158,12 @@ tulip_pci_attach(
sc->tulip_unit = unit;
sc->tulip_name = "de";
retval = pci_map_mem(config_id, PCI_CBMA, &va_csrs, &pa_csrs);
- if (retval) {
- printf("de%d: pci_map_mem failed.\n", unit);
+ if (!retval) {
kmem_free(kernel_map, sc->tulip_rxspace, TULIP_RXSPACE + NBPG);
free((caddr_t) txdescs, M_DEVBUF);
free((caddr_t) rxdescs, M_DEVBUF);
free((caddr_t) sc, M_DEVBUF);
- return -1;
+ return;
}
tulips[unit] = sc;
tulip_initcsrs(sc, (volatile tulip_uint32_t *) va_csrs, TULIP_PCI_CSRSIZE);
@@ -1171,10 +1180,10 @@ tulip_pci_attach(
(sc->tulip_revinfo & 0xF0) >> 4, sc->tulip_revinfo & 0x0F,
"unknown");
} else {
+ pci_map_int (config_id, tulip_intr, (void*) sc, &net_imask);
TULIP_RESET(sc);
tulip_attach(sc);
}
- return 1;
}
#endif /* NPCI > 0 */
#endif /* NDE > 0 */
diff --git a/sys/dev/pci/pci.c b/sys/dev/pci/pci.c
index c34523d..396b96f 100644
--- a/sys/dev/pci/pci.c
+++ b/sys/dev/pci/pci.c
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** $Id: pci.c,v 1.5 1994/09/28 16:34:07 se Exp $
+** $Id: pci.c,v 2.12 94/10/11 22:20:37 wolf Oct11 $
**
** General subroutines for the PCI bus on 80*86 systems.
** pci_configure ()
@@ -33,27 +33,17 @@
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**
-**-------------------------------------------------------------------------
+***************************************************************************
*/
#include <pci.h>
#if NPCI > 0
-/*========================================================
-**
-** Configuration
-**
-**========================================================
-*/
-
-/*
-** maximum number of devices which share one interrupt line
-*/
-
-#ifndef PCI_MAX_DPI
-#define PCI_MAX_DPI (4)
-#endif /*PCI_MAX_DPI*/
-
+#ifndef __FreeBSD2__
+#if __FreeBSD__ >= 2
+#define __FreeBSD2__
+#endif
+#endif
/*========================================================
**
@@ -64,101 +54,54 @@
#include <sys/param.h>
#include <sys/systm.h>
+#include <sys/malloc.h>
#include <sys/errno.h>
#include <vm/vm.h>
#include <vm/vm_param.h>
-#include <i386/isa/icu.h>
#include <i386/isa/isa.h>
#include <i386/isa/isa_device.h>
-
-#include <i386/pci/pci.h>
-#include <i386/pci/pci_device.h>
-#include <i386/pci/pcibios.h>
+#include <i386/isa/icu.h>
+#include <i386/pci/pcireg.h>
/*
** Function prototypes missing in system headers
*/
-#if ! (__FreeBSD__ >= 2)
+#ifndef __FreeBSD2__
extern pmap_t pmap_kernel(void);
static vm_offset_t pmap_mapdev (vm_offset_t paddr, vm_size_t vsize);
-#endif
-
-
-/*========================================================
-**
-** Autoconfiguration (of isa bus)
-**
-**========================================================
-*/
/*
-** per slot data structure for passing interupts..
-*/
-
-static struct {
- u_short number;
- u_short isanum;
- struct {
- int (*proc)(int dev);
- dev_t unit;
- } vector[PCI_MAX_DPI];
-} pcidata [NPCI];
+ * 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));
/*
-** check device ready
-*/
-static int pciprobe (struct isa_device *dev)
-{
- if (dev->id_unit >= NPCI)
- return (0);
-
- if (!pci_conf_mode())
- return (0);
-
- return (-1);
-}
+ * 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));
/*
-** initialize the driver structure
-*/
-static int pciattach (struct isa_device *isdp)
-{
- pcidata[isdp->id_unit].number = 0;
- pcidata[isdp->id_unit].isanum = ffs(isdp->id_irq)-1;
- return (1);
-}
-
-/*
-** ISA driver structure
-*/
-
-struct isa_driver pcidriver = {
- pciprobe,
- pciattach,
- "pci"
-};
-
-/*========================================================
-**
-** Interrupt forward from isa to pci devices.
-**
-**========================================================
+** 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.
+** 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.
*/
+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];
-void pciintr (int unit)
-{
- u_short i;
- if (unit >= NPCI) return;
- for (i=0; i<pcidata[unit].number; i++) {
- (void)(*pcidata[unit].vector[i].proc)
- (pcidata[unit].vector[i].unit);
- };
-}
-
+#endif /* !__FreeBSD2__ */
/*========================================================
**
@@ -183,52 +126,82 @@ void pciintr (int unit)
#define PCI_PMEM_START 0xc0000000
#endif
-static vm_offset_t pci_paddr = PCI_PMEM_START;
+static vm_offset_t pci_paddr = PCI_PMEM_START;
+/*--------------------------------------------------------
+**
+** The pci device interrupt lines should have been
+** assigned by the bios. But if the bios failed to
+** to it, we set it.
+**
+**--------------------------------------------------------
+*/
+
+#ifndef PCI_IRQ
+#define PCI_IRQ 0
+#endif
+
+static u_long pci_irq = PCI_IRQ;
+
/*---------------------------------------------------------
**
** pci_configure ()
**
+** Probe all devices on pci bus and attach them.
+**
+** May be called more than once.
+** Any device is attached only once.
+** (Attached devices are remembered in pci_seen.)
+**
**---------------------------------------------------------
*/
static void not_supported (pcici_t tag, u_long type);
+static unsigned long pci_seen[NPCI];
+
+static int pci_conf_count;
+
void pci_configure()
{
u_char device,last_device;
- u_short bus,last_bus;
+ u_short bus;
pcici_t tag;
pcidi_t type;
u_long data;
int unit;
- int intpin;
- int isanum;
- int pci_mode;
+ int pci_mechanism;
+ int pciint;
+ int irq;
+ char* name=0;
+ int newdev=0;
- struct pci_driver *drp;
+ struct pci_driver *drp=0;
struct pci_device *dvp;
/*
** check pci bus present
*/
- pci_mode = pci_conf_mode ();
- if (!pci_mode) return;
- last_bus = pci_last_bus ();
- last_device = pci_mode==1 ? 31 : 15;
-
+ pci_mechanism = pci_conf_mode ();
+ if (!pci_mechanism) return;
+ last_device = pci_mechanism==1 ? 31 : 15;
+
/*
** hello world ..
*/
+
+ for (bus=0;bus<NPCI;bus++) {
#ifndef PCI_QUIET
- printf ("pci*: mode=%d, scanning bus 0..%d, device 0..%d.\n",
- pci_mode, last_bus, last_device);
+ printf ("pci%d: scanning device 0..%d, mechanism=%d.\n",
+ bus, last_device, pci_mechanism);
#endif
-
- for (bus=0;bus<=last_bus; bus++)
for (device=0; device<=last_device; device ++) {
+
+ if (pci_seen[bus] & (1ul << device))
+ continue;
+
tag = pcitag (bus, device, 0);
type = pci_conf_read (tag, PCI_ID_REG);
@@ -238,137 +211,90 @@ void pci_configure()
** lookup device in ioconfiguration:
*/
- for (dvp = pci_devtab; dvp->pd_device_id; dvp++) {
- if (dvp->pd_device_id == type) break;
+ for (dvp = pci_devtab; dvp->pd_name; dvp++) {
+ drp = dvp->pd_driver;
+ if (!drp)
+ continue;
+ if ((name=(*drp->probe)(tag, type)))
+ break;
};
- drp = dvp->pd_driver;
-
- if (!dvp->pd_device_id) {
- /*
- ** not found
- ** try to dig out some information.
- **
- ** By Garrett Wollman
- ** <wollman@halloran-eldar.lcs.mit.edu>
- */
-
- int data = pci_conf_read(tag, PCI_CLASS_REG);
- vm_offset_t va;
- vm_offset_t pa;
- int reg;
-
- switch (data & PCI_CLASS_MASK) {
-
- case PCI_CLASS_PREHISTORIC:
- if ((data & PCI_SUBCLASS_MASK)
- != PCI_SUBCLASS_PREHISTORIC_VGA)
- break;
-
- case PCI_CLASS_DISPLAY:
- for (reg = PCI_MAP_REG_START;
- reg < PCI_MAP_REG_END;
- reg += 4) {
- data = pci_map_mem(tag, reg, &va, &pa);
- if (data == 0)
- printf (
- "pci%d:%d: mapped VGA-like device at physaddr 0x%lx\n",
- bus, device, (u_long)pa);
-
- }
- continue;
- };
+ if (!dvp->pd_name) {
#ifndef PCI_QUIET
+ if (pci_conf_count)
+ continue;
printf("pci%d:%d: ", bus, device);
not_supported (tag, type);
#endif
- };
-
- if (!drp) {
- if(dvp->pd_flags & PDF_LOADABLE) {
- printf("%s: loadable device on pci%d:%d\n",
- dvp->pd_name, bus, device);
- }
continue;
- }
+ };
+ pci_seen[bus] |= (1ul << device);
/*
- ** found it.
- ** probe returns the device unit.
+ ** Get and increment the unit.
*/
- unit = (*drp->probe) (tag);
+ unit = (*drp->count)++;
- if (unit<0) {
- printf ("%s <%s>: probe failed on pci%d:%d\n",
- dvp->pd_name, drp->name, bus, device);
- continue;
- };
+ /*
+ ** ignore device ?
+ */
+
+ if (!*name) continue;
+
+ /*
+ ** Announce this device
+ */
- printf ("%s%d <%s>", dvp->pd_name, unit, drp->name);
+ newdev++;
+ printf ("%s%d <%s>", dvp->pd_name, unit, name);
/*
- ** install interrupts
+ ** Get the int pin number (pci interrupt number a-d)
+ ** from the pci configuration space.
*/
data = pci_conf_read (tag, PCI_INTERRUPT_REG);
- intpin = PCI_INTERRUPT_PIN_EXTRACT(data);
- if (intpin) {
- int idx=NPCI;
+ pciint = PCI_INTERRUPT_PIN_EXTRACT(data);
- /*
- ** Usage of int line register (if set by bios)
- ** Matt Thomas <thomas@lkg.dec.com>
- */
+ if (pciint) {
- isanum = PCI_INTERRUPT_LINE_EXTRACT(data);
- if (isanum) {
-
- /*
- ** @INT@ FIXME!!!
- **
- ** Should try to use "register_interupt"
- ** at this point.
- */
-
- printf (" line=%d", isanum);
- for (idx = 0; idx < NPCI; idx++) {
- if (pcidata[idx].isanum == isanum)
- break;
- };
- };
+ printf (" int %c", 0x60+pciint);
/*
- ** Or take the device number as index ...
+ ** If the interrupt line register is not set,
+ ** set it now from PCI_IRQ.
*/
- if (idx >= NPCI) idx = device;
+ if (!(PCI_INTERRUPT_LINE_EXTRACT(data))) {
+
+ irq = pci_irq & 0x0f;
+ pci_irq >>= 4;
+
+ data = PCI_INTERRUPT_LINE_INSERT(data, irq);
+ printf (" (config)");
+ pci_conf_write (tag, PCI_INTERRUPT_REG, data);
+ };
+
+ irq = PCI_INTERRUPT_LINE_EXTRACT(data);
/*
- ** And install the interrupt.
+ ** If it's zero, the isa irq number is unknown,
+ ** and we cannot bind the pci interrupt to isa.
*/
- if (idx<NPCI) {
- u_short entry = pcidata[idx].number;
- printf (" irq %c", 0x60+intpin);
- if (entry < PCI_MAX_DPI) {
- pcidata[idx].vector[entry].proc = drp->intr;
- pcidata[idx].vector[entry].unit = unit;
- entry++;
- };
- printf (" isa=%d [%d]",pcidata[idx].isanum, entry);
- pcidata[idx].number=entry;
- } else {
- printf (" no int");
- };
+ if (irq)
+ printf (" irq %d", irq);
+ else
+ printf (" not bound");
};
-
+
/*
** enable memory access
*/
- data = pci_conf_read (tag, PCI_COMMAND_STATUS_REG)
- & 0xffff | PCI_COMMAND_MEM_ENABLE;
+ data = (pci_conf_read (tag, PCI_COMMAND_STATUS_REG)
+ & 0xffff) | PCI_COMMAND_MEM_ENABLE;
pci_conf_write (tag, (u_char) PCI_COMMAND_STATUS_REG, data);
@@ -380,13 +306,16 @@ void pci_configure()
printf (" on pci%d:%d\n", bus, device);
- (void) (*drp->attach) (tag);
- }
+ (*drp->attach) (tag, unit);
+ };
+ };
#ifndef PCI_QUIET
- printf ("pci uses physical addresses from 0x%lx to 0x%lx\n",
+ if (newdev)
+ printf ("pci uses physical addresses from 0x%lx to 0x%lx\n",
(u_long)PCI_PMEM_START, (u_long)pci_paddr);
#endif
+ pci_conf_count++;
}
/*-----------------------------------------------------------------------
@@ -403,7 +332,8 @@ int pci_map_port (pcici_t tag, u_long reg, u_short* pa)
/*
** @MAPIO@ not yet implemented.
*/
- return (ENOSYS);
+ printf ("pci_map_port failed: not yet implemented\n");
+ return (0);
}
/*-----------------------------------------------------------------------
@@ -425,8 +355,11 @@ int pci_map_mem (pcici_t tag, u_long reg, vm_offset_t* va, vm_offset_t* pa)
** sanity check
*/
- if (reg <= PCI_MAP_REG_START || reg >= PCI_MAP_REG_END || (reg & 3))
- return (EINVAL);
+ if (reg < PCI_MAP_REG_START || reg >= PCI_MAP_REG_END || (reg & 3)) {
+ printf ("pci_map_mem failed: bad register=0x%x\n",
+ (unsigned)reg);
+ return (0);
+ };
/*
** get size and type of memory
@@ -445,7 +378,9 @@ int pci_map_mem (pcici_t tag, u_long reg, vm_offset_t* va, vm_offset_t* pa)
break;
default: /* unknown */
- return (EINVAL);
+ printf ("pci_map_mem failed: bad memory type=0x%x\n",
+ (unsigned) data);
+ return (0);
};
/*
@@ -455,18 +390,19 @@ int pci_map_mem (pcici_t tag, u_long reg, vm_offset_t* va, vm_offset_t* pa)
vsize = round_page (-(data & PCI_MAP_MEMORY_ADDRESS_MASK));
- if (!vsize) return (EINVAL);
-
+ if (!vsize) return (0);
+
/*
** align physical address to virtual size
*/
- if (data = pci_paddr % vsize)
+ if ((data = pci_paddr % vsize))
pci_paddr += vsize - data;
- vaddr = pmap_mapdev (pci_paddr, vsize);
+ vaddr = (vm_offset_t) pmap_mapdev (pci_paddr, vsize);
+
- if (!vaddr) return (EINVAL);
+ if (!vaddr) return (0);
#ifndef PCI_QUIET
/*
@@ -474,7 +410,7 @@ int pci_map_mem (pcici_t tag, u_long reg, vm_offset_t* va, vm_offset_t* pa)
*/
printf ("\treg%d: virtual=0x%lx physical=0x%lx\n",
- reg, (u_long)vaddr, (u_long)pci_paddr);
+ (unsigned) reg, (u_long)vaddr, (u_long)pci_paddr);
#endif
/*
@@ -496,50 +432,77 @@ int pci_map_mem (pcici_t tag, u_long reg, vm_offset_t* va, vm_offset_t* pa)
pci_paddr += vsize;
- return (0);
+ return (1);
}
-/*-----------------------------------------------------------
+/*-----------------------------------------------------------------------
**
-** Mapping of physical to virtual memory
+** Map pci interrupts to isa interrupts.
**
-**-----------------------------------------------------------
+**-----------------------------------------------------------------------
*/
-#if ! (__FreeBSD__ >= 2)
+static unsigned int pci_int_mask [16];
-extern vm_map_t kernel_map;
-
-static vm_offset_t pmap_mapdev (vm_offset_t paddr, vm_size_t vsize)
+int pci_map_int (pcici_t tag, int(*func)(), void* arg, unsigned* maskptr)
{
- vm_offset_t vaddr,value;
- u_long result;
+ int irq;
+ unsigned mask;
- vaddr = vm_map_min (kernel_map);
+ irq = PCI_INTERRUPT_LINE_EXTRACT(
+ pci_conf_read (tag, PCI_INTERRUPT_REG));
- result = vm_map_find (kernel_map, (void*)0, (vm_offset_t) 0,
- &vaddr, vsize, TRUE);
-
- if (result != KERN_SUCCESS) {
- printf (" vm_map_find failed(%d)\n", result);
+ if (irq >= 16 || irq <= 0) {
+ printf ("pci_map_int failed: no int line set.\n");
return (0);
- };
+ }
+
+ mask = 1ul << irq;
+
+ if (!maskptr)
+ maskptr = &pci_int_mask[irq];
+
+ INTRMASK (*maskptr, mask);
+ register_intr(
+ irq, /* isa irq */
+ 0, /* deviced?? */
+ 0, /* flags? */
+ (inthand2_t*) func, /* handler */
+#ifdef __FreeBSD2__
+ *maskptr, /* mask */
+#else
+ maskptr, /* mask pointer */
+#endif
+ (int) arg); /* handler arg */
+
+#ifdef __FreeBSD2__
/*
- ** map physical
+ ** XXX See comment at beginning of file.
+ **
+ ** Have to update all the interrupt masks ... Grrrrr!!!
*/
-
- value = vaddr;
- while (vsize >= NBPG) {
- pmap_enter (pmap_kernel(), vaddr, paddr,
- VM_PROT_READ|VM_PROT_WRITE, TRUE);
- vaddr += NBPG;
- paddr += NBPG;
- vsize -= NBPG;
+ {
+ unsigned * mp = &intr_mask[0];
+ /*
+ ** update the isa interrupt masks.
+ */
+ for (mp=&intr_mask[0]; mp<&intr_mask[ICU_LEN]; mp++)
+ if (*mp & *maskptr)
+ *mp |= mask;
+ /*
+ ** update the pci interrupt masks.
+ */
+ for (mp=&pci_int_mask[0]; mp<&pci_int_mask[16]; mp++)
+ if (*mp & *maskptr)
+ *mp |= mask;
};
- return (value);
-}
#endif
+
+ INTREN (mask);
+
+ return (1);
+}
/*-----------------------------------------------------------
**
@@ -554,7 +517,7 @@ struct vt {
static struct vt VendorTable[] = {
{0x1002, "ATI TECHNOLOGIES INC"},
- {0x1011, "DIGITAL EQUIPMENT CORP."},
+ {0x1011, "DIGITAL EQUIPMENT CORPORATION"},
{0x101A, "NCR"},
{0x102B, "MATROX"},
{0x1045, "OPTI"},
@@ -604,18 +567,107 @@ void not_supported (pcici_t tag, u_long type)
case 1:
case 5:
- printf (" map(%lx): io(%lx)\n", reg, data & ~3);
+ printf (" map(%x): io(%lx)\n",
+ reg, data & ~3);
break;
case 0:
- printf (" map(%lx): mem32(%lx)\n", reg, data & ~7);
+ printf (" map(%x): mem32(%lx)\n",
+ reg, data & ~7);
break;
case 2:
- printf (" map(%lx): mem20(%lx)\n", reg, data & ~7);
+ printf (" map(%x): mem20(%lx)\n",
+ reg, data & ~7);
break;
case 4:
- printf (" map(%lx): mem64(%lx)\n", reg, data & ~7);
+ printf (" map(%x): mem64(%lx)\n",
+ reg, data & ~7);
break;
}
}
}
-#endif
+
+#ifndef __FreeBSD2__
+/*-----------------------------------------------------------
+**
+** Mapping of physical to virtual memory
+**
+**-----------------------------------------------------------
+*/
+
+extern vm_map_t kernel_map;
+
+static vm_offset_t pmap_mapdev (vm_offset_t paddr, vm_size_t vsize)
+{
+ vm_offset_t vaddr,value;
+ u_long result;
+
+ vaddr = vm_map_min (kernel_map);
+
+ result = vm_map_find (kernel_map, (void*)0, (vm_offset_t) 0,
+ &vaddr, vsize, TRUE);
+
+ if (result != KERN_SUCCESS) {
+ printf (" vm_map_find failed(%d)\n", result);
+ return (0);
+ };
+
+ /*
+ ** map physical
+ */
+
+ value = vaddr;
+ while (vsize >= NBPG) {
+ pmap_enter (pmap_kernel(), vaddr, paddr,
+ VM_PROT_READ|VM_PROT_WRITE, TRUE);
+ vaddr += NBPG;
+ paddr += NBPG;
+ vsize -= NBPG;
+ };
+ return (value);
+}
+
+/*------------------------------------------------------------
+**
+** Emulate the register_intr() function of FreeBSD 2.0
+**
+** requires a patch:
+** FreeBSD 2.0: "/sys/i386/isa/vector.s"
+** 386bsd0.1: "/sys/i386/isa/icu.s"
+** 386bsd1.0: Please ask Jesus Monroy Jr.
+**
+**------------------------------------------------------------
+*/
+
+#include <machine/segments.h>
+
+int pci_int_unit [16];
+inthand2_t* (pci_int_hdlr [16]);
+unsigned int * pci_int_mptr [16];
+unsigned int pci_int_count[16];
+
+extern void
+ Vpci3(), Vpci4(), Vpci5(), Vpci6(), Vpci7(), Vpci8(), Vpci9(),
+ Vpci10(), Vpci11(), Vpci12(), Vpci13(), Vpci14(), Vpci15();
+
+static inthand_t* pci_int_glue[16] = {
+ 0, 0, 0, Vpci3, Vpci4, Vpci5, Vpci6, Vpci7, Vpci8,
+ Vpci9, Vpci10, Vpci11, Vpci12, Vpci13, Vpci14, Vpci15 };
+
+static int
+register_intr __P((int intr, int device_id, unsigned int flags,
+ inthand2_t *handler, unsigned int* mptr, int unit))
+{
+ if (intr >= 16 || intr <= 2)
+ return (EINVAL);
+ if (pci_int_hdlr [intr])
+ return (EBUSY);
+
+ pci_int_hdlr [intr] = handler;
+ pci_int_unit [intr] = unit;
+ pci_int_mptr [intr] = mptr;
+
+ setidt(NRSVIDT + intr, pci_int_glue[intr], SDT_SYS386IGT, SEL_KPL);
+ return (0);
+}
+#endif /* __FreeBSD2__ */
+#endif /* NPCI */
OpenPOWER on IntegriCloud