New ISA specific PCI code.
Supports shared PCI interrupts. Submitted by: Wolfgang Stanglmeier <wolf@kintaro.cologne.de>
This commit is contained in:
parent
e8208dcf80
commit
1245633d21
@ -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));
|
||||
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 */
|
||||
|
||||
/*
|
||||
* 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));
|
||||
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];
|
||||
|
||||
#endif /* !__FreeBSD2__ */
|
||||
static unsigned int pci_int_mask [16];
|
||||
|
||||
int pcibus_regint (pcici_t tag, int(*func)(), void* arg, unsigned* maskptr)
|
||||
pcibus_ihandler_detach (int irq, void(*func)())
|
||||
{
|
||||
int irq;
|
||||
unsigned mask, oldmask;
|
||||
int result;
|
||||
|
||||
irq = PCI_INTERRUPT_LINE_EXTRACT(
|
||||
pci_conf_read (tag, PCI_INTERRUPT_REG));
|
||||
INTRDIS ((1ul<<irq));
|
||||
|
||||
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)
|
||||
{
|
||||
unsigned mask;
|
||||
|
||||
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
|
||||
|
||||
INTREN (mask);
|
||||
|
||||
return (1);
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
pcibus_imask_exclude (int irq, unsigned* maskptr)
|
||||
{
|
||||
unsigned mask;
|
||||
|
||||
if (!maskptr) return (0);
|
||||
|
||||
mask = 1ul << irq;
|
||||
|
||||
if (! (*maskptr & mask))
|
||||
return (-1);
|
||||
|
||||
*maskptr &= ~mask;
|
||||
update_intr_masks();
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
@ -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));
|
||||
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 */
|
||||
|
||||
/*
|
||||
* 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));
|
||||
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];
|
||||
|
||||
#endif /* !__FreeBSD2__ */
|
||||
static unsigned int pci_int_mask [16];
|
||||
|
||||
int pcibus_regint (pcici_t tag, int(*func)(), void* arg, unsigned* maskptr)
|
||||
pcibus_ihandler_detach (int irq, void(*func)())
|
||||
{
|
||||
int irq;
|
||||
unsigned mask, oldmask;
|
||||
int result;
|
||||
|
||||
irq = PCI_INTERRUPT_LINE_EXTRACT(
|
||||
pci_conf_read (tag, PCI_INTERRUPT_REG));
|
||||
INTRDIS ((1ul<<irq));
|
||||
|
||||
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)
|
||||
{
|
||||
unsigned mask;
|
||||
|
||||
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
|
||||
|
||||
INTREN (mask);
|
||||
|
||||
return (1);
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
pcibus_imask_exclude (int irq, unsigned* maskptr)
|
||||
{
|
||||
unsigned mask;
|
||||
|
||||
if (!maskptr) return (0);
|
||||
|
||||
mask = 1ul << irq;
|
||||
|
||||
if (! (*maskptr & mask))
|
||||
return (-1);
|
||||
|
||||
*maskptr &= ~mask;
|
||||
update_intr_masks();
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
@ -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));
|
||||
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 */
|
||||
|
||||
/*
|
||||
* 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));
|
||||
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];
|
||||
|
||||
#endif /* !__FreeBSD2__ */
|
||||
static unsigned int pci_int_mask [16];
|
||||
|
||||
int pcibus_regint (pcici_t tag, int(*func)(), void* arg, unsigned* maskptr)
|
||||
pcibus_ihandler_detach (int irq, void(*func)())
|
||||
{
|
||||
int irq;
|
||||
unsigned mask, oldmask;
|
||||
int result;
|
||||
|
||||
irq = PCI_INTERRUPT_LINE_EXTRACT(
|
||||
pci_conf_read (tag, PCI_INTERRUPT_REG));
|
||||
INTRDIS ((1ul<<irq));
|
||||
|
||||
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)
|
||||
{
|
||||
unsigned mask;
|
||||
|
||||
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
|
||||
|
||||
INTREN (mask);
|
||||
|
||||
return (1);
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
pcibus_imask_exclude (int irq, unsigned* maskptr)
|
||||
{
|
||||
unsigned mask;
|
||||
|
||||
if (!maskptr) return (0);
|
||||
|
||||
mask = 1ul << irq;
|
||||
|
||||
if (! (*maskptr & mask))
|
||||
return (-1);
|
||||
|
||||
*maskptr &= ~mask;
|
||||
update_intr_masks();
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
@ -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));
|
||||
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 */
|
||||
|
||||
/*
|
||||
* 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));
|
||||
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];
|
||||
|
||||
#endif /* !__FreeBSD2__ */
|
||||
static unsigned int pci_int_mask [16];
|
||||
|
||||
int pcibus_regint (pcici_t tag, int(*func)(), void* arg, unsigned* maskptr)
|
||||
pcibus_ihandler_detach (int irq, void(*func)())
|
||||
{
|
||||
int irq;
|
||||
unsigned mask, oldmask;
|
||||
int result;
|
||||
|
||||
irq = PCI_INTERRUPT_LINE_EXTRACT(
|
||||
pci_conf_read (tag, PCI_INTERRUPT_REG));
|
||||
INTRDIS ((1ul<<irq));
|
||||
|
||||
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)
|
||||
{
|
||||
unsigned mask;
|
||||
|
||||
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
|
||||
|
||||
INTREN (mask);
|
||||
|
||||
return (1);
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
pcibus_imask_exclude (int irq, unsigned* maskptr)
|
||||
{
|
||||
unsigned mask;
|
||||
|
||||
if (!maskptr) return (0);
|
||||
|
||||
mask = 1ul << irq;
|
||||
|
||||
if (! (*maskptr & mask))
|
||||
return (-1);
|
||||
|
||||
*maskptr &= ~mask;
|
||||
update_intr_masks();
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
@ -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));
|
||||
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 */
|
||||
|
||||
/*
|
||||
* 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));
|
||||
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];
|
||||
|
||||
#endif /* !__FreeBSD2__ */
|
||||
static unsigned int pci_int_mask [16];
|
||||
|
||||
int pcibus_regint (pcici_t tag, int(*func)(), void* arg, unsigned* maskptr)
|
||||
pcibus_ihandler_detach (int irq, void(*func)())
|
||||
{
|
||||
int irq;
|
||||
unsigned mask, oldmask;
|
||||
int result;
|
||||
|
||||
irq = PCI_INTERRUPT_LINE_EXTRACT(
|
||||
pci_conf_read (tag, PCI_INTERRUPT_REG));
|
||||
INTRDIS ((1ul<<irq));
|
||||
|
||||
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)
|
||||
{
|
||||
unsigned mask;
|
||||
|
||||
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
|
||||
|
||||
INTREN (mask);
|
||||
|
||||
return (1);
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
pcibus_imask_exclude (int irq, unsigned* maskptr)
|
||||
{
|
||||
unsigned mask;
|
||||
|
||||
if (!maskptr) return (0);
|
||||
|
||||
mask = 1ul << irq;
|
||||
|
||||
if (! (*maskptr & mask))
|
||||
return (-1);
|
||||
|
||||
*maskptr &= ~mask;
|
||||
update_intr_masks();
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
@ -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));
|
||||
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 */
|
||||
|
||||
/*
|
||||
* 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));
|
||||
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];
|
||||
|
||||
#endif /* !__FreeBSD2__ */
|
||||
static unsigned int pci_int_mask [16];
|
||||
|
||||
int pcibus_regint (pcici_t tag, int(*func)(), void* arg, unsigned* maskptr)
|
||||
pcibus_ihandler_detach (int irq, void(*func)())
|
||||
{
|
||||
int irq;
|
||||
unsigned mask, oldmask;
|
||||
int result;
|
||||
|
||||
irq = PCI_INTERRUPT_LINE_EXTRACT(
|
||||
pci_conf_read (tag, PCI_INTERRUPT_REG));
|
||||
INTRDIS ((1ul<<irq));
|
||||
|
||||
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)
|
||||
{
|
||||
unsigned mask;
|
||||
|
||||
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
|
||||
|
||||
INTREN (mask);
|
||||
|
||||
return (1);
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
pcibus_imask_exclude (int irq, unsigned* maskptr)
|
||||
{
|
||||
unsigned mask;
|
||||
|
||||
if (!maskptr) return (0);
|
||||
|
||||
mask = 1ul << irq;
|
||||
|
||||
if (! (*maskptr & mask))
|
||||
return (-1);
|
||||
|
||||
*maskptr &= ~mask;
|
||||
update_intr_masks();
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user