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:
dg 1995-02-02 13:12:18 +00:00
parent cab076f4f5
commit a4cc75ab15
10 changed files with 594 additions and 868 deletions

View File

@ -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 */

View File

@ -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) {

View File

@ -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

View File

@ -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)
{

View File

@ -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 */

View File

@ -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;
};

View File

@ -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 */

View File

@ -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) {

View File

@ -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

View File

@ -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) {