Reapplied all of Stefan's changes. What a mess - the files were modified
and moved at the same time. This made it *very* difficult to fix the revision log lossage that happend when the files were moved. SIGH.
This commit is contained in:
parent
cab076f4f5
commit
a4cc75ab15
@ -21,7 +21,7 @@
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* $Id: if_de.c,v 1.13 1994/12/22 23:42:25 davidg Exp $
|
||||
* $Id: if_de.c,v 1.14 1995/02/02 12:36:15 davidg Exp $
|
||||
*
|
||||
*/
|
||||
|
||||
@ -46,6 +46,8 @@
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/errno.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <machine/clock.h>
|
||||
|
||||
#include <net/if.h>
|
||||
#include <net/if_types.h>
|
||||
@ -78,9 +80,9 @@
|
||||
|
||||
#include <pci.h>
|
||||
#if NPCI > 0
|
||||
#include <pci/pcireg.h>
|
||||
#include <pci/pcivar.h>
|
||||
#endif
|
||||
#include <i386/isa/icu.h>
|
||||
|
||||
#include <pci/dc21040.h>
|
||||
|
||||
/*
|
||||
@ -840,6 +842,8 @@ tulip_addr_filter(
|
||||
}
|
||||
}
|
||||
|
||||
/*extern void arp_ifinit(struct arpcom *, struct ifaddr*);*/
|
||||
|
||||
static int
|
||||
tulip_ioctl(
|
||||
struct ifnet *ifp,
|
||||
@ -1041,12 +1045,15 @@ 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 = {
|
||||
struct pci_device dedevice = {
|
||||
"de",
|
||||
tulip_pci_probe,
|
||||
tulip_pci_attach,
|
||||
&tulip_count,
|
||||
};
|
||||
|
||||
DATA_SET (pcidevice_set, dedevice);
|
||||
|
||||
#define PCI_CFID 0x00 /* Configuration ID */
|
||||
#define PCI_CFCS 0x04 /* Configurtion Command/Status */
|
||||
#define PCI_CFRV 0x08 /* Configuration Revision */
|
||||
|
@ -1,6 +1,6 @@
|
||||
/**************************************************************************
|
||||
**
|
||||
** $Id: pci.c,v 1.9 1994/11/02 23:47:13 se Exp $
|
||||
** $Id: pci.c,v 1.10 1995/02/02 12:36:18 davidg Exp $
|
||||
**
|
||||
** General subroutines for the PCI bus on 80*86 systems.
|
||||
** pci_configure ()
|
||||
@ -56,62 +56,38 @@
|
||||
#include <sys/systm.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/errno.h>
|
||||
#include <sys/kernel.h>
|
||||
|
||||
#include <vm/vm.h>
|
||||
#include <vm/vm_param.h>
|
||||
|
||||
#include <i386/isa/isa.h>
|
||||
#include <i386/isa/isa_device.h>
|
||||
#include <i386/isa/icu.h>
|
||||
#include <pci/pcivar.h>
|
||||
#include <pci/pcireg.h>
|
||||
#include <pci/pcibus.h>
|
||||
|
||||
#ifdef __FreeBSD2__
|
||||
#include <sys/devconf.h>
|
||||
|
||||
|
||||
struct pci_devconf {
|
||||
struct kern_devconf pdc_kdc;
|
||||
struct pci_info pdc_pi;
|
||||
};
|
||||
#endif
|
||||
|
||||
static int
|
||||
pci_externalize (struct proc *, struct kern_devconf *, void *, size_t);
|
||||
|
||||
static int
|
||||
pci_internalize (struct proc *, struct kern_devconf *, void *, size_t);
|
||||
#else /* __FreeBSD2__ */
|
||||
|
||||
/*
|
||||
** Function prototypes missing in system headers
|
||||
*/
|
||||
|
||||
#ifndef __FreeBSD2__
|
||||
extern pmap_t pmap_kernel(void);
|
||||
static vm_offset_t pmap_mapdev (vm_offset_t paddr, vm_size_t vsize);
|
||||
#endif /* __FreeBSD2__ */
|
||||
|
||||
/*
|
||||
* Type of the first (asm) part of an interrupt handler.
|
||||
*/
|
||||
typedef void inthand_t __P((u_int cs, u_int ef, u_int esp, u_int ss));
|
||||
|
||||
/*
|
||||
* Usual type of the second (C) part of an interrupt handler. Some bogus
|
||||
* ones need the arg to be the interrupt frame (and not a copy of it, which
|
||||
* is all that is possible in C).
|
||||
*/
|
||||
typedef void inthand2_t __P((int unit));
|
||||
|
||||
/*
|
||||
** 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.
|
||||
*/
|
||||
|
||||
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__ */
|
||||
|
||||
/*========================================================
|
||||
**
|
||||
@ -138,6 +114,20 @@ extern unsigned intr_mask[ICU_LEN];
|
||||
|
||||
static vm_offset_t pci_paddr = PCI_PMEM_START;
|
||||
|
||||
/*--------------------------------------------------------
|
||||
**
|
||||
** The pci ports can be mapped to any address.
|
||||
** As default we start at 0x400
|
||||
**
|
||||
**--------------------------------------------------------
|
||||
*/
|
||||
|
||||
#ifndef PCI_PORT_START
|
||||
#define PCI_PORT_START 0x0400
|
||||
#endif
|
||||
|
||||
static u_short pci_ioaddr = PCI_PORT_START;
|
||||
|
||||
/*--------------------------------------------------------
|
||||
**
|
||||
** The pci device interrupt lines should have been
|
||||
@ -172,15 +162,6 @@ static unsigned long pci_seen[NPCI];
|
||||
|
||||
static int pci_conf_count;
|
||||
|
||||
#ifdef __FreeBSD2__
|
||||
static int
|
||||
pci_externalize (struct proc *, struct kern_devconf *, void *, size_t);
|
||||
|
||||
static int
|
||||
pci_internalize (struct proc *, struct kern_devconf *, void *, size_t);
|
||||
|
||||
#endif /* __FreeBSD2__ */
|
||||
|
||||
void pci_configure()
|
||||
{
|
||||
u_char device,last_device;
|
||||
@ -194,19 +175,28 @@ void pci_configure()
|
||||
int irq;
|
||||
char* name=0;
|
||||
vm_offset_t old_addr=pci_paddr;
|
||||
u_short old_ioaddr=pci_ioaddr;
|
||||
|
||||
struct pci_driver *drp=0;
|
||||
struct pci_device *dvp;
|
||||
int dvi;
|
||||
struct pci_device *dvp=0;
|
||||
|
||||
#ifdef __FreeBSD2__
|
||||
struct pci_devconf *pdcp;
|
||||
#endif
|
||||
|
||||
/*
|
||||
** first check pci bus driver available
|
||||
*/
|
||||
|
||||
if (pcibus_set.ls_length <= 0)
|
||||
return;
|
||||
|
||||
#define pcibus (*((struct pcibus*) pcibus_set.ls_items[0]))
|
||||
/*
|
||||
** check pci bus present
|
||||
*/
|
||||
|
||||
pci_mechanism = pci_conf_mode ();
|
||||
pci_mechanism = pcibus.pb_mode ();
|
||||
if (!pci_mechanism) return;
|
||||
last_device = pci_mechanism==1 ? 31 : 15;
|
||||
|
||||
@ -217,16 +207,16 @@ void pci_configure()
|
||||
|
||||
for (bus=0;bus<NPCI;bus++) {
|
||||
#ifndef PCI_QUIET
|
||||
printf ("pci%d: scanning device 0..%d, mechanism=%d.\n",
|
||||
bus, last_device, pci_mechanism);
|
||||
printf ("%s%d: scanning device 0..%d, mechanism=%d.\n",
|
||||
pcibus.pb_name, bus, last_device, pci_mechanism);
|
||||
#endif
|
||||
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);
|
||||
tag = pcibus.pb_tag (bus, device, 0);
|
||||
type = pcibus.pb_read (tag, PCI_ID_REG);
|
||||
|
||||
if ((!type) || (type==0xfffffffful)) continue;
|
||||
|
||||
@ -234,19 +224,18 @@ void pci_configure()
|
||||
** lookup device in ioconfiguration:
|
||||
*/
|
||||
|
||||
for (dvp = pci_devtab; dvp->pd_name; dvp++) {
|
||||
drp = dvp->pd_driver;
|
||||
if (!drp)
|
||||
continue;
|
||||
if ((name=(*drp->probe)(tag, type)))
|
||||
for (dvi=0; dvi<pcidevice_set.ls_length; dvi++) {
|
||||
dvp = (struct pci_device*) pcidevice_set.ls_items[dvi];
|
||||
if ((name=(*dvp->pd_probe)(tag, type)))
|
||||
break;
|
||||
dvp = NULL;
|
||||
};
|
||||
|
||||
if (!dvp->pd_name) {
|
||||
if (dvp==NULL) {
|
||||
#ifndef PCI_QUIET
|
||||
if (pci_conf_count)
|
||||
continue;
|
||||
printf("pci%d:%d: ", bus, device);
|
||||
printf("%s%d:%d: ", pcibus.pb_name, bus, device);
|
||||
not_supported (tag, type);
|
||||
#endif
|
||||
continue;
|
||||
@ -257,7 +246,7 @@ void pci_configure()
|
||||
** Get and increment the unit.
|
||||
*/
|
||||
|
||||
unit = (*drp->count)++;
|
||||
unit = (*dvp->pd_count)++;
|
||||
|
||||
/*
|
||||
** ignore device ?
|
||||
@ -276,7 +265,7 @@ void pci_configure()
|
||||
** from the pci configuration space.
|
||||
*/
|
||||
|
||||
data = pci_conf_read (tag, PCI_INTERRUPT_REG);
|
||||
data = pcibus.pb_read (tag, PCI_INTERRUPT_REG);
|
||||
pciint = PCI_INTERRUPT_PIN_EXTRACT(data);
|
||||
|
||||
if (pciint) {
|
||||
@ -295,7 +284,7 @@ void pci_configure()
|
||||
|
||||
data = PCI_INTERRUPT_LINE_INSERT(data, irq);
|
||||
printf (" (config)");
|
||||
pci_conf_write (tag, PCI_INTERRUPT_REG, data);
|
||||
pcibus.pb_write (tag, PCI_INTERRUPT_REG, data);
|
||||
};
|
||||
|
||||
irq = PCI_INTERRUPT_LINE_EXTRACT(data);
|
||||
@ -315,10 +304,10 @@ void pci_configure()
|
||||
** enable memory access
|
||||
*/
|
||||
|
||||
data = (pci_conf_read (tag, PCI_COMMAND_STATUS_REG)
|
||||
data = (pcibus.pb_read (tag, PCI_COMMAND_STATUS_REG)
|
||||
& 0xffff) | PCI_COMMAND_MEM_ENABLE;
|
||||
|
||||
pci_conf_write (tag, (u_char) PCI_COMMAND_STATUS_REG, data);
|
||||
pcibus.pb_write (tag, (u_char) PCI_COMMAND_STATUS_REG, data);
|
||||
|
||||
/*
|
||||
** show pci slot.
|
||||
@ -333,7 +322,7 @@ void pci_configure()
|
||||
*/
|
||||
|
||||
pdcp = (struct pci_devconf *)
|
||||
malloc (sizeof (struct pci_devconf),M_DEVBUF,M_WAITOK);
|
||||
malloc (sizeof (struct pci_devconf),M_DEVBUF,M_WAITOK);
|
||||
|
||||
/*
|
||||
** Fill in.
|
||||
@ -378,7 +367,7 @@ void pci_configure()
|
||||
** i.e. when installing subdevices.
|
||||
*/
|
||||
|
||||
(*drp->attach) (tag, unit);
|
||||
(*dvp->pd_attach) (tag, unit);
|
||||
};
|
||||
};
|
||||
|
||||
@ -386,10 +375,43 @@ void pci_configure()
|
||||
if (pci_paddr != old_addr)
|
||||
printf ("pci uses physical addresses from 0x%lx to 0x%lx\n",
|
||||
(u_long)PCI_PMEM_START, (u_long)pci_paddr);
|
||||
if (pci_ioaddr != old_ioaddr)
|
||||
printf ("pci devices use ioports from 0x%x to 0x%x\n",
|
||||
(unsigned)PCI_PORT_START, (unsigned)pci_ioaddr);
|
||||
#endif
|
||||
pci_conf_count++;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------
|
||||
**
|
||||
** The following functions are provided for the device driver
|
||||
** to read/write the configuration space.
|
||||
**
|
||||
** pci_conf_read():
|
||||
** Read a long word from the pci configuration space.
|
||||
** Requires a tag (from pcitag) and the register
|
||||
** number (should be a long word alligned one).
|
||||
**
|
||||
** pci_conf_write():
|
||||
** Writes a long word to the pci configuration space.
|
||||
** Requires a tag (from pcitag), the register number
|
||||
** (should be a long word alligned one), and a value.
|
||||
**
|
||||
**-----------------------------------------------------------------
|
||||
*/
|
||||
|
||||
u_long
|
||||
pci_conf_read (pcici_t tag, u_long reg)
|
||||
{
|
||||
return (pcibus.pb_read (tag, reg));
|
||||
}
|
||||
|
||||
void
|
||||
pci_conf_write (pcici_t tag, u_long reg, u_long data)
|
||||
{
|
||||
pcibus.pb_write (tag, reg, data);
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------
|
||||
**
|
||||
** Map device into port space.
|
||||
@ -401,11 +423,78 @@ void pci_configure()
|
||||
|
||||
int pci_map_port (pcici_t tag, u_long reg, u_short* pa)
|
||||
{
|
||||
u_long data;
|
||||
u_short size;
|
||||
|
||||
/*
|
||||
** @MAPIO@ not yet implemented.
|
||||
** sanity check
|
||||
*/
|
||||
printf ("pci_map_port failed: not yet implemented\n");
|
||||
return (0);
|
||||
|
||||
if (reg < PCI_MAP_REG_START || reg >= PCI_MAP_REG_END || (reg & 3)) {
|
||||
printf ("pci_map_port failed: bad register=0x%x\n",
|
||||
(unsigned)reg);
|
||||
return (0);
|
||||
};
|
||||
|
||||
/*
|
||||
** get size and type of port
|
||||
**
|
||||
** type is in the lowest two bits.
|
||||
** If device requires 2^n bytes, the next
|
||||
** n-2 bits are hardwired as 0.
|
||||
*/
|
||||
|
||||
pcibus.pb_write (tag, reg, 0xfffffffful);
|
||||
data = pcibus.pb_read (tag, reg);
|
||||
|
||||
switch (data & 0x03) {
|
||||
|
||||
case PCI_MAP_IO:
|
||||
break;
|
||||
|
||||
default: /* unknown */
|
||||
printf ("pci_map_port failed: bad port type=0x%x\n",
|
||||
(unsigned) data);
|
||||
return (0);
|
||||
};
|
||||
|
||||
/*
|
||||
** get the size
|
||||
*/
|
||||
|
||||
size = -(data & PCI_MAP_IO_ADDRESS_MASK);
|
||||
|
||||
if (!size) return (0);
|
||||
|
||||
/*
|
||||
** align physical address to virtual size
|
||||
*/
|
||||
|
||||
if ((data = pci_ioaddr % size))
|
||||
pci_ioaddr += size - data;
|
||||
|
||||
#ifndef PCI_QUIET
|
||||
/*
|
||||
** display values.
|
||||
*/
|
||||
|
||||
printf ("\treg%d: ioaddr=0x%x size=0x%x\n",
|
||||
(unsigned) reg, (unsigned) pci_ioaddr, (unsigned) size);
|
||||
#endif
|
||||
|
||||
/*
|
||||
** return them to the driver
|
||||
*/
|
||||
|
||||
*pa = pci_ioaddr;
|
||||
|
||||
/*
|
||||
** and don't forget to increment pci_ioaddr
|
||||
*/
|
||||
|
||||
pci_ioaddr += size;
|
||||
|
||||
return (1);
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------
|
||||
@ -427,10 +516,10 @@ 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)) {
|
||||
printf ("pci_map_mem failed: bad register=0x%x\n",
|
||||
(unsigned)reg);
|
||||
return (0);
|
||||
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);
|
||||
};
|
||||
|
||||
/*
|
||||
@ -441,8 +530,8 @@ int pci_map_mem (pcici_t tag, u_long reg, vm_offset_t* va, vm_offset_t* pa)
|
||||
** n-4 bits are read as 0.
|
||||
*/
|
||||
|
||||
pci_conf_write (tag, reg, 0xfffffffful);
|
||||
data = pci_conf_read (tag, reg);
|
||||
pcibus.pb_write (tag, reg, 0xfffffffful);
|
||||
data = pcibus.pb_read (tag, reg);
|
||||
|
||||
switch (data & 0x0f) {
|
||||
|
||||
@ -450,9 +539,9 @@ int pci_map_mem (pcici_t tag, u_long reg, vm_offset_t* va, vm_offset_t* pa)
|
||||
break;
|
||||
|
||||
default: /* unknown */
|
||||
printf ("pci_map_mem failed: bad memory type=0x%x\n",
|
||||
(unsigned) data);
|
||||
return (0);
|
||||
printf ("pci_map_mem failed: bad memory type=0x%x\n",
|
||||
(unsigned) data);
|
||||
return (0);
|
||||
};
|
||||
|
||||
/*
|
||||
@ -496,7 +585,7 @@ int pci_map_mem (pcici_t tag, u_long reg, vm_offset_t* va, vm_offset_t* pa)
|
||||
** set device address
|
||||
*/
|
||||
|
||||
pci_conf_write (tag, reg, pci_paddr);
|
||||
pcibus.pb_write (tag, reg, pci_paddr);
|
||||
|
||||
/*
|
||||
** and don't forget to increment pci_paddr
|
||||
@ -519,29 +608,29 @@ pci_externalize (struct proc *p, struct kern_devconf *kdcp, void *u, size_t l)
|
||||
{
|
||||
struct pci_externalize_buffer buffer;
|
||||
struct pci_info * pip = kdcp->kdc_parentdata;
|
||||
pcici_t tag;
|
||||
pcici_t tag;
|
||||
int i;
|
||||
|
||||
if (l < sizeof buffer) {
|
||||
return ENOMEM;
|
||||
return ENOMEM;
|
||||
};
|
||||
|
||||
tag = pcitag (pip->pi_bus, pip->pi_device, 0);
|
||||
tag = pcibus.pb_tag (pip->pi_bus, pip->pi_device, 0);
|
||||
|
||||
buffer.peb_pci_info = *pip;
|
||||
|
||||
for (i=0; i<PCI_EXT_CONF_LEN; i++) {
|
||||
buffer.peb_config[i] = pci_conf_read (tag, i*4);
|
||||
buffer.peb_config[i] = pcibus.pb_read (tag, i*4);
|
||||
};
|
||||
|
||||
return copyout(&buffer, u, sizeof buffer);
|
||||
return copyout(&buffer, u, sizeof buffer);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
pci_internalize (struct proc *p, struct kern_devconf *kdcp, void *u, size_t s)
|
||||
{
|
||||
return EOPNOTSUPP;
|
||||
return EOPNOTSUPP;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------
|
||||
@ -551,60 +640,24 @@ pci_internalize (struct proc *p, struct kern_devconf *kdcp, void *u, size_t s)
|
||||
**-----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static unsigned int pci_int_mask [16];
|
||||
|
||||
int pci_map_int (pcici_t tag, int(*func)(), void* arg, unsigned* maskptr)
|
||||
{
|
||||
int irq;
|
||||
unsigned mask;
|
||||
int irq, result;
|
||||
|
||||
irq = PCI_INTERRUPT_LINE_EXTRACT(
|
||||
pci_conf_read (tag, PCI_INTERRUPT_REG));
|
||||
pcibus.pb_read (tag, PCI_INTERRUPT_REG));
|
||||
|
||||
if (irq >= 16 || irq <= 0) {
|
||||
printf ("pci_map_int failed: no int line set.\n");
|
||||
return (0);
|
||||
}
|
||||
|
||||
mask = 1ul << irq;
|
||||
result = pcibus.pb_regint (tag, func, arg, maskptr);
|
||||
|
||||
if (!maskptr)
|
||||
maskptr = &pci_int_mask[irq];
|
||||
|
||||
INTRMASK (*maskptr, mask);
|
||||
|
||||
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 & *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;
|
||||
if (!result) {
|
||||
printf ("pci_map_int failed.\n");
|
||||
return (0);
|
||||
};
|
||||
#endif
|
||||
|
||||
INTREN (mask);
|
||||
|
||||
return (1);
|
||||
}
|
||||
@ -659,14 +712,14 @@ void not_supported (pcici_t tag, u_long type)
|
||||
|
||||
printf (", device=0x%lx", type >> 16);
|
||||
|
||||
data = (pci_conf_read(tag, PCI_CLASS_REG) >> 24) & 0xff;
|
||||
data = (pcibus.pb_read(tag, PCI_CLASS_REG) >> 24) & 0xff;
|
||||
if (data < sizeof(majclasses) / sizeof(majclasses[0]))
|
||||
printf(", class=%s", majclasses[data]);
|
||||
|
||||
printf (" [not supported]\n");
|
||||
|
||||
for (reg=PCI_MAP_REG_START; reg<PCI_MAP_REG_END; reg+=4) {
|
||||
data = pci_conf_read (tag, reg);
|
||||
data = pcibus.pb_read (tag, reg);
|
||||
if (!data) continue;
|
||||
switch (data&7) {
|
||||
|
||||
|
@ -1,10 +1,12 @@
|
||||
/**************************************************************************
|
||||
**
|
||||
** $Id: pcireg.h,v 1.1 1994/10/12 02:25:03 se Exp $
|
||||
** $Id: pcireg.h,v 1.1 1995/02/01 22:56:50 se Exp $
|
||||
**
|
||||
** Declarations for pci bus drivers.
|
||||
** Names for PCI configuration space registers.
|
||||
**
|
||||
** 386bsd / FreeBSD
|
||||
** Copyright (c) 1994 Charles Hannum. All rights reserved.
|
||||
**
|
||||
** FreeBSD
|
||||
**
|
||||
**-------------------------------------------------------------------------
|
||||
**
|
||||
@ -38,271 +40,16 @@
|
||||
#ifndef __PCI_REG_H__
|
||||
#define __PCI_REG_H__
|
||||
|
||||
/*-----------------------------------------------------------------
|
||||
**
|
||||
** main pci initialization function.
|
||||
** called at boot time from autoconf.c
|
||||
**
|
||||
**-----------------------------------------------------------------
|
||||
*/
|
||||
|
||||
void pci_configure (void);
|
||||
|
||||
/*-----------------------------------------------------------------
|
||||
**
|
||||
** The pci configuration id describes a pci device on the bus.
|
||||
** It is constructed from: bus, device & function numbers.
|
||||
**
|
||||
**-----------------------------------------------------------------
|
||||
*/
|
||||
|
||||
typedef union {
|
||||
u_long cfg1;
|
||||
struct {
|
||||
u_char enable;
|
||||
u_char forward;
|
||||
u_short port;
|
||||
} cfg2;
|
||||
} pcici_t;
|
||||
|
||||
/*-----------------------------------------------------------------
|
||||
**
|
||||
** Each pci device has an unique device id.
|
||||
** It is used to find a matching driver.
|
||||
**
|
||||
**-----------------------------------------------------------------
|
||||
*/
|
||||
|
||||
typedef u_long pcidi_t;
|
||||
|
||||
/*-----------------------------------------------------------------
|
||||
**
|
||||
** The pci driver structure.
|
||||
**
|
||||
** probe: Checks if the driver can support a device
|
||||
** with this type. The tag may be used to get
|
||||
** more info with pci_read_conf(). See below.
|
||||
** It returns a string with the devices name,
|
||||
** or a NULL pointer, if the driver cannot
|
||||
** support this device.
|
||||
**
|
||||
** attach: Allocate a control structure and prepare
|
||||
** it. This function may use the pci mapping
|
||||
** functions. See below.
|
||||
** (configuration id) or type.
|
||||
**
|
||||
** count: A pointer to a unit counter.
|
||||
** It's used by the pci configurator to
|
||||
** allocate unit numbers.
|
||||
**
|
||||
**-----------------------------------------------------------------
|
||||
*/
|
||||
|
||||
struct pci_driver {
|
||||
char* (*probe ) (pcici_t tag, pcidi_t type);
|
||||
void (*attach) (pcici_t tag, int unit);
|
||||
u_long *count;
|
||||
};
|
||||
|
||||
/*-----------------------------------------------------------------
|
||||
**
|
||||
** The pci-devconf interface.
|
||||
**
|
||||
**-----------------------------------------------------------------
|
||||
*/
|
||||
|
||||
struct pci_info {
|
||||
u_short pi_bus;
|
||||
u_short pi_device;
|
||||
};
|
||||
|
||||
#define PCI_EXT_CONF_LEN (16)
|
||||
#define PCI_EXTERNAL_LEN (sizeof(struct pci_externalize_buffer))
|
||||
|
||||
struct pci_externalize_buffer {
|
||||
struct pci_info peb_pci_info;
|
||||
u_long peb_config[PCI_EXT_CONF_LEN];
|
||||
};
|
||||
|
||||
|
||||
/*-----------------------------------------------------------------
|
||||
**
|
||||
** Per device structure.
|
||||
**
|
||||
** An array of this structure should be created by the
|
||||
** config utility and live in "ioconf.c".
|
||||
**
|
||||
** At the moment it's created by hand and lives in
|
||||
** pci_config.c
|
||||
**
|
||||
** pd_driver:
|
||||
** a pointer to the driver structure.
|
||||
**
|
||||
** pd_name:
|
||||
** the name of the devices which are supported
|
||||
** by this driver for kernel messages.
|
||||
**
|
||||
** pd_flags:
|
||||
** for further study.
|
||||
**
|
||||
**-----------------------------------------------------------------
|
||||
*/
|
||||
|
||||
struct pci_device {
|
||||
struct
|
||||
pci_driver* pd_driver;
|
||||
const char * pd_name;
|
||||
int pd_flags;
|
||||
};
|
||||
|
||||
/*-----------------------------------------------------------------
|
||||
**
|
||||
** This table should be generated in file "ioconf.c"
|
||||
** by the config program.
|
||||
** It is used at boot time by the configuration function
|
||||
** pci_configure()
|
||||
**
|
||||
**-----------------------------------------------------------------
|
||||
*/
|
||||
|
||||
extern struct pci_device pci_devtab[];
|
||||
|
||||
/*-----------------------------------------------------------------
|
||||
**
|
||||
** Map a pci device to physical and virtual memory.
|
||||
**
|
||||
** The va and pa addresses are "in/out" parameters.
|
||||
** If they are 0 on entry, the function assigns an address.
|
||||
**
|
||||
** Entry selects the register in the pci configuration
|
||||
** space, which supplies the size of the region, and
|
||||
** receives the physical address.
|
||||
**
|
||||
** If there is any error, a message is written, and
|
||||
** the function returns with zero.
|
||||
** Else it returns with a value different to zero.
|
||||
**
|
||||
**-----------------------------------------------------------------
|
||||
*/
|
||||
|
||||
int pci_map_mem (pcici_t tag, u_long entry, u_long * va, u_long * pa);
|
||||
|
||||
/*-----------------------------------------------------------------
|
||||
**
|
||||
** Map a pci device to an io port area.
|
||||
**
|
||||
** *pa is an "in/out" parameter.
|
||||
** If it's 0 on entry, the function assigns an port number..
|
||||
**
|
||||
** Entry selects the register in the pci configuration
|
||||
** space, which supplies the size of the region, and
|
||||
** receives the port number.
|
||||
**
|
||||
** If there is any error, a message is written, and
|
||||
** the function returns with zero.
|
||||
** Else it returns with a value different to zero.
|
||||
**
|
||||
**-----------------------------------------------------------------
|
||||
*/
|
||||
|
||||
int pci_map_port(pcici_t tag, u_long entry, u_short * pa);
|
||||
|
||||
/*-----------------------------------------------------------------
|
||||
**
|
||||
** Map a pci interrupt to an isa irq line,
|
||||
** and enable the interrupt.
|
||||
**
|
||||
** func is the interrupt handler, arg is the argument
|
||||
** to this function.
|
||||
**
|
||||
** The maskptr argument should be &bio_imask,
|
||||
** &net_imask etc. or NULL.
|
||||
**
|
||||
** If there is any error, a message is written, and
|
||||
** the function returns with zero.
|
||||
** Else it returns with a value different to zero.
|
||||
**
|
||||
** A word of caution for FreeBSD 2.0:
|
||||
**
|
||||
** We use the register_intr() function.
|
||||
**
|
||||
** The interrupt line of the selected device is included
|
||||
** into the supplied mask: after the corresponding splXXX
|
||||
** this drivers interrupts are blocked.
|
||||
**
|
||||
** But in the interrupt handlers startup code ONLY
|
||||
** the interrupt of the driver is blocked, and NOT
|
||||
** all interrupts of the spl group.
|
||||
**
|
||||
** It may be required to additional block the group
|
||||
** interrupts by splXXX() inside the interrupt handler.
|
||||
**
|
||||
** In pre 2.0 kernels we emulate the register_intr
|
||||
** function. The emulating function blocks all interrupts
|
||||
** of the group in the interrupt handler prefix code.
|
||||
**
|
||||
**-----------------------------------------------------------------
|
||||
*/
|
||||
|
||||
int pci_map_int (pcici_t tag, int (*func)(), void* arg, unsigned * maskptr);
|
||||
|
||||
/*-----------------------------------------------------------------
|
||||
**
|
||||
** The following functions are provided by the pci bios.
|
||||
** They are used only by the pci configuration.
|
||||
**
|
||||
** pci_conf_mode():
|
||||
** Probes for a pci system.
|
||||
** Returns 1 or 2 for pci configuration mechanism.
|
||||
** Returns 0 if no pci system.
|
||||
**
|
||||
** pcitag():
|
||||
** 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.
|
||||
**
|
||||
** pci_conf_read():
|
||||
** Read a long word from the pci configuration space.
|
||||
** Requires a tag (from pcitag) and the register
|
||||
** number (should be a long word alligned one).
|
||||
**
|
||||
** pci_conf_write():
|
||||
** Writes a long word to the pci configuration space.
|
||||
** Requires a tag (from pcitag), the register number
|
||||
** (should be a long word alligned one), and a value.
|
||||
**
|
||||
**-----------------------------------------------------------------
|
||||
*/
|
||||
|
||||
int pci_conf_mode (void);
|
||||
|
||||
pcici_t pcitag (unsigned char bus,
|
||||
unsigned char device,
|
||||
unsigned char func);
|
||||
|
||||
u_long pci_conf_read (pcici_t tag, u_long reg );
|
||||
void pci_conf_write (pcici_t tag, u_long reg, u_long data);
|
||||
|
||||
|
||||
/*------------------------------------------------------------------
|
||||
**
|
||||
** Names for PCI configuration space registers.
|
||||
**
|
||||
** Copyright (c) 1994 Charles Hannum. All rights reserved.
|
||||
**
|
||||
**------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/*
|
||||
* Device identification register; contains a vendor ID and a device ID.
|
||||
* We have little need to distinguish the two parts.
|
||||
*/
|
||||
** Device identification register; contains a vendor ID and a device ID.
|
||||
** We have little need to distinguish the two parts.
|
||||
*/
|
||||
#define PCI_ID_REG 0x00
|
||||
|
||||
/*
|
||||
* Command and status register.
|
||||
*/
|
||||
** Command and status register.
|
||||
*/
|
||||
#define PCI_COMMAND_STATUS_REG 0x04
|
||||
|
||||
#define PCI_COMMAND_IO_ENABLE 0x00000001
|
||||
@ -329,8 +76,8 @@ void pci_conf_write (pcici_t tag, u_long reg, u_long data);
|
||||
#define PCI_STATUS_PARITY_DETECT 0x80000000
|
||||
|
||||
/*
|
||||
* Class register; defines basic type of device.
|
||||
*/
|
||||
** Class register; defines basic type of device.
|
||||
*/
|
||||
#define PCI_CLASS_REG 0x08
|
||||
|
||||
#define PCI_CLASS_MASK 0xff000000
|
||||
@ -388,8 +135,8 @@ void pci_conf_write (pcici_t tag, u_long reg, u_long data);
|
||||
#define PCI_SUBCLASS_BRIDGE_MISC 0x00800000
|
||||
|
||||
/*
|
||||
* Mapping registers
|
||||
*/
|
||||
** Mapping registers
|
||||
*/
|
||||
#define PCI_MAP_REG_START 0x10
|
||||
#define PCI_MAP_REG_END 0x28
|
||||
|
||||
@ -403,9 +150,11 @@ void pci_conf_write (pcici_t tag, u_long reg, u_long data);
|
||||
#define PCI_MAP_MEMORY_CACHABLE 0x00000008
|
||||
#define PCI_MAP_MEMORY_ADDRESS_MASK 0xfffffff0
|
||||
|
||||
#define PCI_MAP_IO_ADDRESS_MASK 0xfffffffc
|
||||
|
||||
/*
|
||||
* Interrupt configuration register
|
||||
*/
|
||||
** Interrupt configuration register
|
||||
*/
|
||||
#define PCI_INTERRUPT_REG 0x3c
|
||||
|
||||
#define PCI_INTERRUPT_PIN_MASK 0x0000ff00
|
||||
|
@ -19,7 +19,7 @@
|
||||
* 4. Modifications may be freely made to this file if the above conditions
|
||||
* are met.
|
||||
*
|
||||
* $Id: aic7870.c,v 1.3 1995/01/22 00:47:50 gibbs Exp $
|
||||
* $Id: aic7870.c,v 1.4 1995/02/02 12:36:14 davidg Exp $
|
||||
*/
|
||||
|
||||
#include <pci.h>
|
||||
@ -29,6 +29,7 @@
|
||||
#include <scsi/scsi_all.h>
|
||||
#include <scsi/scsiconf.h>
|
||||
#include <pci/pcireg.h>
|
||||
#include <pci/pcivar.h>
|
||||
#include <i386/scsi/aic7xxx.h>
|
||||
|
||||
#define PCI_BASEADR0 PCI_MAP_REG_START
|
||||
@ -40,12 +41,15 @@ void aic7870_attach __P((pcici_t config_id, int unit));
|
||||
|
||||
static u_long aic7870_count;
|
||||
|
||||
struct pci_driver ahc_device = {
|
||||
struct pci_device ahc_device = {
|
||||
"ahc",
|
||||
aic7870_probe,
|
||||
aic7870_attach,
|
||||
&aic7870_count
|
||||
};
|
||||
|
||||
DATA_SET (pcidevice_set, ahc_device);
|
||||
|
||||
static char*
|
||||
aic7870_probe (pcici_t tag, pcidi_t type)
|
||||
{
|
||||
|
@ -21,7 +21,7 @@
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* $Id: if_de.c,v 1.13 1994/12/22 23:42:25 davidg Exp $
|
||||
* $Id: if_de.c,v 1.14 1995/02/02 12:36:15 davidg Exp $
|
||||
*
|
||||
*/
|
||||
|
||||
@ -46,6 +46,8 @@
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/errno.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <machine/clock.h>
|
||||
|
||||
#include <net/if.h>
|
||||
#include <net/if_types.h>
|
||||
@ -78,9 +80,9 @@
|
||||
|
||||
#include <pci.h>
|
||||
#if NPCI > 0
|
||||
#include <pci/pcireg.h>
|
||||
#include <pci/pcivar.h>
|
||||
#endif
|
||||
#include <i386/isa/icu.h>
|
||||
|
||||
#include <pci/dc21040.h>
|
||||
|
||||
/*
|
||||
@ -840,6 +842,8 @@ tulip_addr_filter(
|
||||
}
|
||||
}
|
||||
|
||||
/*extern void arp_ifinit(struct arpcom *, struct ifaddr*);*/
|
||||
|
||||
static int
|
||||
tulip_ioctl(
|
||||
struct ifnet *ifp,
|
||||
@ -1041,12 +1045,15 @@ 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 = {
|
||||
struct pci_device dedevice = {
|
||||
"de",
|
||||
tulip_pci_probe,
|
||||
tulip_pci_attach,
|
||||
&tulip_count,
|
||||
};
|
||||
|
||||
DATA_SET (pcidevice_set, dedevice);
|
||||
|
||||
#define PCI_CFID 0x00 /* Configuration ID */
|
||||
#define PCI_CFCS 0x04 /* Configurtion Command/Status */
|
||||
#define PCI_CFRV 0x08 /* Configuration Revision */
|
||||
|
196
sys/pci/ncr.c
196
sys/pci/ncr.c
@ -1,6 +1,6 @@
|
||||
/**************************************************************************
|
||||
**
|
||||
** $Id: ncr.c,v 1.14 1995/01/12 14:01:13 se Exp $
|
||||
** $Id: ncr.c,v 1.15 1995/02/02 12:36:16 davidg Exp $
|
||||
**
|
||||
** Device driver for the NCR 53C810 PCI-SCSI-Controller.
|
||||
**
|
||||
@ -44,15 +44,21 @@
|
||||
***************************************************************************
|
||||
*/
|
||||
|
||||
#define NCR_PATCHLEVEL "pl4 95/01/27"
|
||||
|
||||
#define NCR_VERSION (2)
|
||||
#define MAX_UNITS (16)
|
||||
|
||||
#ifndef LDSC
|
||||
/* belongs to sstat2 in ncrreg.h */
|
||||
#define LDSC 0x02 /* sta: disconnect & reconnect */
|
||||
#endif
|
||||
|
||||
/*==========================================================
|
||||
**
|
||||
** Configuration and Debugging
|
||||
**
|
||||
** May be overwritten in <i386/conf/XXXXX>
|
||||
** May be overwritten in <arch/conf/XXXXX>
|
||||
**
|
||||
**==========================================================
|
||||
*/
|
||||
@ -139,12 +145,6 @@
|
||||
*/
|
||||
|
||||
#define MAX_SIZE ((MAX_SCATTER-1) * NBPG)
|
||||
|
||||
/*
|
||||
** Write disk status information to dkstat ?
|
||||
*/
|
||||
|
||||
/* #define DK */
|
||||
|
||||
/*==========================================================
|
||||
**
|
||||
@ -163,19 +163,23 @@
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/buf.h>
|
||||
#include <sys/kernel.h>
|
||||
#ifdef DK
|
||||
#include <sys/dkstat.h>
|
||||
#endif /* DK */
|
||||
#ifndef __NetBSD__
|
||||
#include <machine/clock.h>
|
||||
#endif
|
||||
#include <vm/vm.h>
|
||||
#endif /* KERNEL */
|
||||
|
||||
#include <pci/ncrreg.h>
|
||||
|
||||
#ifdef __NetBSD__
|
||||
#include <sys/device.h>
|
||||
#include <i386/pci/pcivar.h>
|
||||
#endif /* __NetBSD */
|
||||
#ifndef __NetBSD__
|
||||
#include <pci/pcivar.h>
|
||||
#include <pci/pcireg.h>
|
||||
#include <pci/ncrreg.h>
|
||||
#else
|
||||
#include <sys/device.h>
|
||||
#include <i386/pci/ncrreg.h>
|
||||
#include <i386/pci/pcivar.h>
|
||||
#include <i386/pci/pcireg.h>
|
||||
#endif /* __NetBSD */
|
||||
|
||||
#include <scsi/scsi_all.h>
|
||||
#include <scsi/scsiconf.h>
|
||||
@ -1152,7 +1156,7 @@ struct script {
|
||||
ncrcmd data_in [MAX_SCATTER * 4 + 7];
|
||||
ncrcmd data_out [MAX_SCATTER * 4 + 7];
|
||||
ncrcmd aborttag [ 4];
|
||||
ncrcmd abort [ 20];
|
||||
ncrcmd abort [ 22];
|
||||
ncrcmd snooptest [ 11];
|
||||
};
|
||||
|
||||
@ -1222,7 +1226,7 @@ static void ncr_attach (pcici_t tag, int unit);
|
||||
|
||||
|
||||
static char ident[] =
|
||||
"\n$Id: ncr.c,v 1.14 1995/01/12 14:01:13 se Exp $\n";
|
||||
"\n$Id: ncr.c,v 1.15 1995/02/02 12:36:16 davidg Exp $\n";
|
||||
|
||||
u_long ncr_version = NCR_VERSION
|
||||
+ (u_long) sizeof (struct ncb)
|
||||
@ -1258,7 +1262,6 @@ static u_char rs_cmd [6] =
|
||||
*/
|
||||
|
||||
#define NCR_810_ID (0x00011000ul)
|
||||
#define NCR_815_ID (0x00041000ul)
|
||||
#define NCR_825_ID (0x00031000ul)
|
||||
|
||||
#ifdef __NetBSD__
|
||||
@ -1271,12 +1274,15 @@ struct cfdriver ncrcd = {
|
||||
|
||||
static u_long ncr_count;
|
||||
|
||||
struct pci_driver ncr_device = {
|
||||
struct pci_device ncr_device = {
|
||||
"ncr",
|
||||
ncr_probe,
|
||||
ncr_attach,
|
||||
&ncr_count
|
||||
};
|
||||
|
||||
DATA_SET (pcidevice_set, ncr_device);
|
||||
|
||||
#endif /* !__NetBSD__ */
|
||||
|
||||
#ifndef ANCIENT
|
||||
@ -2345,7 +2351,8 @@ static struct script script0 = {
|
||||
/*
|
||||
** DISCONNECTing ...
|
||||
**
|
||||
** Disable the "unexpected disconnect" feature.
|
||||
** disable the "unexpected disconnect" feature,
|
||||
** and remove the ACK signal.
|
||||
*/
|
||||
SCR_REG_REG (scntl2, SCR_AND, 0x7f),
|
||||
0,
|
||||
@ -2383,8 +2390,6 @@ static struct script script0 = {
|
||||
}/*-------------------------< MSG_OUT >-------------------*/,{
|
||||
/*
|
||||
** The target requests a message.
|
||||
** First remove ATN so the target will
|
||||
** not continue fetching messages.
|
||||
*/
|
||||
SCR_MOVE_ABS (1) ^ SCR_MSG_OUT,
|
||||
NADDR (msgout),
|
||||
@ -2824,6 +2829,8 @@ static struct script script0 = {
|
||||
SCR_COPY (1),
|
||||
RADDR (sfbr),
|
||||
NADDR (lastmsg),
|
||||
SCR_CLR (SCR_ACK),
|
||||
0,
|
||||
SCR_WAIT_DISC,
|
||||
0,
|
||||
SCR_JUMP,
|
||||
@ -3119,7 +3126,6 @@ ncr_probe(parent, self, aux)
|
||||
if (!pci_targmatch(cf, pa))
|
||||
return 0;
|
||||
if (pa->pa_id != NCR_810_ID &&
|
||||
pa->pa_id != NCR_815_ID &&
|
||||
pa->pa_id != NCR_825_ID)
|
||||
return 0;
|
||||
|
||||
@ -3136,9 +3142,6 @@ static char* ncr_probe (pcici_t tag, pcidi_t type)
|
||||
case NCR_810_ID:
|
||||
return ("ncr 53c810 scsi");
|
||||
|
||||
case NCR_815_ID:
|
||||
return ("ncr 53c815 scsi");
|
||||
|
||||
case NCR_825_ID:
|
||||
return ("ncr 53c825 wide scsi");
|
||||
}
|
||||
@ -3247,7 +3250,6 @@ static void ncr_attach (pcici_t config_id, int unit)
|
||||
case NCR_810_ID:
|
||||
np->maxwide = 0;
|
||||
break;
|
||||
case NCR_815_ID:
|
||||
case NCR_825_ID:
|
||||
np->maxwide = 1;
|
||||
break;
|
||||
@ -3296,6 +3298,31 @@ static void ncr_attach (pcici_t config_id, int unit)
|
||||
OUTB (nc_istat, SRST);
|
||||
OUTB (nc_istat, 0 );
|
||||
|
||||
#ifdef NCR_DUMP_REG
|
||||
/*
|
||||
** Log the initial register contents
|
||||
*/
|
||||
{
|
||||
int reg;
|
||||
#ifdef __NetBSD__
|
||||
u_long config_id = pa->pa_tag;
|
||||
#endif
|
||||
for (reg=0; reg<256; reg+=4) {
|
||||
if (reg%16==0) printf ("reg[%2x]", reg);
|
||||
printf (" %08x", (int)pci_conf_read (config_id, reg));
|
||||
if (reg%16==12) printf ("\n");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Reset chip, once again.
|
||||
*/
|
||||
|
||||
OUTB (nc_istat, SRST);
|
||||
OUTB (nc_istat, 0 );
|
||||
|
||||
#endif NCR_DUMP_REG
|
||||
|
||||
/*
|
||||
** Now check the cache handling of the pci chipset.
|
||||
*/
|
||||
@ -3333,8 +3360,12 @@ static void ncr_attach (pcici_t config_id, int unit)
|
||||
ncr_name (np));
|
||||
DELAY (1000000);
|
||||
#endif
|
||||
printf ("%s scanning for targets 0..%d ($Revision: 1.14 $)\n",
|
||||
ncr_name (np), MAX_TARGET-1);
|
||||
#ifdef NCR_PATCHLEVEL
|
||||
printf ("%s scanning for targets 0..%d (V%d " NCR_PATCHLEVEL ")\n",
|
||||
#else
|
||||
printf ("%s scanning for targets 0..%d (V%d)\n",
|
||||
#endif
|
||||
ncr_name (np), MAX_TARGET-1, NCR_VERSION);
|
||||
|
||||
/*
|
||||
** Now let the generic SCSI driver
|
||||
@ -3668,7 +3699,22 @@ static INT32 ncr_start (struct scsi_xfer * xp)
|
||||
**----------------------------------------------------
|
||||
*/
|
||||
|
||||
idmsg = (cp==&np->ccb ? 0x80 : 0xc0) | xp->LUN;
|
||||
#ifndef NCR_NO_DISCONNECT
|
||||
idmsg = (cp==&np->ccb ? M_IDENTIFY : 0xc0) | xp->LUN;
|
||||
#else
|
||||
/*---------------------------------------------------------------------
|
||||
** Some users have problems with this driver.
|
||||
** I assume that the current problems relate to a conflict between
|
||||
** a disconnect and an immediately following reconnect operation.
|
||||
** With this option you can prevent the driver from using disconnects.
|
||||
** If this removes the problems, I would know where to search further..
|
||||
** Of course this is no solution.
|
||||
** Without disconnects the performance will be severely degraded.
|
||||
** But it may help to trace down the core problem.
|
||||
**---------------------------------------------------------------------
|
||||
*/
|
||||
idmsg = M_IDENTIFY | xp->LUN;
|
||||
#endif
|
||||
|
||||
cp -> scsi_smsg [0] = idmsg;
|
||||
msglen=1;
|
||||
@ -3957,7 +4003,7 @@ void ncr_complete (ncb_p np, ccb_p cp)
|
||||
** Sanity check
|
||||
*/
|
||||
|
||||
if (!cp || !cp->magic || !cp->xfer) return;
|
||||
if (!cp || (cp->magic!=CCB_MAGIC) || !cp->xfer) return;
|
||||
cp->magic = 1;
|
||||
cp->tlimit= 0;
|
||||
|
||||
@ -4084,12 +4130,6 @@ void ncr_complete (ncb_p np, ccb_p cp)
|
||||
ncr_opennings (np, lp, xp);
|
||||
};
|
||||
|
||||
#ifdef DK
|
||||
dk_xfer[DK] ++;
|
||||
dk_wds [DK] += xp->datalen/64;
|
||||
dk_wpms[DK] = 1000000;
|
||||
#endif /* DK */
|
||||
|
||||
tp->bytes += xp->datalen;
|
||||
tp->transfers ++;
|
||||
|
||||
@ -4306,7 +4346,7 @@ void ncr_init (ncb_p np, char * msg, u_long code)
|
||||
OUTB (nc_scntl0, 0xca ); /* full arb., ena parity, par->ATN */
|
||||
OUTB (nc_scntl1, 0x00 ); /* odd parity, and remove CRST!! */
|
||||
OUTB (nc_scntl3, np->rv_scntl3);/* timing prescaler */
|
||||
OUTB (nc_scid , 0x40|np->myaddr);/* host adapter SCSI address */
|
||||
OUTB (nc_scid , RRE|np->myaddr);/* host adapter SCSI address */
|
||||
OUTW (nc_respid, 1ul<<np->myaddr);/* id to respond to */
|
||||
OUTB (nc_istat , SIGP ); /* Signal Process */
|
||||
OUTB (nc_dmode , 0xc0 ); /* Burst length = 16 transfer */
|
||||
@ -4684,6 +4724,10 @@ static void ncr_timeout (ncb_p np)
|
||||
ccb_p cp;
|
||||
|
||||
if (np->lasttime != thistime) {
|
||||
/*
|
||||
** block ncr interupts
|
||||
*/
|
||||
int oldspl = splbio();
|
||||
np->lasttime = thistime;
|
||||
|
||||
ncr_usercmd (np);
|
||||
@ -4781,12 +4825,9 @@ static void ncr_timeout (ncb_p np)
|
||||
/*
|
||||
** wakeup this ccb.
|
||||
*/
|
||||
{
|
||||
int oldspl = splbio();
|
||||
ncr_complete (np, cp);
|
||||
splx (oldspl);
|
||||
};
|
||||
ncr_complete (np, cp);
|
||||
};
|
||||
splx (oldspl);
|
||||
}
|
||||
|
||||
timeout (TIMEOUT ncr_timeout, (caddr_t) np, step ? step : 1);
|
||||
@ -4819,6 +4860,7 @@ void ncr_exception (ncb_p np)
|
||||
u_char istat, dstat;
|
||||
u_short sist;
|
||||
u_long dsp;
|
||||
int i;
|
||||
|
||||
/*
|
||||
** interrupt on the fly ?
|
||||
@ -4935,13 +4977,47 @@ void ncr_exception (ncb_p np)
|
||||
np->regdump.nc_dstat = dstat;
|
||||
np->regdump.nc_sist = sist;
|
||||
};
|
||||
|
||||
/*=========================================
|
||||
** log message for real hard errors
|
||||
**=========================================
|
||||
|
||||
printf ("%s targ %d?: ERROR (%x:%x:%x) (%x/%x) @ (%x:%x).\n",
|
||||
"ncr0 targ 0?: ERROR (ds:si) (so-si-sd) (sxfer/scntl3) @ (dsp:dbc)."
|
||||
" reg: r0 r1 r2 r3 r4 r5 r6 ..... rf."
|
||||
|
||||
exception register:
|
||||
ds: dstat
|
||||
si: sist
|
||||
|
||||
SCSI bus lines:
|
||||
so: control lines as driver by NCR.
|
||||
si: control lines as seen by NCR.
|
||||
sd: scsi data lines as seen by NCR.
|
||||
|
||||
wide/fastmode:
|
||||
sxfer: (see the manual)
|
||||
scntl3: (see the manual)
|
||||
|
||||
current script command:
|
||||
dsp: script adress (relative to start of script).
|
||||
dbc: first word of script command.
|
||||
|
||||
First 16 register of the chip:
|
||||
r0..rf
|
||||
|
||||
=============================================
|
||||
*/
|
||||
|
||||
printf ("%s targ %d?: ERROR (%x:%x) (%x-%x-%x) (%x/%x) @ (%x:%x).\n",
|
||||
ncr_name (np), INB (nc_ctest0)&7, dstat, sist,
|
||||
INB (nc_sbcl),
|
||||
INB (nc_socl), INB (nc_sbcl), INB (nc_sbdl),
|
||||
INB (nc_sxfer),INB (nc_scntl3),
|
||||
(unsigned) (dsp = INL (nc_dsp)),
|
||||
((unsigned) (dsp = INL (nc_dsp))) - (unsigned) np->p_script,
|
||||
(unsigned) INL (nc_dbc));
|
||||
printf (" reg:");
|
||||
for (i=0; i<16;i++)
|
||||
printf (" %x", ((u_char*)np->reg)[i]);
|
||||
printf (".\n");
|
||||
|
||||
/*----------------------------------------
|
||||
** clean up the dma fifo
|
||||
@ -4980,15 +5056,27 @@ void ncr_exception (ncb_p np)
|
||||
!(dstat & (MDPE|BF|ABRT|SIR)) &&
|
||||
((INL(nc_dbc) & 0xf8000000) == SCR_WAIT_DISC)) {
|
||||
/*
|
||||
** Data cycles while waiting for disconnect.
|
||||
** Force disconnect.
|
||||
** Unexpected data cycle while waiting for disconnect.
|
||||
*/
|
||||
OUTB (nc_scntl1, 0);
|
||||
if (INB(nc_sstat2) & LDSC) {
|
||||
/*
|
||||
** It's an early reconnect.
|
||||
** Let's continue ...
|
||||
*/
|
||||
OUTB (nc_dcntl, (STD|NOCOM));
|
||||
/*
|
||||
** info message
|
||||
*/
|
||||
printf ("%s: XXX INFO: LDSC while IID.\n",
|
||||
ncr_name (np));
|
||||
return;
|
||||
};
|
||||
printf ("%s: target %d? doesn't release the bus.\n",
|
||||
ncr_name (np), INB (nc_ctest0)&7);
|
||||
/*
|
||||
** System may hang, but timeout will handle that.
|
||||
** In fact, timeout can handle ALL problems :-)
|
||||
** return without restarting the NCR.
|
||||
** timeout will do the real work.
|
||||
*/
|
||||
OUTB (nc_dcntl, (STD|NOCOM));
|
||||
return;
|
||||
};
|
||||
|
||||
@ -5914,7 +6002,7 @@ static ccb_p ncr_get_ccb
|
||||
|
||||
while (cp->magic) {
|
||||
if (flags & SCSI_NOSLEEP) break;
|
||||
if (tsleep ((caddr_t)cp, PZERO|PCATCH, "ncr", 0))
|
||||
if (tsleep ((caddr_t)cp, PRIBIO|PCATCH, "ncr", 0))
|
||||
break;
|
||||
};
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
/**************************************************************************
|
||||
**
|
||||
** $Id: ncrreg.h,v 2.3 94/10/09 21:10:34 wolf Oct11 $
|
||||
** $Id: ncrreg.h,v 1.1 1994/10/12 02:21:56 se Exp $
|
||||
**
|
||||
** Device driver for the NCR 53C810 PCI-SCSI-Controller.
|
||||
**
|
||||
@ -123,6 +123,7 @@ struct ncr_reg {
|
||||
#define ILF1 0x80 /* sta: data in SIDL register msb[W]*/
|
||||
#define ORF1 0x40 /* sta: data in SODR register msb[W]*/
|
||||
#define OLF1 0x20 /* sta: data in SODL register msb[W]*/
|
||||
#define LDSC 0x02 /* sta: disconnect & reconnect */
|
||||
|
||||
/*10*/ u_long nc_dsa; /* --> Base page */
|
||||
|
||||
|
313
sys/pci/pci.c
313
sys/pci/pci.c
@ -1,6 +1,6 @@
|
||||
/**************************************************************************
|
||||
**
|
||||
** $Id: pci.c,v 1.9 1994/11/02 23:47:13 se Exp $
|
||||
** $Id: pci.c,v 1.10 1995/02/02 12:36:18 davidg Exp $
|
||||
**
|
||||
** General subroutines for the PCI bus on 80*86 systems.
|
||||
** pci_configure ()
|
||||
@ -56,62 +56,38 @@
|
||||
#include <sys/systm.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/errno.h>
|
||||
#include <sys/kernel.h>
|
||||
|
||||
#include <vm/vm.h>
|
||||
#include <vm/vm_param.h>
|
||||
|
||||
#include <i386/isa/isa.h>
|
||||
#include <i386/isa/isa_device.h>
|
||||
#include <i386/isa/icu.h>
|
||||
#include <pci/pcivar.h>
|
||||
#include <pci/pcireg.h>
|
||||
#include <pci/pcibus.h>
|
||||
|
||||
#ifdef __FreeBSD2__
|
||||
#include <sys/devconf.h>
|
||||
|
||||
|
||||
struct pci_devconf {
|
||||
struct kern_devconf pdc_kdc;
|
||||
struct pci_info pdc_pi;
|
||||
};
|
||||
#endif
|
||||
|
||||
static int
|
||||
pci_externalize (struct proc *, struct kern_devconf *, void *, size_t);
|
||||
|
||||
static int
|
||||
pci_internalize (struct proc *, struct kern_devconf *, void *, size_t);
|
||||
#else /* __FreeBSD2__ */
|
||||
|
||||
/*
|
||||
** Function prototypes missing in system headers
|
||||
*/
|
||||
|
||||
#ifndef __FreeBSD2__
|
||||
extern pmap_t pmap_kernel(void);
|
||||
static vm_offset_t pmap_mapdev (vm_offset_t paddr, vm_size_t vsize);
|
||||
#endif /* __FreeBSD2__ */
|
||||
|
||||
/*
|
||||
* Type of the first (asm) part of an interrupt handler.
|
||||
*/
|
||||
typedef void inthand_t __P((u_int cs, u_int ef, u_int esp, u_int ss));
|
||||
|
||||
/*
|
||||
* Usual type of the second (C) part of an interrupt handler. Some bogus
|
||||
* ones need the arg to be the interrupt frame (and not a copy of it, which
|
||||
* is all that is possible in C).
|
||||
*/
|
||||
typedef void inthand2_t __P((int unit));
|
||||
|
||||
/*
|
||||
** 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.
|
||||
*/
|
||||
|
||||
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__ */
|
||||
|
||||
/*========================================================
|
||||
**
|
||||
@ -138,6 +114,20 @@ extern unsigned intr_mask[ICU_LEN];
|
||||
|
||||
static vm_offset_t pci_paddr = PCI_PMEM_START;
|
||||
|
||||
/*--------------------------------------------------------
|
||||
**
|
||||
** The pci ports can be mapped to any address.
|
||||
** As default we start at 0x400
|
||||
**
|
||||
**--------------------------------------------------------
|
||||
*/
|
||||
|
||||
#ifndef PCI_PORT_START
|
||||
#define PCI_PORT_START 0x0400
|
||||
#endif
|
||||
|
||||
static u_short pci_ioaddr = PCI_PORT_START;
|
||||
|
||||
/*--------------------------------------------------------
|
||||
**
|
||||
** The pci device interrupt lines should have been
|
||||
@ -172,15 +162,6 @@ static unsigned long pci_seen[NPCI];
|
||||
|
||||
static int pci_conf_count;
|
||||
|
||||
#ifdef __FreeBSD2__
|
||||
static int
|
||||
pci_externalize (struct proc *, struct kern_devconf *, void *, size_t);
|
||||
|
||||
static int
|
||||
pci_internalize (struct proc *, struct kern_devconf *, void *, size_t);
|
||||
|
||||
#endif /* __FreeBSD2__ */
|
||||
|
||||
void pci_configure()
|
||||
{
|
||||
u_char device,last_device;
|
||||
@ -194,19 +175,28 @@ void pci_configure()
|
||||
int irq;
|
||||
char* name=0;
|
||||
vm_offset_t old_addr=pci_paddr;
|
||||
u_short old_ioaddr=pci_ioaddr;
|
||||
|
||||
struct pci_driver *drp=0;
|
||||
struct pci_device *dvp;
|
||||
int dvi;
|
||||
struct pci_device *dvp=0;
|
||||
|
||||
#ifdef __FreeBSD2__
|
||||
struct pci_devconf *pdcp;
|
||||
#endif
|
||||
|
||||
/*
|
||||
** first check pci bus driver available
|
||||
*/
|
||||
|
||||
if (pcibus_set.ls_length <= 0)
|
||||
return;
|
||||
|
||||
#define pcibus (*((struct pcibus*) pcibus_set.ls_items[0]))
|
||||
/*
|
||||
** check pci bus present
|
||||
*/
|
||||
|
||||
pci_mechanism = pci_conf_mode ();
|
||||
pci_mechanism = pcibus.pb_mode ();
|
||||
if (!pci_mechanism) return;
|
||||
last_device = pci_mechanism==1 ? 31 : 15;
|
||||
|
||||
@ -217,16 +207,16 @@ void pci_configure()
|
||||
|
||||
for (bus=0;bus<NPCI;bus++) {
|
||||
#ifndef PCI_QUIET
|
||||
printf ("pci%d: scanning device 0..%d, mechanism=%d.\n",
|
||||
bus, last_device, pci_mechanism);
|
||||
printf ("%s%d: scanning device 0..%d, mechanism=%d.\n",
|
||||
pcibus.pb_name, bus, last_device, pci_mechanism);
|
||||
#endif
|
||||
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);
|
||||
tag = pcibus.pb_tag (bus, device, 0);
|
||||
type = pcibus.pb_read (tag, PCI_ID_REG);
|
||||
|
||||
if ((!type) || (type==0xfffffffful)) continue;
|
||||
|
||||
@ -234,19 +224,18 @@ void pci_configure()
|
||||
** lookup device in ioconfiguration:
|
||||
*/
|
||||
|
||||
for (dvp = pci_devtab; dvp->pd_name; dvp++) {
|
||||
drp = dvp->pd_driver;
|
||||
if (!drp)
|
||||
continue;
|
||||
if ((name=(*drp->probe)(tag, type)))
|
||||
for (dvi=0; dvi<pcidevice_set.ls_length; dvi++) {
|
||||
dvp = (struct pci_device*) pcidevice_set.ls_items[dvi];
|
||||
if ((name=(*dvp->pd_probe)(tag, type)))
|
||||
break;
|
||||
dvp = NULL;
|
||||
};
|
||||
|
||||
if (!dvp->pd_name) {
|
||||
if (dvp==NULL) {
|
||||
#ifndef PCI_QUIET
|
||||
if (pci_conf_count)
|
||||
continue;
|
||||
printf("pci%d:%d: ", bus, device);
|
||||
printf("%s%d:%d: ", pcibus.pb_name, bus, device);
|
||||
not_supported (tag, type);
|
||||
#endif
|
||||
continue;
|
||||
@ -257,7 +246,7 @@ void pci_configure()
|
||||
** Get and increment the unit.
|
||||
*/
|
||||
|
||||
unit = (*drp->count)++;
|
||||
unit = (*dvp->pd_count)++;
|
||||
|
||||
/*
|
||||
** ignore device ?
|
||||
@ -276,7 +265,7 @@ void pci_configure()
|
||||
** from the pci configuration space.
|
||||
*/
|
||||
|
||||
data = pci_conf_read (tag, PCI_INTERRUPT_REG);
|
||||
data = pcibus.pb_read (tag, PCI_INTERRUPT_REG);
|
||||
pciint = PCI_INTERRUPT_PIN_EXTRACT(data);
|
||||
|
||||
if (pciint) {
|
||||
@ -295,7 +284,7 @@ void pci_configure()
|
||||
|
||||
data = PCI_INTERRUPT_LINE_INSERT(data, irq);
|
||||
printf (" (config)");
|
||||
pci_conf_write (tag, PCI_INTERRUPT_REG, data);
|
||||
pcibus.pb_write (tag, PCI_INTERRUPT_REG, data);
|
||||
};
|
||||
|
||||
irq = PCI_INTERRUPT_LINE_EXTRACT(data);
|
||||
@ -315,10 +304,10 @@ void pci_configure()
|
||||
** enable memory access
|
||||
*/
|
||||
|
||||
data = (pci_conf_read (tag, PCI_COMMAND_STATUS_REG)
|
||||
data = (pcibus.pb_read (tag, PCI_COMMAND_STATUS_REG)
|
||||
& 0xffff) | PCI_COMMAND_MEM_ENABLE;
|
||||
|
||||
pci_conf_write (tag, (u_char) PCI_COMMAND_STATUS_REG, data);
|
||||
pcibus.pb_write (tag, (u_char) PCI_COMMAND_STATUS_REG, data);
|
||||
|
||||
/*
|
||||
** show pci slot.
|
||||
@ -333,7 +322,7 @@ void pci_configure()
|
||||
*/
|
||||
|
||||
pdcp = (struct pci_devconf *)
|
||||
malloc (sizeof (struct pci_devconf),M_DEVBUF,M_WAITOK);
|
||||
malloc (sizeof (struct pci_devconf),M_DEVBUF,M_WAITOK);
|
||||
|
||||
/*
|
||||
** Fill in.
|
||||
@ -378,7 +367,7 @@ void pci_configure()
|
||||
** i.e. when installing subdevices.
|
||||
*/
|
||||
|
||||
(*drp->attach) (tag, unit);
|
||||
(*dvp->pd_attach) (tag, unit);
|
||||
};
|
||||
};
|
||||
|
||||
@ -386,10 +375,43 @@ void pci_configure()
|
||||
if (pci_paddr != old_addr)
|
||||
printf ("pci uses physical addresses from 0x%lx to 0x%lx\n",
|
||||
(u_long)PCI_PMEM_START, (u_long)pci_paddr);
|
||||
if (pci_ioaddr != old_ioaddr)
|
||||
printf ("pci devices use ioports from 0x%x to 0x%x\n",
|
||||
(unsigned)PCI_PORT_START, (unsigned)pci_ioaddr);
|
||||
#endif
|
||||
pci_conf_count++;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------
|
||||
**
|
||||
** The following functions are provided for the device driver
|
||||
** to read/write the configuration space.
|
||||
**
|
||||
** pci_conf_read():
|
||||
** Read a long word from the pci configuration space.
|
||||
** Requires a tag (from pcitag) and the register
|
||||
** number (should be a long word alligned one).
|
||||
**
|
||||
** pci_conf_write():
|
||||
** Writes a long word to the pci configuration space.
|
||||
** Requires a tag (from pcitag), the register number
|
||||
** (should be a long word alligned one), and a value.
|
||||
**
|
||||
**-----------------------------------------------------------------
|
||||
*/
|
||||
|
||||
u_long
|
||||
pci_conf_read (pcici_t tag, u_long reg)
|
||||
{
|
||||
return (pcibus.pb_read (tag, reg));
|
||||
}
|
||||
|
||||
void
|
||||
pci_conf_write (pcici_t tag, u_long reg, u_long data)
|
||||
{
|
||||
pcibus.pb_write (tag, reg, data);
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------
|
||||
**
|
||||
** Map device into port space.
|
||||
@ -401,11 +423,78 @@ void pci_configure()
|
||||
|
||||
int pci_map_port (pcici_t tag, u_long reg, u_short* pa)
|
||||
{
|
||||
u_long data;
|
||||
u_short size;
|
||||
|
||||
/*
|
||||
** @MAPIO@ not yet implemented.
|
||||
** sanity check
|
||||
*/
|
||||
printf ("pci_map_port failed: not yet implemented\n");
|
||||
return (0);
|
||||
|
||||
if (reg < PCI_MAP_REG_START || reg >= PCI_MAP_REG_END || (reg & 3)) {
|
||||
printf ("pci_map_port failed: bad register=0x%x\n",
|
||||
(unsigned)reg);
|
||||
return (0);
|
||||
};
|
||||
|
||||
/*
|
||||
** get size and type of port
|
||||
**
|
||||
** type is in the lowest two bits.
|
||||
** If device requires 2^n bytes, the next
|
||||
** n-2 bits are hardwired as 0.
|
||||
*/
|
||||
|
||||
pcibus.pb_write (tag, reg, 0xfffffffful);
|
||||
data = pcibus.pb_read (tag, reg);
|
||||
|
||||
switch (data & 0x03) {
|
||||
|
||||
case PCI_MAP_IO:
|
||||
break;
|
||||
|
||||
default: /* unknown */
|
||||
printf ("pci_map_port failed: bad port type=0x%x\n",
|
||||
(unsigned) data);
|
||||
return (0);
|
||||
};
|
||||
|
||||
/*
|
||||
** get the size
|
||||
*/
|
||||
|
||||
size = -(data & PCI_MAP_IO_ADDRESS_MASK);
|
||||
|
||||
if (!size) return (0);
|
||||
|
||||
/*
|
||||
** align physical address to virtual size
|
||||
*/
|
||||
|
||||
if ((data = pci_ioaddr % size))
|
||||
pci_ioaddr += size - data;
|
||||
|
||||
#ifndef PCI_QUIET
|
||||
/*
|
||||
** display values.
|
||||
*/
|
||||
|
||||
printf ("\treg%d: ioaddr=0x%x size=0x%x\n",
|
||||
(unsigned) reg, (unsigned) pci_ioaddr, (unsigned) size);
|
||||
#endif
|
||||
|
||||
/*
|
||||
** return them to the driver
|
||||
*/
|
||||
|
||||
*pa = pci_ioaddr;
|
||||
|
||||
/*
|
||||
** and don't forget to increment pci_ioaddr
|
||||
*/
|
||||
|
||||
pci_ioaddr += size;
|
||||
|
||||
return (1);
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------
|
||||
@ -427,10 +516,10 @@ 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)) {
|
||||
printf ("pci_map_mem failed: bad register=0x%x\n",
|
||||
(unsigned)reg);
|
||||
return (0);
|
||||
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);
|
||||
};
|
||||
|
||||
/*
|
||||
@ -441,8 +530,8 @@ int pci_map_mem (pcici_t tag, u_long reg, vm_offset_t* va, vm_offset_t* pa)
|
||||
** n-4 bits are read as 0.
|
||||
*/
|
||||
|
||||
pci_conf_write (tag, reg, 0xfffffffful);
|
||||
data = pci_conf_read (tag, reg);
|
||||
pcibus.pb_write (tag, reg, 0xfffffffful);
|
||||
data = pcibus.pb_read (tag, reg);
|
||||
|
||||
switch (data & 0x0f) {
|
||||
|
||||
@ -450,9 +539,9 @@ int pci_map_mem (pcici_t tag, u_long reg, vm_offset_t* va, vm_offset_t* pa)
|
||||
break;
|
||||
|
||||
default: /* unknown */
|
||||
printf ("pci_map_mem failed: bad memory type=0x%x\n",
|
||||
(unsigned) data);
|
||||
return (0);
|
||||
printf ("pci_map_mem failed: bad memory type=0x%x\n",
|
||||
(unsigned) data);
|
||||
return (0);
|
||||
};
|
||||
|
||||
/*
|
||||
@ -496,7 +585,7 @@ int pci_map_mem (pcici_t tag, u_long reg, vm_offset_t* va, vm_offset_t* pa)
|
||||
** set device address
|
||||
*/
|
||||
|
||||
pci_conf_write (tag, reg, pci_paddr);
|
||||
pcibus.pb_write (tag, reg, pci_paddr);
|
||||
|
||||
/*
|
||||
** and don't forget to increment pci_paddr
|
||||
@ -519,29 +608,29 @@ pci_externalize (struct proc *p, struct kern_devconf *kdcp, void *u, size_t l)
|
||||
{
|
||||
struct pci_externalize_buffer buffer;
|
||||
struct pci_info * pip = kdcp->kdc_parentdata;
|
||||
pcici_t tag;
|
||||
pcici_t tag;
|
||||
int i;
|
||||
|
||||
if (l < sizeof buffer) {
|
||||
return ENOMEM;
|
||||
return ENOMEM;
|
||||
};
|
||||
|
||||
tag = pcitag (pip->pi_bus, pip->pi_device, 0);
|
||||
tag = pcibus.pb_tag (pip->pi_bus, pip->pi_device, 0);
|
||||
|
||||
buffer.peb_pci_info = *pip;
|
||||
|
||||
for (i=0; i<PCI_EXT_CONF_LEN; i++) {
|
||||
buffer.peb_config[i] = pci_conf_read (tag, i*4);
|
||||
buffer.peb_config[i] = pcibus.pb_read (tag, i*4);
|
||||
};
|
||||
|
||||
return copyout(&buffer, u, sizeof buffer);
|
||||
return copyout(&buffer, u, sizeof buffer);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
pci_internalize (struct proc *p, struct kern_devconf *kdcp, void *u, size_t s)
|
||||
{
|
||||
return EOPNOTSUPP;
|
||||
return EOPNOTSUPP;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------
|
||||
@ -551,60 +640,24 @@ pci_internalize (struct proc *p, struct kern_devconf *kdcp, void *u, size_t s)
|
||||
**-----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static unsigned int pci_int_mask [16];
|
||||
|
||||
int pci_map_int (pcici_t tag, int(*func)(), void* arg, unsigned* maskptr)
|
||||
{
|
||||
int irq;
|
||||
unsigned mask;
|
||||
int irq, result;
|
||||
|
||||
irq = PCI_INTERRUPT_LINE_EXTRACT(
|
||||
pci_conf_read (tag, PCI_INTERRUPT_REG));
|
||||
pcibus.pb_read (tag, PCI_INTERRUPT_REG));
|
||||
|
||||
if (irq >= 16 || irq <= 0) {
|
||||
printf ("pci_map_int failed: no int line set.\n");
|
||||
return (0);
|
||||
}
|
||||
|
||||
mask = 1ul << irq;
|
||||
result = pcibus.pb_regint (tag, func, arg, maskptr);
|
||||
|
||||
if (!maskptr)
|
||||
maskptr = &pci_int_mask[irq];
|
||||
|
||||
INTRMASK (*maskptr, mask);
|
||||
|
||||
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 & *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;
|
||||
if (!result) {
|
||||
printf ("pci_map_int failed.\n");
|
||||
return (0);
|
||||
};
|
||||
#endif
|
||||
|
||||
INTREN (mask);
|
||||
|
||||
return (1);
|
||||
}
|
||||
@ -659,14 +712,14 @@ void not_supported (pcici_t tag, u_long type)
|
||||
|
||||
printf (", device=0x%lx", type >> 16);
|
||||
|
||||
data = (pci_conf_read(tag, PCI_CLASS_REG) >> 24) & 0xff;
|
||||
data = (pcibus.pb_read(tag, PCI_CLASS_REG) >> 24) & 0xff;
|
||||
if (data < sizeof(majclasses) / sizeof(majclasses[0]))
|
||||
printf(", class=%s", majclasses[data]);
|
||||
|
||||
printf (" [not supported]\n");
|
||||
|
||||
for (reg=PCI_MAP_REG_START; reg<PCI_MAP_REG_END; reg+=4) {
|
||||
data = pci_conf_read (tag, reg);
|
||||
data = pcibus.pb_read (tag, reg);
|
||||
if (!data) continue;
|
||||
switch (data&7) {
|
||||
|
||||
|
287
sys/pci/pcireg.h
287
sys/pci/pcireg.h
@ -1,10 +1,12 @@
|
||||
/**************************************************************************
|
||||
**
|
||||
** $Id: pcireg.h,v 1.1 1994/10/12 02:25:03 se Exp $
|
||||
** $Id: pcireg.h,v 1.1 1995/02/01 22:56:50 se Exp $
|
||||
**
|
||||
** Declarations for pci bus drivers.
|
||||
** Names for PCI configuration space registers.
|
||||
**
|
||||
** 386bsd / FreeBSD
|
||||
** Copyright (c) 1994 Charles Hannum. All rights reserved.
|
||||
**
|
||||
** FreeBSD
|
||||
**
|
||||
**-------------------------------------------------------------------------
|
||||
**
|
||||
@ -38,271 +40,16 @@
|
||||
#ifndef __PCI_REG_H__
|
||||
#define __PCI_REG_H__
|
||||
|
||||
/*-----------------------------------------------------------------
|
||||
**
|
||||
** main pci initialization function.
|
||||
** called at boot time from autoconf.c
|
||||
**
|
||||
**-----------------------------------------------------------------
|
||||
*/
|
||||
|
||||
void pci_configure (void);
|
||||
|
||||
/*-----------------------------------------------------------------
|
||||
**
|
||||
** The pci configuration id describes a pci device on the bus.
|
||||
** It is constructed from: bus, device & function numbers.
|
||||
**
|
||||
**-----------------------------------------------------------------
|
||||
*/
|
||||
|
||||
typedef union {
|
||||
u_long cfg1;
|
||||
struct {
|
||||
u_char enable;
|
||||
u_char forward;
|
||||
u_short port;
|
||||
} cfg2;
|
||||
} pcici_t;
|
||||
|
||||
/*-----------------------------------------------------------------
|
||||
**
|
||||
** Each pci device has an unique device id.
|
||||
** It is used to find a matching driver.
|
||||
**
|
||||
**-----------------------------------------------------------------
|
||||
*/
|
||||
|
||||
typedef u_long pcidi_t;
|
||||
|
||||
/*-----------------------------------------------------------------
|
||||
**
|
||||
** The pci driver structure.
|
||||
**
|
||||
** probe: Checks if the driver can support a device
|
||||
** with this type. The tag may be used to get
|
||||
** more info with pci_read_conf(). See below.
|
||||
** It returns a string with the devices name,
|
||||
** or a NULL pointer, if the driver cannot
|
||||
** support this device.
|
||||
**
|
||||
** attach: Allocate a control structure and prepare
|
||||
** it. This function may use the pci mapping
|
||||
** functions. See below.
|
||||
** (configuration id) or type.
|
||||
**
|
||||
** count: A pointer to a unit counter.
|
||||
** It's used by the pci configurator to
|
||||
** allocate unit numbers.
|
||||
**
|
||||
**-----------------------------------------------------------------
|
||||
*/
|
||||
|
||||
struct pci_driver {
|
||||
char* (*probe ) (pcici_t tag, pcidi_t type);
|
||||
void (*attach) (pcici_t tag, int unit);
|
||||
u_long *count;
|
||||
};
|
||||
|
||||
/*-----------------------------------------------------------------
|
||||
**
|
||||
** The pci-devconf interface.
|
||||
**
|
||||
**-----------------------------------------------------------------
|
||||
*/
|
||||
|
||||
struct pci_info {
|
||||
u_short pi_bus;
|
||||
u_short pi_device;
|
||||
};
|
||||
|
||||
#define PCI_EXT_CONF_LEN (16)
|
||||
#define PCI_EXTERNAL_LEN (sizeof(struct pci_externalize_buffer))
|
||||
|
||||
struct pci_externalize_buffer {
|
||||
struct pci_info peb_pci_info;
|
||||
u_long peb_config[PCI_EXT_CONF_LEN];
|
||||
};
|
||||
|
||||
|
||||
/*-----------------------------------------------------------------
|
||||
**
|
||||
** Per device structure.
|
||||
**
|
||||
** An array of this structure should be created by the
|
||||
** config utility and live in "ioconf.c".
|
||||
**
|
||||
** At the moment it's created by hand and lives in
|
||||
** pci_config.c
|
||||
**
|
||||
** pd_driver:
|
||||
** a pointer to the driver structure.
|
||||
**
|
||||
** pd_name:
|
||||
** the name of the devices which are supported
|
||||
** by this driver for kernel messages.
|
||||
**
|
||||
** pd_flags:
|
||||
** for further study.
|
||||
**
|
||||
**-----------------------------------------------------------------
|
||||
*/
|
||||
|
||||
struct pci_device {
|
||||
struct
|
||||
pci_driver* pd_driver;
|
||||
const char * pd_name;
|
||||
int pd_flags;
|
||||
};
|
||||
|
||||
/*-----------------------------------------------------------------
|
||||
**
|
||||
** This table should be generated in file "ioconf.c"
|
||||
** by the config program.
|
||||
** It is used at boot time by the configuration function
|
||||
** pci_configure()
|
||||
**
|
||||
**-----------------------------------------------------------------
|
||||
*/
|
||||
|
||||
extern struct pci_device pci_devtab[];
|
||||
|
||||
/*-----------------------------------------------------------------
|
||||
**
|
||||
** Map a pci device to physical and virtual memory.
|
||||
**
|
||||
** The va and pa addresses are "in/out" parameters.
|
||||
** If they are 0 on entry, the function assigns an address.
|
||||
**
|
||||
** Entry selects the register in the pci configuration
|
||||
** space, which supplies the size of the region, and
|
||||
** receives the physical address.
|
||||
**
|
||||
** If there is any error, a message is written, and
|
||||
** the function returns with zero.
|
||||
** Else it returns with a value different to zero.
|
||||
**
|
||||
**-----------------------------------------------------------------
|
||||
*/
|
||||
|
||||
int pci_map_mem (pcici_t tag, u_long entry, u_long * va, u_long * pa);
|
||||
|
||||
/*-----------------------------------------------------------------
|
||||
**
|
||||
** Map a pci device to an io port area.
|
||||
**
|
||||
** *pa is an "in/out" parameter.
|
||||
** If it's 0 on entry, the function assigns an port number..
|
||||
**
|
||||
** Entry selects the register in the pci configuration
|
||||
** space, which supplies the size of the region, and
|
||||
** receives the port number.
|
||||
**
|
||||
** If there is any error, a message is written, and
|
||||
** the function returns with zero.
|
||||
** Else it returns with a value different to zero.
|
||||
**
|
||||
**-----------------------------------------------------------------
|
||||
*/
|
||||
|
||||
int pci_map_port(pcici_t tag, u_long entry, u_short * pa);
|
||||
|
||||
/*-----------------------------------------------------------------
|
||||
**
|
||||
** Map a pci interrupt to an isa irq line,
|
||||
** and enable the interrupt.
|
||||
**
|
||||
** func is the interrupt handler, arg is the argument
|
||||
** to this function.
|
||||
**
|
||||
** The maskptr argument should be &bio_imask,
|
||||
** &net_imask etc. or NULL.
|
||||
**
|
||||
** If there is any error, a message is written, and
|
||||
** the function returns with zero.
|
||||
** Else it returns with a value different to zero.
|
||||
**
|
||||
** A word of caution for FreeBSD 2.0:
|
||||
**
|
||||
** We use the register_intr() function.
|
||||
**
|
||||
** The interrupt line of the selected device is included
|
||||
** into the supplied mask: after the corresponding splXXX
|
||||
** this drivers interrupts are blocked.
|
||||
**
|
||||
** But in the interrupt handlers startup code ONLY
|
||||
** the interrupt of the driver is blocked, and NOT
|
||||
** all interrupts of the spl group.
|
||||
**
|
||||
** It may be required to additional block the group
|
||||
** interrupts by splXXX() inside the interrupt handler.
|
||||
**
|
||||
** In pre 2.0 kernels we emulate the register_intr
|
||||
** function. The emulating function blocks all interrupts
|
||||
** of the group in the interrupt handler prefix code.
|
||||
**
|
||||
**-----------------------------------------------------------------
|
||||
*/
|
||||
|
||||
int pci_map_int (pcici_t tag, int (*func)(), void* arg, unsigned * maskptr);
|
||||
|
||||
/*-----------------------------------------------------------------
|
||||
**
|
||||
** The following functions are provided by the pci bios.
|
||||
** They are used only by the pci configuration.
|
||||
**
|
||||
** pci_conf_mode():
|
||||
** Probes for a pci system.
|
||||
** Returns 1 or 2 for pci configuration mechanism.
|
||||
** Returns 0 if no pci system.
|
||||
**
|
||||
** pcitag():
|
||||
** 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.
|
||||
**
|
||||
** pci_conf_read():
|
||||
** Read a long word from the pci configuration space.
|
||||
** Requires a tag (from pcitag) and the register
|
||||
** number (should be a long word alligned one).
|
||||
**
|
||||
** pci_conf_write():
|
||||
** Writes a long word to the pci configuration space.
|
||||
** Requires a tag (from pcitag), the register number
|
||||
** (should be a long word alligned one), and a value.
|
||||
**
|
||||
**-----------------------------------------------------------------
|
||||
*/
|
||||
|
||||
int pci_conf_mode (void);
|
||||
|
||||
pcici_t pcitag (unsigned char bus,
|
||||
unsigned char device,
|
||||
unsigned char func);
|
||||
|
||||
u_long pci_conf_read (pcici_t tag, u_long reg );
|
||||
void pci_conf_write (pcici_t tag, u_long reg, u_long data);
|
||||
|
||||
|
||||
/*------------------------------------------------------------------
|
||||
**
|
||||
** Names for PCI configuration space registers.
|
||||
**
|
||||
** Copyright (c) 1994 Charles Hannum. All rights reserved.
|
||||
**
|
||||
**------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/*
|
||||
* Device identification register; contains a vendor ID and a device ID.
|
||||
* We have little need to distinguish the two parts.
|
||||
*/
|
||||
** Device identification register; contains a vendor ID and a device ID.
|
||||
** We have little need to distinguish the two parts.
|
||||
*/
|
||||
#define PCI_ID_REG 0x00
|
||||
|
||||
/*
|
||||
* Command and status register.
|
||||
*/
|
||||
** Command and status register.
|
||||
*/
|
||||
#define PCI_COMMAND_STATUS_REG 0x04
|
||||
|
||||
#define PCI_COMMAND_IO_ENABLE 0x00000001
|
||||
@ -329,8 +76,8 @@ void pci_conf_write (pcici_t tag, u_long reg, u_long data);
|
||||
#define PCI_STATUS_PARITY_DETECT 0x80000000
|
||||
|
||||
/*
|
||||
* Class register; defines basic type of device.
|
||||
*/
|
||||
** Class register; defines basic type of device.
|
||||
*/
|
||||
#define PCI_CLASS_REG 0x08
|
||||
|
||||
#define PCI_CLASS_MASK 0xff000000
|
||||
@ -388,8 +135,8 @@ void pci_conf_write (pcici_t tag, u_long reg, u_long data);
|
||||
#define PCI_SUBCLASS_BRIDGE_MISC 0x00800000
|
||||
|
||||
/*
|
||||
* Mapping registers
|
||||
*/
|
||||
** Mapping registers
|
||||
*/
|
||||
#define PCI_MAP_REG_START 0x10
|
||||
#define PCI_MAP_REG_END 0x28
|
||||
|
||||
@ -403,9 +150,11 @@ void pci_conf_write (pcici_t tag, u_long reg, u_long data);
|
||||
#define PCI_MAP_MEMORY_CACHABLE 0x00000008
|
||||
#define PCI_MAP_MEMORY_ADDRESS_MASK 0xfffffff0
|
||||
|
||||
#define PCI_MAP_IO_ADDRESS_MASK 0xfffffffc
|
||||
|
||||
/*
|
||||
* Interrupt configuration register
|
||||
*/
|
||||
** Interrupt configuration register
|
||||
*/
|
||||
#define PCI_INTERRUPT_REG 0x3c
|
||||
|
||||
#define PCI_INTERRUPT_PIN_MASK 0x0000ff00
|
||||
|
@ -1,6 +1,6 @@
|
||||
/**************************************************************************
|
||||
**
|
||||
** $Id: pcisupport.c,v 1.6 1994/12/22 21:20:39 se Exp $
|
||||
** $Id: pcisupport.c,v 1.7 1995/02/02 12:36:19 davidg Exp $
|
||||
**
|
||||
** Device driver for INTEL PCI chipsets.
|
||||
**
|
||||
@ -50,7 +50,10 @@
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/kernel.h>
|
||||
|
||||
#include <pci/pcivar.h>
|
||||
#include <pci/pcireg.h>
|
||||
|
||||
extern void printf();
|
||||
@ -69,12 +72,15 @@ static char* chipset_probe (pcici_t tag, pcidi_t type);
|
||||
static void chipset_attach(pcici_t tag, int unit);
|
||||
static u_long chipset_count;
|
||||
|
||||
struct pci_driver chipset_device = {
|
||||
struct pci_device chipset_device = {
|
||||
"chip",
|
||||
chipset_probe,
|
||||
chipset_attach,
|
||||
&chipset_count
|
||||
};
|
||||
|
||||
DATA_SET (pcidevice_set, chipset_device);
|
||||
|
||||
static char confread(pcici_t config_id, int port);
|
||||
|
||||
struct condmsg {
|
||||
@ -296,12 +302,15 @@ static char* vga_probe (pcici_t tag, pcidi_t type);
|
||||
static void vga_attach(pcici_t tag, int unit);
|
||||
static u_long vga_count;
|
||||
|
||||
struct pci_driver vga_device = {
|
||||
struct pci_device vga_device = {
|
||||
"vga",
|
||||
vga_probe,
|
||||
vga_attach,
|
||||
&vga_count
|
||||
};
|
||||
|
||||
DATA_SET (pcidevice_set, vga_device);
|
||||
|
||||
static char* vga_probe (pcici_t tag, pcidi_t type)
|
||||
{
|
||||
int data = pci_conf_read(tag, PCI_CLASS_REG);
|
||||
@ -345,12 +354,15 @@ static char* lkm_probe (pcici_t tag, pcidi_t type);
|
||||
static void lkm_attach(pcici_t tag, int unit);
|
||||
static u_long lkm_count;
|
||||
|
||||
struct pci_driver lkm_device = {
|
||||
struct pci_device lkm_device = {
|
||||
"lkm",
|
||||
lkm_probe,
|
||||
lkm_attach,
|
||||
&lkm_count
|
||||
};
|
||||
|
||||
DATA_SET (pcidevice_set, lkm_device);
|
||||
|
||||
static char* lkm_probe (pcici_t tag, pcidi_t type)
|
||||
{
|
||||
/*
|
||||
@ -375,12 +387,15 @@ static char* ign_probe (pcici_t tag, pcidi_t type);
|
||||
static void ign_attach(pcici_t tag, int unit);
|
||||
static u_long ign_count;
|
||||
|
||||
struct pci_driver ign_device = {
|
||||
struct pci_device ign_device = {
|
||||
NULL,
|
||||
ign_probe,
|
||||
ign_attach,
|
||||
&ign_count
|
||||
};
|
||||
|
||||
DATA_SET (pcidevice_set, ign_device);
|
||||
|
||||
static char* ign_probe (pcici_t tag, pcidi_t type)
|
||||
{
|
||||
switch (type) {
|
||||
|
Loading…
Reference in New Issue
Block a user