Submitted by: Wolfgang Stanglmeier <wolf@dentaro.GUN.de>

Bug fixed, that caused system hang on first interrupt on some motherboards.

New version of PCI bus configuration code, now supports dynamic interrupt
configuration (using BIOS supplied values).
NCR SCSI and DEC Ethernet driver patched to use this feature.
*** Remove PCI IRQ specifications from your kernel config file ! ***
This commit is contained in:
Stefan Eßer 1994-10-12 02:33:23 +00:00
parent 86e0c19b6c
commit 65772aee92
10 changed files with 1353 additions and 1201 deletions

View File

@ -101,8 +101,7 @@
#include <pci.h>
#if NPCI > 0
#include <i386/pci/pci.h>
#include <i386/pci/pci_device.h>
#include <i386/pci/pcireg.h>
#endif
#include <i386/isa/icu.h>
#include <i386/pci/dc21040.h>
@ -310,7 +309,7 @@ tulip_init(
int unit)
{
tulip_softc_t *sc = tulips[unit];
unsigned new_cmdmode;
/* XXX unsigned new_cmdmode; */
if (sc->tulip_if.if_flags & IFF_UP) {
sc->tulip_if.if_flags |= IFF_RUNNING;
@ -332,7 +331,7 @@ tulip_init(
sc->tulip_intrmask &= ~TULIP_STS_RXSTOPPED;
tulip_start(&sc->tulip_if);
}
tulip_cmdnode |= TULIP_CMD_THRSHLD160;
sc->tulip_cmdmode |= TULIP_CMD_THRSHLD160;
*sc->tulip_csrs.csr_intr = sc->tulip_intrmask;
*sc->tulip_csrs.csr_command = sc->tulip_cmdmode;
} else {
@ -690,13 +689,12 @@ tulip_start(
static int
tulip_intr(
int unit)
tulip_softc_t *sc)
{
tulip_softc_t *sc = tulips[unit];
tulip_uint32_t csr;
unsigned spins = 0;
tulip_intrs[unit]++;
/* XXX tulip_intrs[unit]++; */
while ((csr = *sc->tulip_csrs.csr_status) & (TULIP_STS_NORMALINTR|TULIP_STS_ABNRMLINTR)) {
*sc->tulip_csrs.csr_status = csr & sc->tulip_intrmask;
@ -706,7 +704,7 @@ tulip_intr(
if ((csr & TULIP_STS_ERRORMASK) == TULIP_STS_ERR_PARITY) {
TULIP_RESET(sc);
tulip_init(sc->tulip_unit);
return unit;
return (1);
}
}
if (csr & TULIP_STS_RXINTR)
@ -723,7 +721,7 @@ tulip_intr(
}
if (spins > sc->tulip_high_intrspins)
sc->tulip_high_intrspins = spins;
return unit;
return (1);
}
/*
@ -777,6 +775,7 @@ tulip_read_macaddr(
return 0;
}
#ifdef MULTICAST
static unsigned
tulip_mchash(
unsigned char *mca)
@ -794,20 +793,24 @@ tulip_mchash(
#endif
return crc & 0x1FF;
}
#endif MULTICAST
static void
tulip_addr_filter(
tulip_softc_t *sc)
{
tulip_uint32_t *sp = sc->tulip_setupdata;
#ifdef MULTICAST
struct ether_multistep step;
struct ether_multi *enm;
#endif
int i;
sc->tulip_flags &= ~TULIP_WANTHASH;
sc->tulip_flags |= TULIP_WANTSETUP;
sc->tulip_cmdmode &= ~TULIP_CMD_RXRUN;
sc->tulip_intrmask &= ~TULIP_STS_RXSTOPPED;
#ifdef MULTICAST
if (sc->tulip_ac.ac_multicnt > 14) {
unsigned hash;
/*
@ -830,10 +833,12 @@ tulip_addr_filter(
sp[41] = ((u_short *) sc->tulip_ac.ac_enaddr)[1];
sp[42] = ((u_short *) sc->tulip_ac.ac_enaddr)[2];
} else {
#endif
/*
* Else can get perfect filtering for 16 addresses.
*/
i = 0;
#ifdef MULTICAST
ETHER_FIRST_MULTI(step, &sc->tulip_ac, enm);
for (; enm != NULL; i++) {
*sp++ = ((u_short *) enm->enm_addrlo)[0];
@ -841,6 +846,7 @@ tulip_addr_filter(
*sp++ = ((u_short *) enm->enm_addrlo)[2];
ETHER_NEXT_MULTI(step, enm);
}
#endif
/*
* If an IP address is enabled, turn on broadcast
*/
@ -858,7 +864,9 @@ tulip_addr_filter(
*sp++ = ((u_short *) sc->tulip_ac.ac_enaddr)[1];
*sp++ = ((u_short *) sc->tulip_ac.ac_enaddr)[2];
}
#ifdef MULTICAST
}
#endif
}
static int
@ -931,6 +939,7 @@ tulip_ioctl(
break;
}
#ifdef MULTICAST
case SIOCADDMULTI:
case SIOCDELMULTI: {
/*
@ -948,6 +957,7 @@ tulip_ioctl(
}
break;
}
#endif /* MULTICAST */
default: {
error = EINVAL;
@ -968,7 +978,9 @@ tulip_attach(
int cnt;
ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS;
#ifdef MULTICAST
ifp->if_flags |= IFF_MULTICAST;
#endif /* MULTICAST */
*sc->tulip_csrs.csr_sia_connectivity = 0;
*sc->tulip_csrs.csr_sia_connectivity = TULIP_SIACONN_10BASET;
@ -1066,18 +1078,14 @@ tulip_initring(
* on both EISA and PCI boards, one must be careful in how defines the
* DC21040 in the config file.
*/
static int tulip_pci_probe(pcici_t config_id);
static int tulip_pci_attach(pcici_t config_id);
static char* tulip_pci_probe (pcici_t config_id, pcidi_t device_id);
static void tulip_pci_attach(pcici_t config_id, int unit);
static u_long tulip_count;
struct pci_driver dedevice = {
tulip_pci_probe,
tulip_pci_attach,
0x00021011ul,
#if __FreeBSD__ == 1
"de",
#endif
"digital dc21040 ethernet",
tulip_intr
&tulip_count,
};
#define PCI_CFID 0x00 /* Configuration ID */
@ -1090,39 +1098,41 @@ struct pci_driver dedevice = {
#define PCI_CFDA 0x40 /* Configuration Driver Area */
#define TULIP_PCI_CSRSIZE (8 / sizeof(tulip_uint32_t))
static int
static char*
tulip_pci_probe(
pcici_t config_id)
pcici_t config_id,
pcidi_t device_id)
{
int idx;
if (device_id != 0x00021011ul)
return (NULL);
for (idx = 0; idx < NDE; idx++)
if (tulips[idx] == NULL)
return idx;
return -1;
return ("digital dc21040 ethernet");
return (NULL);
}
static int
static void
tulip_pci_attach(
pcici_t config_id)
pcici_t config_id,
int unit)
{
tulip_softc_t *sc;
int retval, idx, revinfo, unit;
signed int csr;
int retval, idx /* XXX , revinfo, */;
/* XXX signed int csr; */
vm_offset_t va_csrs, pa_csrs;
int result;
/* XXX int result;*/
tulip_desc_t *rxdescs, *txdescs;
unit = tulip_pci_probe(config_id);
sc = (tulip_softc_t *) malloc(sizeof(*sc), M_DEVBUF, M_NOWAIT);
if (sc == NULL)
return -1;
return;
rxdescs = (tulip_desc_t *)
malloc(sizeof(tulip_desc_t) * TULIP_RXDESCS, M_DEVBUF, M_NOWAIT);
if (rxdescs == NULL) {
free((caddr_t) sc, M_DEVBUF);
return -1;
return;
}
txdescs = (tulip_desc_t *)
@ -1130,7 +1140,7 @@ tulip_pci_attach(
if (txdescs == NULL) {
free((caddr_t) rxdescs, M_DEVBUF);
free((caddr_t) sc, M_DEVBUF);
return -1;
return;
}
bzero(sc, sizeof(sc)); /* Zero out the softc*/
@ -1148,13 +1158,12 @@ tulip_pci_attach(
sc->tulip_unit = unit;
sc->tulip_name = "de";
retval = pci_map_mem(config_id, PCI_CBMA, &va_csrs, &pa_csrs);
if (retval) {
printf("de%d: pci_map_mem failed.\n", unit);
if (!retval) {
kmem_free(kernel_map, sc->tulip_rxspace, TULIP_RXSPACE + NBPG);
free((caddr_t) txdescs, M_DEVBUF);
free((caddr_t) rxdescs, M_DEVBUF);
free((caddr_t) sc, M_DEVBUF);
return -1;
return;
}
tulips[unit] = sc;
tulip_initcsrs(sc, (volatile tulip_uint32_t *) va_csrs, TULIP_PCI_CSRSIZE);
@ -1171,10 +1180,10 @@ tulip_pci_attach(
(sc->tulip_revinfo & 0xF0) >> 4, sc->tulip_revinfo & 0x0F,
"unknown");
} else {
pci_map_int (config_id, tulip_intr, (void*) sc, &net_imask);
TULIP_RESET(sc);
tulip_attach(sc);
}
return 1;
}
#endif /* NPCI > 0 */
#endif /* NDE > 0 */

View File

@ -1,6 +1,6 @@
/**************************************************************************
**
** $Id: pci.c,v 1.5 1994/09/28 16:34:07 se Exp $
** $Id: pci.c,v 2.12 94/10/11 22:20:37 wolf Oct11 $
**
** General subroutines for the PCI bus on 80*86 systems.
** pci_configure ()
@ -33,27 +33,17 @@
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**
**-------------------------------------------------------------------------
***************************************************************************
*/
#include <pci.h>
#if NPCI > 0
/*========================================================
**
** Configuration
**
**========================================================
*/
/*
** maximum number of devices which share one interrupt line
*/
#ifndef PCI_MAX_DPI
#define PCI_MAX_DPI (4)
#endif /*PCI_MAX_DPI*/
#ifndef __FreeBSD2__
#if __FreeBSD__ >= 2
#define __FreeBSD2__
#endif
#endif
/*========================================================
**
@ -64,101 +54,54 @@
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/malloc.h>
#include <sys/errno.h>
#include <vm/vm.h>
#include <vm/vm_param.h>
#include <i386/isa/icu.h>
#include <i386/isa/isa.h>
#include <i386/isa/isa_device.h>
#include <i386/pci/pci.h>
#include <i386/pci/pci_device.h>
#include <i386/pci/pcibios.h>
#include <i386/isa/icu.h>
#include <i386/pci/pcireg.h>
/*
** Function prototypes missing in system headers
*/
#if ! (__FreeBSD__ >= 2)
#ifndef __FreeBSD2__
extern pmap_t pmap_kernel(void);
static vm_offset_t pmap_mapdev (vm_offset_t paddr, vm_size_t vsize);
#endif
/*========================================================
**
** Autoconfiguration (of isa bus)
**
**========================================================
*/
/*
** per slot data structure for passing interupts..
*/
static struct {
u_short number;
u_short isanum;
struct {
int (*proc)(int dev);
dev_t unit;
} vector[PCI_MAX_DPI];
} pcidata [NPCI];
* Type of the first (asm) part of an interrupt handler.
*/
typedef void inthand_t __P((u_int cs, u_int ef, u_int esp, u_int ss));
/*
** check device ready
*/
static int pciprobe (struct isa_device *dev)
{
if (dev->id_unit >= NPCI)
return (0);
if (!pci_conf_mode())
return (0);
return (-1);
}
* Usual type of the second (C) part of an interrupt handler. Some bogus
* ones need the arg to be the interrupt frame (and not a copy of it, which
* is all that is possible in C).
*/
typedef void inthand2_t __P((int unit));
/*
** initialize the driver structure
*/
static int pciattach (struct isa_device *isdp)
{
pcidata[isdp->id_unit].number = 0;
pcidata[isdp->id_unit].isanum = ffs(isdp->id_irq)-1;
return (1);
}
/*
** ISA driver structure
*/
struct isa_driver pcidriver = {
pciprobe,
pciattach,
"pci"
};
/*========================================================
** XXX @FreeBSD2@
**
** Interrupt forward from isa to pci devices.
**
**========================================================
** Unfortunately, the mptr argument is _no_ pointer in 2.0 FreeBSD.
** We would prefer a pointer because it enables us to install
** new interrupt handlers at any time.
** In 2.0 FreeBSD later installed interrupt handlers may change
** the xyz_imask, but this would not be recognized by handlers
** which are installed before.
*/
static int
register_intr __P((int intr, int device_id, unsigned int flags,
inthand2_t *handler, unsigned int * mptr, int unit));
extern unsigned intr_mask[ICU_LEN];
void pciintr (int unit)
{
u_short i;
if (unit >= NPCI) return;
for (i=0; i<pcidata[unit].number; i++) {
(void)(*pcidata[unit].vector[i].proc)
(pcidata[unit].vector[i].unit);
};
}
#endif /* !__FreeBSD2__ */
/*========================================================
**
@ -183,52 +126,82 @@ void pciintr (int unit)
#define PCI_PMEM_START 0xc0000000
#endif
static vm_offset_t pci_paddr = PCI_PMEM_START;
static vm_offset_t pci_paddr = PCI_PMEM_START;
/*--------------------------------------------------------
**
** The pci device interrupt lines should have been
** assigned by the bios. But if the bios failed to
** to it, we set it.
**
**--------------------------------------------------------
*/
#ifndef PCI_IRQ
#define PCI_IRQ 0
#endif
static u_long pci_irq = PCI_IRQ;
/*---------------------------------------------------------
**
** pci_configure ()
**
** Probe all devices on pci bus and attach them.
**
** May be called more than once.
** Any device is attached only once.
** (Attached devices are remembered in pci_seen.)
**
**---------------------------------------------------------
*/
static void not_supported (pcici_t tag, u_long type);
static unsigned long pci_seen[NPCI];
static int pci_conf_count;
void pci_configure()
{
u_char device,last_device;
u_short bus,last_bus;
u_short bus;
pcici_t tag;
pcidi_t type;
u_long data;
int unit;
int intpin;
int isanum;
int pci_mode;
int pci_mechanism;
int pciint;
int irq;
char* name=0;
int newdev=0;
struct pci_driver *drp;
struct pci_driver *drp=0;
struct pci_device *dvp;
/*
** check pci bus present
*/
pci_mode = pci_conf_mode ();
if (!pci_mode) return;
last_bus = pci_last_bus ();
last_device = pci_mode==1 ? 31 : 15;
pci_mechanism = pci_conf_mode ();
if (!pci_mechanism) return;
last_device = pci_mechanism==1 ? 31 : 15;
/*
** hello world ..
*/
for (bus=0;bus<NPCI;bus++) {
#ifndef PCI_QUIET
printf ("pci*: mode=%d, scanning bus 0..%d, device 0..%d.\n",
pci_mode, last_bus, last_device);
printf ("pci%d: scanning device 0..%d, mechanism=%d.\n",
bus, last_device, pci_mechanism);
#endif
for (bus=0;bus<=last_bus; bus++)
for (device=0; device<=last_device; device ++) {
if (pci_seen[bus] & (1ul << device))
continue;
tag = pcitag (bus, device, 0);
type = pci_conf_read (tag, PCI_ID_REG);
@ -238,137 +211,90 @@ void pci_configure()
** lookup device in ioconfiguration:
*/
for (dvp = pci_devtab; dvp->pd_device_id; dvp++) {
if (dvp->pd_device_id == type) break;
};
drp = dvp->pd_driver;
if (!dvp->pd_device_id) {
/*
** not found
** try to dig out some information.
**
** By Garrett Wollman
** <wollman@halloran-eldar.lcs.mit.edu>
*/
int data = pci_conf_read(tag, PCI_CLASS_REG);
vm_offset_t va;
vm_offset_t pa;
int reg;
switch (data & PCI_CLASS_MASK) {
case PCI_CLASS_PREHISTORIC:
if ((data & PCI_SUBCLASS_MASK)
!= PCI_SUBCLASS_PREHISTORIC_VGA)
break;
case PCI_CLASS_DISPLAY:
for (reg = PCI_MAP_REG_START;
reg < PCI_MAP_REG_END;
reg += 4) {
data = pci_map_mem(tag, reg, &va, &pa);
if (data == 0)
printf (
"pci%d:%d: mapped VGA-like device at physaddr 0x%lx\n",
bus, device, (u_long)pa);
}
for (dvp = pci_devtab; dvp->pd_name; dvp++) {
drp = dvp->pd_driver;
if (!drp)
continue;
};
if ((name=(*drp->probe)(tag, type)))
break;
};
if (!dvp->pd_name) {
#ifndef PCI_QUIET
if (pci_conf_count)
continue;
printf("pci%d:%d: ", bus, device);
not_supported (tag, type);
#endif
};
if (!drp) {
if(dvp->pd_flags & PDF_LOADABLE) {
printf("%s: loadable device on pci%d:%d\n",
dvp->pd_name, bus, device);
}
continue;
}
};
pci_seen[bus] |= (1ul << device);
/*
** found it.
** probe returns the device unit.
** Get and increment the unit.
*/
unit = (*drp->probe) (tag);
unit = (*drp->count)++;
if (unit<0) {
printf ("%s <%s>: probe failed on pci%d:%d\n",
dvp->pd_name, drp->name, bus, device);
continue;
};
/*
** ignore device ?
*/
printf ("%s%d <%s>", dvp->pd_name, unit, drp->name);
if (!*name) continue;
/*
** Announce this device
*/
newdev++;
printf ("%s%d <%s>", dvp->pd_name, unit, name);
/*
** install interrupts
** Get the int pin number (pci interrupt number a-d)
** from the pci configuration space.
*/
data = pci_conf_read (tag, PCI_INTERRUPT_REG);
intpin = PCI_INTERRUPT_PIN_EXTRACT(data);
if (intpin) {
int idx=NPCI;
pciint = PCI_INTERRUPT_PIN_EXTRACT(data);
if (pciint) {
printf (" int %c", 0x60+pciint);
/*
** Usage of int line register (if set by bios)
** Matt Thomas <thomas@lkg.dec.com>
** If the interrupt line register is not set,
** set it now from PCI_IRQ.
*/
isanum = PCI_INTERRUPT_LINE_EXTRACT(data);
if (isanum) {
if (!(PCI_INTERRUPT_LINE_EXTRACT(data))) {
/*
** @INT@ FIXME!!!
**
** Should try to use "register_interupt"
** at this point.
*/
irq = pci_irq & 0x0f;
pci_irq >>= 4;
printf (" line=%d", isanum);
for (idx = 0; idx < NPCI; idx++) {
if (pcidata[idx].isanum == isanum)
break;
};
data = PCI_INTERRUPT_LINE_INSERT(data, irq);
printf (" (config)");
pci_conf_write (tag, PCI_INTERRUPT_REG, data);
};
/*
** Or take the device number as index ...
*/
if (idx >= NPCI) idx = device;
irq = PCI_INTERRUPT_LINE_EXTRACT(data);
/*
** And install the interrupt.
** If it's zero, the isa irq number is unknown,
** and we cannot bind the pci interrupt to isa.
*/
if (idx<NPCI) {
u_short entry = pcidata[idx].number;
printf (" irq %c", 0x60+intpin);
if (entry < PCI_MAX_DPI) {
pcidata[idx].vector[entry].proc = drp->intr;
pcidata[idx].vector[entry].unit = unit;
entry++;
};
printf (" isa=%d [%d]",pcidata[idx].isanum, entry);
pcidata[idx].number=entry;
} else {
printf (" no int");
};
if (irq)
printf (" irq %d", irq);
else
printf (" not bound");
};
/*
** enable memory access
*/
data = pci_conf_read (tag, PCI_COMMAND_STATUS_REG)
& 0xffff | PCI_COMMAND_MEM_ENABLE;
data = (pci_conf_read (tag, PCI_COMMAND_STATUS_REG)
& 0xffff) | PCI_COMMAND_MEM_ENABLE;
pci_conf_write (tag, (u_char) PCI_COMMAND_STATUS_REG, data);
@ -380,13 +306,16 @@ void pci_configure()
printf (" on pci%d:%d\n", bus, device);
(void) (*drp->attach) (tag);
}
(*drp->attach) (tag, unit);
};
};
#ifndef PCI_QUIET
printf ("pci uses physical addresses from 0x%lx to 0x%lx\n",
if (newdev)
printf ("pci uses physical addresses from 0x%lx to 0x%lx\n",
(u_long)PCI_PMEM_START, (u_long)pci_paddr);
#endif
pci_conf_count++;
}
/*-----------------------------------------------------------------------
@ -403,7 +332,8 @@ int pci_map_port (pcici_t tag, u_long reg, u_short* pa)
/*
** @MAPIO@ not yet implemented.
*/
return (ENOSYS);
printf ("pci_map_port failed: not yet implemented\n");
return (0);
}
/*-----------------------------------------------------------------------
@ -425,8 +355,11 @@ int pci_map_mem (pcici_t tag, u_long reg, vm_offset_t* va, vm_offset_t* pa)
** sanity check
*/
if (reg <= PCI_MAP_REG_START || reg >= PCI_MAP_REG_END || (reg & 3))
return (EINVAL);
if (reg < PCI_MAP_REG_START || reg >= PCI_MAP_REG_END || (reg & 3)) {
printf ("pci_map_mem failed: bad register=0x%x\n",
(unsigned)reg);
return (0);
};
/*
** get size and type of memory
@ -445,7 +378,9 @@ int pci_map_mem (pcici_t tag, u_long reg, vm_offset_t* va, vm_offset_t* pa)
break;
default: /* unknown */
return (EINVAL);
printf ("pci_map_mem failed: bad memory type=0x%x\n",
(unsigned) data);
return (0);
};
/*
@ -455,18 +390,19 @@ int pci_map_mem (pcici_t tag, u_long reg, vm_offset_t* va, vm_offset_t* pa)
vsize = round_page (-(data & PCI_MAP_MEMORY_ADDRESS_MASK));
if (!vsize) return (EINVAL);
if (!vsize) return (0);
/*
** align physical address to virtual size
*/
if (data = pci_paddr % vsize)
if ((data = pci_paddr % vsize))
pci_paddr += vsize - data;
vaddr = pmap_mapdev (pci_paddr, vsize);
vaddr = (vm_offset_t) pmap_mapdev (pci_paddr, vsize);
if (!vaddr) return (EINVAL);
if (!vaddr) return (0);
#ifndef PCI_QUIET
/*
@ -474,7 +410,7 @@ int pci_map_mem (pcici_t tag, u_long reg, vm_offset_t* va, vm_offset_t* pa)
*/
printf ("\treg%d: virtual=0x%lx physical=0x%lx\n",
reg, (u_long)vaddr, (u_long)pci_paddr);
(unsigned) reg, (u_long)vaddr, (u_long)pci_paddr);
#endif
/*
@ -496,50 +432,77 @@ int pci_map_mem (pcici_t tag, u_long reg, vm_offset_t* va, vm_offset_t* pa)
pci_paddr += vsize;
return (0);
return (1);
}
/*-----------------------------------------------------------
/*-----------------------------------------------------------------------
**
** Mapping of physical to virtual memory
** Map pci interrupts to isa interrupts.
**
**-----------------------------------------------------------
**-----------------------------------------------------------------------
*/
#if ! (__FreeBSD__ >= 2)
static unsigned int pci_int_mask [16];
extern vm_map_t kernel_map;
static vm_offset_t pmap_mapdev (vm_offset_t paddr, vm_size_t vsize)
int pci_map_int (pcici_t tag, int(*func)(), void* arg, unsigned* maskptr)
{
vm_offset_t vaddr,value;
u_long result;
int irq;
unsigned mask;
vaddr = vm_map_min (kernel_map);
irq = PCI_INTERRUPT_LINE_EXTRACT(
pci_conf_read (tag, PCI_INTERRUPT_REG));
result = vm_map_find (kernel_map, (void*)0, (vm_offset_t) 0,
&vaddr, vsize, TRUE);
if (result != KERN_SUCCESS) {
printf (" vm_map_find failed(%d)\n", result);
if (irq >= 16 || irq <= 0) {
printf ("pci_map_int failed: no int line set.\n");
return (0);
};
}
/*
** map physical
*/
mask = 1ul << irq;
value = vaddr;
while (vsize >= NBPG) {
pmap_enter (pmap_kernel(), vaddr, paddr,
VM_PROT_READ|VM_PROT_WRITE, TRUE);
vaddr += NBPG;
paddr += NBPG;
vsize -= NBPG;
};
return (value);
}
if (!maskptr)
maskptr = &pci_int_mask[irq];
INTRMASK (*maskptr, mask);
register_intr(
irq, /* isa irq */
0, /* deviced?? */
0, /* flags? */
(inthand2_t*) func, /* handler */
#ifdef __FreeBSD2__
*maskptr, /* mask */
#else
maskptr, /* mask pointer */
#endif
(int) arg); /* handler arg */
#ifdef __FreeBSD2__
/*
** 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;
};
#endif
INTREN (mask);
return (1);
}
/*-----------------------------------------------------------
**
@ -554,7 +517,7 @@ struct vt {
static struct vt VendorTable[] = {
{0x1002, "ATI TECHNOLOGIES INC"},
{0x1011, "DIGITAL EQUIPMENT CORP."},
{0x1011, "DIGITAL EQUIPMENT CORPORATION"},
{0x101A, "NCR"},
{0x102B, "MATROX"},
{0x1045, "OPTI"},
@ -604,18 +567,107 @@ void not_supported (pcici_t tag, u_long type)
case 1:
case 5:
printf (" map(%lx): io(%lx)\n", reg, data & ~3);
printf (" map(%x): io(%lx)\n",
reg, data & ~3);
break;
case 0:
printf (" map(%lx): mem32(%lx)\n", reg, data & ~7);
printf (" map(%x): mem32(%lx)\n",
reg, data & ~7);
break;
case 2:
printf (" map(%lx): mem20(%lx)\n", reg, data & ~7);
printf (" map(%x): mem20(%lx)\n",
reg, data & ~7);
break;
case 4:
printf (" map(%lx): mem64(%lx)\n", reg, data & ~7);
printf (" map(%x): mem64(%lx)\n",
reg, data & ~7);
break;
}
}
}
#endif
#ifndef __FreeBSD2__
/*-----------------------------------------------------------
**
** Mapping of physical to virtual memory
**
**-----------------------------------------------------------
*/
extern vm_map_t kernel_map;
static vm_offset_t pmap_mapdev (vm_offset_t paddr, vm_size_t vsize)
{
vm_offset_t vaddr,value;
u_long result;
vaddr = vm_map_min (kernel_map);
result = vm_map_find (kernel_map, (void*)0, (vm_offset_t) 0,
&vaddr, vsize, TRUE);
if (result != KERN_SUCCESS) {
printf (" vm_map_find failed(%d)\n", result);
return (0);
};
/*
** map physical
*/
value = vaddr;
while (vsize >= NBPG) {
pmap_enter (pmap_kernel(), vaddr, paddr,
VM_PROT_READ|VM_PROT_WRITE, TRUE);
vaddr += NBPG;
paddr += NBPG;
vsize -= NBPG;
};
return (value);
}
/*------------------------------------------------------------
**
** Emulate the register_intr() function of FreeBSD 2.0
**
** requires a patch:
** FreeBSD 2.0: "/sys/i386/isa/vector.s"
** 386bsd0.1: "/sys/i386/isa/icu.s"
** 386bsd1.0: Please ask Jesus Monroy Jr.
**
**------------------------------------------------------------
*/
#include <machine/segments.h>
int pci_int_unit [16];
inthand2_t* (pci_int_hdlr [16]);
unsigned int * pci_int_mptr [16];
unsigned int pci_int_count[16];
extern void
Vpci3(), Vpci4(), Vpci5(), Vpci6(), Vpci7(), Vpci8(), Vpci9(),
Vpci10(), Vpci11(), Vpci12(), Vpci13(), Vpci14(), Vpci15();
static inthand_t* pci_int_glue[16] = {
0, 0, 0, Vpci3, Vpci4, Vpci5, Vpci6, Vpci7, Vpci8,
Vpci9, Vpci10, Vpci11, Vpci12, Vpci13, Vpci14, Vpci15 };
static int
register_intr __P((int intr, int device_id, unsigned int flags,
inthand2_t *handler, unsigned int* mptr, int unit))
{
if (intr >= 16 || intr <= 2)
return (EINVAL);
if (pci_int_hdlr [intr])
return (EBUSY);
pci_int_hdlr [intr] = handler;
pci_int_unit [intr] = unit;
pci_int_mptr [intr] = mptr;
setidt(NRSVIDT + intr, pci_int_glue[intr], SDT_SYS386IGT, SEL_KPL);
return (0);
}
#endif /* __FreeBSD2__ */
#endif /* NPCI */

View File

@ -101,8 +101,7 @@
#include <pci.h>
#if NPCI > 0
#include <i386/pci/pci.h>
#include <i386/pci/pci_device.h>
#include <i386/pci/pcireg.h>
#endif
#include <i386/isa/icu.h>
#include <i386/pci/dc21040.h>
@ -310,7 +309,7 @@ tulip_init(
int unit)
{
tulip_softc_t *sc = tulips[unit];
unsigned new_cmdmode;
/* XXX unsigned new_cmdmode; */
if (sc->tulip_if.if_flags & IFF_UP) {
sc->tulip_if.if_flags |= IFF_RUNNING;
@ -332,7 +331,7 @@ tulip_init(
sc->tulip_intrmask &= ~TULIP_STS_RXSTOPPED;
tulip_start(&sc->tulip_if);
}
tulip_cmdnode |= TULIP_CMD_THRSHLD160;
sc->tulip_cmdmode |= TULIP_CMD_THRSHLD160;
*sc->tulip_csrs.csr_intr = sc->tulip_intrmask;
*sc->tulip_csrs.csr_command = sc->tulip_cmdmode;
} else {
@ -690,13 +689,12 @@ tulip_start(
static int
tulip_intr(
int unit)
tulip_softc_t *sc)
{
tulip_softc_t *sc = tulips[unit];
tulip_uint32_t csr;
unsigned spins = 0;
tulip_intrs[unit]++;
/* XXX tulip_intrs[unit]++; */
while ((csr = *sc->tulip_csrs.csr_status) & (TULIP_STS_NORMALINTR|TULIP_STS_ABNRMLINTR)) {
*sc->tulip_csrs.csr_status = csr & sc->tulip_intrmask;
@ -706,7 +704,7 @@ tulip_intr(
if ((csr & TULIP_STS_ERRORMASK) == TULIP_STS_ERR_PARITY) {
TULIP_RESET(sc);
tulip_init(sc->tulip_unit);
return unit;
return (1);
}
}
if (csr & TULIP_STS_RXINTR)
@ -723,7 +721,7 @@ tulip_intr(
}
if (spins > sc->tulip_high_intrspins)
sc->tulip_high_intrspins = spins;
return unit;
return (1);
}
/*
@ -777,6 +775,7 @@ tulip_read_macaddr(
return 0;
}
#ifdef MULTICAST
static unsigned
tulip_mchash(
unsigned char *mca)
@ -794,20 +793,24 @@ tulip_mchash(
#endif
return crc & 0x1FF;
}
#endif MULTICAST
static void
tulip_addr_filter(
tulip_softc_t *sc)
{
tulip_uint32_t *sp = sc->tulip_setupdata;
#ifdef MULTICAST
struct ether_multistep step;
struct ether_multi *enm;
#endif
int i;
sc->tulip_flags &= ~TULIP_WANTHASH;
sc->tulip_flags |= TULIP_WANTSETUP;
sc->tulip_cmdmode &= ~TULIP_CMD_RXRUN;
sc->tulip_intrmask &= ~TULIP_STS_RXSTOPPED;
#ifdef MULTICAST
if (sc->tulip_ac.ac_multicnt > 14) {
unsigned hash;
/*
@ -830,10 +833,12 @@ tulip_addr_filter(
sp[41] = ((u_short *) sc->tulip_ac.ac_enaddr)[1];
sp[42] = ((u_short *) sc->tulip_ac.ac_enaddr)[2];
} else {
#endif
/*
* Else can get perfect filtering for 16 addresses.
*/
i = 0;
#ifdef MULTICAST
ETHER_FIRST_MULTI(step, &sc->tulip_ac, enm);
for (; enm != NULL; i++) {
*sp++ = ((u_short *) enm->enm_addrlo)[0];
@ -841,6 +846,7 @@ tulip_addr_filter(
*sp++ = ((u_short *) enm->enm_addrlo)[2];
ETHER_NEXT_MULTI(step, enm);
}
#endif
/*
* If an IP address is enabled, turn on broadcast
*/
@ -858,7 +864,9 @@ tulip_addr_filter(
*sp++ = ((u_short *) sc->tulip_ac.ac_enaddr)[1];
*sp++ = ((u_short *) sc->tulip_ac.ac_enaddr)[2];
}
#ifdef MULTICAST
}
#endif
}
static int
@ -931,6 +939,7 @@ tulip_ioctl(
break;
}
#ifdef MULTICAST
case SIOCADDMULTI:
case SIOCDELMULTI: {
/*
@ -948,6 +957,7 @@ tulip_ioctl(
}
break;
}
#endif /* MULTICAST */
default: {
error = EINVAL;
@ -968,7 +978,9 @@ tulip_attach(
int cnt;
ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS;
#ifdef MULTICAST
ifp->if_flags |= IFF_MULTICAST;
#endif /* MULTICAST */
*sc->tulip_csrs.csr_sia_connectivity = 0;
*sc->tulip_csrs.csr_sia_connectivity = TULIP_SIACONN_10BASET;
@ -1066,18 +1078,14 @@ tulip_initring(
* on both EISA and PCI boards, one must be careful in how defines the
* DC21040 in the config file.
*/
static int tulip_pci_probe(pcici_t config_id);
static int tulip_pci_attach(pcici_t config_id);
static char* tulip_pci_probe (pcici_t config_id, pcidi_t device_id);
static void tulip_pci_attach(pcici_t config_id, int unit);
static u_long tulip_count;
struct pci_driver dedevice = {
tulip_pci_probe,
tulip_pci_attach,
0x00021011ul,
#if __FreeBSD__ == 1
"de",
#endif
"digital dc21040 ethernet",
tulip_intr
&tulip_count,
};
#define PCI_CFID 0x00 /* Configuration ID */
@ -1090,39 +1098,41 @@ struct pci_driver dedevice = {
#define PCI_CFDA 0x40 /* Configuration Driver Area */
#define TULIP_PCI_CSRSIZE (8 / sizeof(tulip_uint32_t))
static int
static char*
tulip_pci_probe(
pcici_t config_id)
pcici_t config_id,
pcidi_t device_id)
{
int idx;
if (device_id != 0x00021011ul)
return (NULL);
for (idx = 0; idx < NDE; idx++)
if (tulips[idx] == NULL)
return idx;
return -1;
return ("digital dc21040 ethernet");
return (NULL);
}
static int
static void
tulip_pci_attach(
pcici_t config_id)
pcici_t config_id,
int unit)
{
tulip_softc_t *sc;
int retval, idx, revinfo, unit;
signed int csr;
int retval, idx /* XXX , revinfo, */;
/* XXX signed int csr; */
vm_offset_t va_csrs, pa_csrs;
int result;
/* XXX int result;*/
tulip_desc_t *rxdescs, *txdescs;
unit = tulip_pci_probe(config_id);
sc = (tulip_softc_t *) malloc(sizeof(*sc), M_DEVBUF, M_NOWAIT);
if (sc == NULL)
return -1;
return;
rxdescs = (tulip_desc_t *)
malloc(sizeof(tulip_desc_t) * TULIP_RXDESCS, M_DEVBUF, M_NOWAIT);
if (rxdescs == NULL) {
free((caddr_t) sc, M_DEVBUF);
return -1;
return;
}
txdescs = (tulip_desc_t *)
@ -1130,7 +1140,7 @@ tulip_pci_attach(
if (txdescs == NULL) {
free((caddr_t) rxdescs, M_DEVBUF);
free((caddr_t) sc, M_DEVBUF);
return -1;
return;
}
bzero(sc, sizeof(sc)); /* Zero out the softc*/
@ -1148,13 +1158,12 @@ tulip_pci_attach(
sc->tulip_unit = unit;
sc->tulip_name = "de";
retval = pci_map_mem(config_id, PCI_CBMA, &va_csrs, &pa_csrs);
if (retval) {
printf("de%d: pci_map_mem failed.\n", unit);
if (!retval) {
kmem_free(kernel_map, sc->tulip_rxspace, TULIP_RXSPACE + NBPG);
free((caddr_t) txdescs, M_DEVBUF);
free((caddr_t) rxdescs, M_DEVBUF);
free((caddr_t) sc, M_DEVBUF);
return -1;
return;
}
tulips[unit] = sc;
tulip_initcsrs(sc, (volatile tulip_uint32_t *) va_csrs, TULIP_PCI_CSRSIZE);
@ -1171,10 +1180,10 @@ tulip_pci_attach(
(sc->tulip_revinfo & 0xF0) >> 4, sc->tulip_revinfo & 0x0F,
"unknown");
} else {
pci_map_int (config_id, tulip_intr, (void*) sc, &net_imask);
TULIP_RESET(sc);
tulip_attach(sc);
}
return 1;
}
#endif /* NPCI > 0 */
#endif /* NDE > 0 */

View File

@ -1,6 +1,6 @@
/**************************************************************************
**
** $Id: ncr.c,v 1.5 1994/09/24 02:42:11 rgrimes Exp $
** $Id: ncr.c,v 2.11 94/10/11 19:03:07 wolf Oct11 $
**
** Device driver for the NCR 53C810 PCI-SCSI-Controller.
**
@ -9,11 +9,11 @@
**-------------------------------------------------------------------------
**
** Written for 386bsd and FreeBSD by
** wolf@dentaro.gun.de Wolfgang Stanglmeier
** se@mi.Uni-Koeln.de Stefan Esser
** Wolfgang Stanglmeier <wolf@dentaro.gun.de>
** Stefan Esser <se@mi.Uni-Koeln.de>
**
** Ported to NetBSD by
** mycroft@gnu.ai.mit.edu
** Charles M. Hannum <mycroft@gnu.ai.mit.edu>
**
**-------------------------------------------------------------------------
**
@ -41,18 +41,11 @@
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**
**-------------------------------------------------------------------------
***************************************************************************
*/
#ifndef __NetBSD__
#ifdef KERNEL
#include <ncr.h>
#else /* KERNEL */
#define NNCR 1
#endif /* KERNEL */
#endif /* !__NetBSD__ */
#define NCR_VERSION (2)
#define MAX_UNITS (16)
/*==========================================================
@ -107,7 +100,7 @@
*/
#ifndef SCSI_NCR_MAX_TAGS
#define SCSI_NCR_MAX_TAGS (8)
#define SCSI_NCR_MAX_TAGS (0)
#endif /* SCSI_NCR_MAX_TAGS */
/*==========================================================
@ -178,6 +171,7 @@
#include <sys/types.h>
#include <sys/param.h>
#include <sys/time.h>
#include <sys/proc.h>
#ifdef KERNEL
#include <sys/systm.h>
@ -190,17 +184,13 @@
#include <vm/vm.h>
#endif /* KERNEL */
#include <i386/pci/ncr_reg.h>
#include <i386/pci/ncrreg.h>
#ifdef __NetBSD__
#include <sys/device.h>
#include <i386/pci/pcivar.h>
#include <i386/pci/pcireg.h>
#else
#include <i386/pci/pci.h>
#include <i386/pci/pcibios.h>
#include <i386/pci/pci_device.h>
#endif
#include <i386/pci/pcireg.h>
#include <scsi/scsi_all.h>
#include <scsi/scsiconf.h>
@ -369,6 +359,7 @@ int ncr_debug = 0;
*/
#define CCB_MAGIC (0xf2691ad2)
#define MAX_TAGS (16) /* hard limit */
/*==========================================================
**
@ -394,6 +385,7 @@ int ncr_debug = 0;
extern void timeout();
extern void untimeout();
#endif /* KERNEL */
#define bio_imask biomask
#define LUN lu
#define TARGET targ
#define PRINT_ADDR(xp) printf ("ncr0: targ %d lun %d ",xp->targ,xp->lu)
@ -946,6 +938,8 @@ struct ncb {
#ifdef __NetBSD__
struct device sc_dev;
struct intrhand sc_ih;
#else
int unit;
#endif
/*-----------------------------------------------
@ -1195,6 +1189,7 @@ static void ncr_getclock (ncb_p np);
static ccb_p ncr_get_ccb (ncb_p np, u_long flags, u_long t,u_long l);
static U_INT32 ncr_info (int unit);
static void ncr_init (ncb_p np, char * msg, u_long code);
static int ncr_intr (ncb_p np);
static void ncr_int_ma (ncb_p np);
static void ncr_int_sir (ncb_p np);
static void ncr_int_sto (ncb_p np);
@ -1223,11 +1218,9 @@ static void ncr_wakeup (ncb_p np, u_long code);
#ifdef __NetBSD__
static int ncr_probe (struct device *, struct device *, void *);
static void ncr_attach (struct device *, struct device *, void *);
static int ncr_intr (ncb_p np);
#else
static int ncr_probe (pcici_t config_id);
static int ncr_attach (pcici_t config_id);
static int ncr_intr (int dev);
static char* ncr_probe (pcici_t tag, pcidi_t type);
static void ncr_attach (pcici_t tag, int unit);
#endif
/*==========================================================
@ -1241,9 +1234,8 @@ static int ncr_intr (int dev);
#ifdef DIRTY
#include <i386/include/cpufunc.h>
#ifdef __NetBSD__
#include <i386/include/cpufunc.h>
#include <i386/include/pio.h>
#include <i386/isa/isareg.h>
#define DELAY(x) delay(x)
@ -1326,7 +1318,7 @@ static u_long getirr (void)
static char ident[] =
"\n$Id: ncr.c,v 1.4 1994/09/16 13:33:56 davidg Exp $\n";
"\n$Id: ncr.c,v 2.11 94/10/11 19:03:07 wolf Oct11 $\n";
u_long ncr_version = NCR_VERSION
+ (u_long) sizeof (struct ncb)
@ -1337,9 +1329,8 @@ u_long ncr_version = NCR_VERSION
#ifdef KERNEL
#ifndef __NetBSD__
u_long ncr_units;
u_long nncr=NNCR;
ncb_p ncrp [NNCR];
u_long nncr=MAX_UNITS;
ncb_p ncrp [MAX_UNITS];
#endif
int ncr_cache; /* may _NOT_ be static */
@ -1371,20 +1362,12 @@ struct cfdriver ncrcd = {
#else /* !__NetBSD__ */
struct pci_driver ncr810_device = {
ncr_probe,
ncr_attach,
NCR_810_ID,
"ncr 53c810 scsi",
ncr_intr
};
static u_long ncr_count;
struct pci_driver ncr825_device = {
struct pci_driver ncr_device = {
ncr_probe,
ncr_attach,
NCR_825_ID,
"ncr 53c825 scsi",
ncr_intr
&ncr_count
};
#endif /* !__NetBSD__ */
@ -1429,14 +1412,8 @@ struct scsi_switch ncr_switch =
static char *ncr_name (ncb_p np)
{
static char name[10];
int idx;
for (idx = 0; idx < NNCR; idx++)
if (ncrp[idx] == np) {
sprintf(name, "ncr%d", idx);
return (name);
}
return ("ncr?");
sprintf(name, "ncr%d", np->unit);
return (name);
}
#endif
@ -3092,7 +3069,7 @@ static void ncr_script_copy_and_bind (struct script *script, ncb_p np)
#ifdef SCSI_NCR_DEBUG
if (ncr_debug & DEBUG_SCRIPT)
printf ("%x: <%x>\n",
(u_long)(src-1), opcode);
(unsigned)(src-1), (unsigned)opcode);
#endif /* SCSI_NCR_DEBUG */
/*
@ -3245,13 +3222,22 @@ ncr_probe(parent, self, aux)
#else /* !__NetBSD__ */
static int ncr_probe(pcici_t config_id)
static char* ncr_probe (pcici_t tag, pcidi_t type)
{
if (ncr_units >= NNCR) return (-1);
return (ncr_units);
switch (type) {
case NCR_810_ID:
return ("ncr 53c810 scsi");
case NCR_825_ID:
return ("ncr 53c825 wide scsi");
}
return (0);
}
#endif /* !__NetBSD__ */
/*==========================================================
**
@ -3307,39 +3293,36 @@ ncr_attach(parent, self, aux)
#else /* !__NetBSD__ */
static int ncr_attach (pcici_t config_id)
static void ncr_attach (pcici_t config_id, int unit)
{
int retval;
ncb_p np = ncrp[ncr_units];
ncb_p np;
#if ! (__FreeBSD__ >= 2)
extern unsigned bio_imask;
#endif
/*
** allocate structure
*/
if (!np) {
np = (ncb_p) malloc (sizeof (struct ncb),
M_DEVBUF, M_NOWAIT);
if (!np) return (0);
ncrp[ncr_units]=np;
}
np = (ncb_p) malloc (sizeof (struct ncb), M_DEVBUF, M_WAITOK);
if (!np) return;
ncrp[unit]=np;
/*
** initialize structure.
*/
bzero (np, sizeof (*np));
np->unit = unit;
/*
** Try to map the controller chip to
** virtual and physical memory.
*/
retval = pci_map_mem (config_id, 0x14, &np->vaddr, &np->paddr);
if (retval) {
printf ("%s: pci_map_mem failed.\n", ncr_name (np));
return (retval);
};
if (!pci_map_mem (config_id, 0x14, &np->vaddr, &np->paddr))
return;
#endif /* !__NetBSD__ */
@ -3409,9 +3392,18 @@ static int ncr_attach (pcici_t config_id)
if (ncr_snooptest (np)) {
printf ("CACHE INCORRECTLY CONFIGURED.\n");
return (0);
return;
};
#ifndef __NetBSD__
/*
** Install the interrupt handler.
*/
if (!pci_map_int (config_id, ncr_intr, np, &bio_imask))
printf ("\tinterruptless mode: reduced performance.\n");
#endif
/*
** After SCSI devices have been opened, we cannot
** reset the bus safely, so we do it here.
@ -3431,7 +3423,7 @@ static int ncr_attach (pcici_t config_id)
ncr_name (np));
DELAY (1000000);
#endif
printf ("%s scanning for targets 0..%d ($Revision: 1.5 $)\n",
printf ("%s scanning for targets 0..%d ($Revision: 2.11 $)\n",
ncr_name (np), MAX_TARGET-1);
/*
@ -3443,7 +3435,7 @@ static int ncr_attach (pcici_t config_id)
#ifdef __NetBSD__
np->sc_link.adapter_softc = np;
#else /* !__NetBSD__ */
np->sc_link.adapter_unit = ncr_units;
np->sc_link.adapter_unit = unit;
#endif /* !__NetBSD__ */
np->sc_link.adapter_targ = np->myaddr;
np->sc_link.adapter = &ncr_switch;
@ -3455,7 +3447,7 @@ static int ncr_attach (pcici_t config_id)
scsi_attachdevs (&np->sc_link);
#endif /* !__NetBSD__ */
#else /* ANCIENT */
scsi_attachdevs (ncr_units, np->myaddr, &ncr_switch);
scsi_attachdevs (unit, np->myaddr, &ncr_switch);
#endif /* ANCIENT */
/*
@ -3468,10 +3460,7 @@ static int ncr_attach (pcici_t config_id)
** Done.
*/
#ifndef __NetBSD__
ncr_units++;
return(1);
#endif
return;
}
/*==========================================================
@ -3483,46 +3472,27 @@ static int ncr_attach (pcici_t config_id)
**==========================================================
*/
#ifdef __NetBSD__
int
ncr_intr(np)
ncb_p np;
{
int n = 0;
#else /* !__NetBSD__ */
static int ncr_intr (int dev)
{
ncb_p np;
int n=0;
/*
** Sanity check
*/
assert (dev<NNCR);
if (dev >= ncr_units) return (0);
np = ncrp[dev];
#endif /* !__NetBSD__ */
#ifdef SCSI_NCR_DEBUG
if (ncr_debug & DEBUG_TINY) printf ("[");
#endif /* SCSI_NCR_DEBUG */
/*
** Repeat until no outstanding ints
*/
while (INB(nc_istat) & (INTF|SIP|DIP)) {
ncr_exception (np);
n=1;
};
if (INB(nc_istat) & (INTF|SIP|DIP)) {
/*
** Repeat until no outstanding ints
*/
do {
ncr_exception (np);
} while (INB(nc_istat) & (INTF|SIP|DIP));
/*
** Slowdown timeout function.
*/
if (n) np->ticks = 100;
n=1;
np->ticks = 100;
};
#ifdef SCSI_NCR_DEBUG
if (ncr_debug & DEBUG_TINY) printf ("]\n");
@ -3637,7 +3607,7 @@ static INT32 ncr_start (struct scsi_xfer * xp)
if (ncr_debug & DEBUG_TINY) {
PRINT_ADDR(xp);
printf ("CMD=%x F=%x L=%x ", cmd->opcode,
xp->flags, xp->datalen);
(unsigned)xp->flags, (unsigned) xp->datalen);
}
#endif /* SCSI_NCR_DEBUG */
@ -3765,8 +3735,12 @@ static INT32 ncr_start (struct scsi_xfer * xp)
cp2 = cp2->next_ccb;
if (cp2) continue;
cp->tag=lp->lasttag;
PRINT_ADDR(xp);
printf ("using tag #%d.\n", cp->tag);
#ifdef SCSI_NCR_DEBUG
if (ncr_debug & DEBUG_TAGS) {
PRINT_ADDR(xp);
printf ("using tag #%d.\n", cp->tag);
};
#endif /* SCSI_NCR_DEBUG */
};
} else {
cp->tag=0;
@ -3813,7 +3787,7 @@ static INT32 ncr_start (struct scsi_xfer * xp)
}
/*
** can be overwritten by ncrstat
** can be overwritten by ncrcontrol
*/
switch (np->order) {
case M_SIMPLE_TAG:
@ -3991,7 +3965,9 @@ static INT32 ncr_start (struct scsi_xfer * xp)
#ifdef SCSI_NCR_DEBUG
if(ncr_debug & DEBUG_QUEUE)
printf ("%s: queuepos=%d tryoffset=%d.\n", ncr_name (np),
np->squeueput, np->script->startpos[0]-(vtophys(&np->script->tryloop)));
np->squeueput,
(unsigned)(np->script->startpos[0]-
(vtophys(&np->script->tryloop))));
#endif /* SCSI_NCR_DEBUG */
/*
@ -4049,7 +4025,7 @@ static INT32 ncr_start (struct scsi_xfer * xp)
if (!(xp->flags & ITSDONE)) {
printf ("%s: abortion failed at %x.\n",
ncr_name (np), INL(nc_dsp));
ncr_name (np), (unsigned) INL(nc_dsp));
ncr_init (np, "timeout", HS_TIMEOUT);
};
@ -4114,7 +4090,7 @@ void ncr_complete (ncb_p np, ccb_p cp)
#ifdef SCSI_NCR_DEBUG
if (ncr_debug & DEBUG_TINY)
printf ("CCB=%x STAT=%x/%x\n", (u_long)cp & 0xfff,
printf ("CCB=%x STAT=%x/%x\n", (unsigned)cp & 0xfff,
cp->host_status,cp->scsi_status);
#endif /* SCSI_NCR_DEBUG */
@ -4279,7 +4255,7 @@ void ncr_complete (ncb_p np, ccb_p cp)
*/
PRINT_ADDR(xp);
printf ("COMMAND FAILED (%x %x) @%x.\n",
cp->host_status, cp->scsi_status, cp);
cp->host_status, cp->scsi_status, (unsigned)cp);
xp->error = XS_DRIVER_STUFFUP;
}
@ -4361,6 +4337,8 @@ void ncr_wakeup (ncb_p np, u_long code)
** complete all jobs that are not IDLE.
*/
int s=splbio();
ccb_p cp = &np->ccb;
while (cp) {
switch (cp->host_status) {
@ -4387,6 +4365,7 @@ void ncr_wakeup (ncb_p np, u_long code)
};
cp = cp -> link_ccb;
};
splx (s);
}
/*==========================================================
@ -4758,7 +4737,7 @@ static void ncr_usercmd (ncb_p np)
break;
case UC_SETTAGS:
if (np->user.data > SCSI_NCR_MAX_TAGS)
if (np->user.data > MAX_TAGS)
break;
for (t=0; t<MAX_TARGET; t++) {
if (!((np->user.target>>t)&1)) continue;
@ -4895,7 +4874,7 @@ static void ncr_timeout (ncb_p np)
if (cp->phys.header.launch.l_paddr ==
vtophys (&np->script->select)) {
printf ("%s: timeout ccb=%x (skip)\n",
ncr_name (np), cp);
ncr_name (np), (unsigned)cp);
cp->phys.header.launch.l_paddr
= vtophys (&np->script->skip);
};
@ -4967,10 +4946,10 @@ static void ncr_timeout (ncb_p np)
*/
if (np->mcount == 100) {
if (np->imask & (np->imask-1)) {
printf ("%s: please configure intr mask %x.\n",
printf ("%s: uses one of the irq in %x.\n",
ncr_name (np), np->imask);
} else {
printf ("%s: please configure intr %d.\n",
printf ("%s: please configure irq %d.\n",
ncr_name (np), ffs (np->imask)-1);
};
np->mcount++;
@ -5022,7 +5001,8 @@ void ncr_exception (ncb_p np)
printf ("<%d|%x:%x|%x:%x>",
INB(nc_scr0),
dstat,sist,
INL(nc_dsp),INL(nc_dbc));
(unsigned)INL(nc_dsp),
(unsigned)INL(nc_dbc));
#endif /* SCSI_NCR_DEBUG */
if ((dstat==DFE) && (sist==PAR)) return;
@ -5117,7 +5097,8 @@ void ncr_exception (ncb_p np)
ncr_name (np), INB (nc_ctest0)&7, dstat, sist,
INB (nc_sbcl),
INB (nc_sxfer),INB (nc_scntl3),
dsp = INL (nc_dsp), INL (nc_dbc));
(unsigned) (dsp = INL (nc_dsp)),
(unsigned) INL (nc_dbc));
/*----------------------------------------
** clean up the dma fifo
@ -5243,7 +5224,7 @@ void ncr_exception (ncb_p np)
**==========================================================
**
** There seems to be a bug in the 53c810.
** Although a STO-Interupt is pending,
** Although a STO-interrupt is pending,
** it continues executing script commands.
** But it will fail and interrupt (IID) on
** the next instruction where it's looking
@ -5381,11 +5362,14 @@ static void ncr_int_ma (ncb_p np)
*/
if (ncr_debug & (DEBUG_TINY|DEBUG_PHASE)) {
printf ("P%d%d ",cmd&7, sbcl&7);
printf ("RL=%d D=%d SS0=%x ",rest,delta,ss0);
printf ("RL=%d D=%d SS0=%x ",
(unsigned) rest, (unsigned) delta, ss0);
};
if (ncr_debug & DEBUG_PHASE) {
printf ("\nCP=%x CP2=%x DSP=%x NXT=%x VDSP=%x CMD=%x ",
cp, np->header.cp, dsp, nxtdsp, vdsp, cmd);
(unsigned)cp, (unsigned)np->header.cp,
(unsigned)dsp,
(unsigned)nxtdsp, (unsigned)vdsp, cmd);
};
#endif /* SCSI_NCR_DEBUG */
@ -5407,7 +5391,10 @@ static void ncr_int_ma (ncb_p np)
#ifdef SCSI_NCR_DEBUG
if (ncr_debug & DEBUG_PHASE) {
printf ("OCMD=%x\nTBLP=%x OLEN=%x OADR=%x\n",
vdsp[0] >> 24, tblp, olen, oadr);
(unsigned) (vdsp[0] >> 24),
(unsigned) tblp,
(unsigned) olen,
(unsigned) oadr);
};
#endif /* SCSI_NCR_DEBUG */
@ -5419,7 +5406,8 @@ static void ncr_int_ma (ncb_p np)
if (cmd & 0x06) {
PRINT_ADDR(cp->xfer);
printf ("phase change %d-%d %d@%x resid=%d.\n",
cmd&7, sbcl&7, olen, oadr, rest);
cmd&7, sbcl&7, (unsigned)olen,
(unsigned)oadr, (unsigned)rest);
OUTB (nc_dcntl, (STD|NOCOM));
return;
@ -5447,7 +5435,10 @@ static void ncr_int_ma (ncb_p np)
PRINT_ADDR(cp->xfer);
printf ("newcmd[%d] %x %x %x %x.\n",
newcmd - cp->patch,
newcmd[0], newcmd[1], newcmd[2], newcmd[3]);
(unsigned)newcmd[0],
(unsigned)newcmd[1],
(unsigned)newcmd[2],
(unsigned)newcmd[3]);
}
#endif /* SCSI_NCR_DEBUG */
/*
@ -5941,7 +5932,7 @@ void ncr_int_sir (ncb_p np)
PRINT_ADDR(cp->xfer);
printf ("M_REJECT received (%x:%x).\n",
np->lastmsg, np->msgout[0]);
(unsigned)np->lastmsg, np->msgout[0]);
break;
case SIR_REJECT_SENT:
@ -5989,10 +5980,10 @@ void ncr_int_sir (ncb_p np)
PRINT_ADDR(cp->xfer);
printf ("M_DISCONNECT received, but datapointer not saved:\n"
" data=%x save=%x goal=%x.\n",
INL (nc_temp),
np->header.savep,
np->header.goalp);
"\tdata=%x save=%x goal=%x.\n",
(unsigned) INL (nc_temp),
(unsigned) np->header.savep,
(unsigned) np->header.goalp);
break;
/*--------------------------------------------------------------------
@ -6047,7 +6038,6 @@ void ncr_int_sir (ncb_p np)
**
**-----------------------------------------------
*/
/*
** Look for a disconnected job.
*/
@ -6209,6 +6199,8 @@ static void ncr_alloc_ccb (ncb_p np, struct scsi_xfer * xp)
tp->jump_lcb.l_cmd = (SCR_JUMP);
tp->jump_lcb.l_paddr = vtophys (&np->script->abort);
np->jump_tcb.l_paddr = vtophys (&tp->jump_tcb);
ncr_setmaxtags (tp, SCSI_NCR_MAX_TAGS);
}
/*
@ -6267,7 +6259,7 @@ static void ncr_alloc_ccb (ncb_p np, struct scsi_xfer * xp)
#ifdef SCSI_NCR_DEBUG
if (ncr_debug & DEBUG_ALLOC) {
PRINT_ADDR(xp);
printf ("new ccb @%x.\n", cp);
printf ("new ccb @%x.\n", (unsigned) cp);
}
#endif /* SCSI_NCR_DEBUG */
@ -6414,7 +6406,7 @@ static int ncr_scatter
#ifdef SCSI_NCR_DEBUG
if(ncr_debug & DEBUG_SCATTER)
printf("ncr?:\tscattering virtual=0x%x size=%d chunk=%d.\n",
(u_long) vaddr, (u_long) datalen, chunk);
(unsigned) vaddr, (unsigned) datalen, (unsigned) chunk);
#endif /* SCSI_NCR_DEBUG */
/*
@ -6456,7 +6448,10 @@ static int ncr_scatter
#ifdef SCSI_NCR_DEBUG
if(ncr_debug & DEBUG_SCATTER)
printf ("\tseg #%d addr=%x size=%d (rest=%d).\n",
segment, segaddr, segsize, datalen);
segment,
(unsigned) segaddr,
(unsigned) segsize,
(unsigned) datalen);
#endif /* SCSI_NCR_DEBUG */
phys->data[segment].addr = segaddr;
@ -6466,7 +6461,7 @@ static int ncr_scatter
if (datalen) {
printf("ncr?: scatter/gather failed (residue=%d).\n",
datalen);
(unsigned) datalen);
return (-1);
};
@ -6478,7 +6473,7 @@ static int ncr_scatter
**
** Test the pci bus snoop logic :-(
**
** Has to be called with disabled interupts.
** Has to be called with interrupts disabled.
**
**
**==========================================================
@ -6522,17 +6517,17 @@ static int ncr_snooptest (struct ncb* np)
*/
if (host_wr != ncr_rd) {
printf ("CACHE TEST FAILED: host wrote %d, ncr read %d.\n",
host_wr, ncr_rd);
(int) host_wr, (int) ncr_rd);
err |= 1;
};
if (host_rd != ncr_wr) {
printf ("CACHE TEST FAILED: ncr wrote %d, host read %d.\n",
ncr_wr, host_rd);
(int) ncr_wr, (int) host_rd);
err |= 2;
};
if (ncr_bk != ncr_wr) {
printf ("CACHE TEST FAILED: ncr wrote %d, read back %d.\n",
ncr_wr, ncr_bk);
(int) ncr_wr, (int) ncr_bk);
err |= 4;
};
return (err);
@ -6627,6 +6622,7 @@ static struct table_entry device_tab[] =
{
{"WangDAT", "Model 2600", "01.7", QUIRK_NOMSG},
{"WangDAT", "Model 3200", "02.2", QUIRK_NOMSG},
{"WangDAT", "Model 1300", "02.4", QUIRK_NOMSG},
{"", "", "", 0} /* catch all: must be last entry. */
};
@ -6639,17 +6635,17 @@ static u_long ncr_lookup(char * id)
d = id+8;
r = p->manufacturer;
while (c=*r++) if (c!=*d++) break;
while ((c=*r++)) if (c!=*d++) break;
if (c) continue;
d = id+16;
r = p->model;
while (c=*r++) if (c!=*d++) break;
while ((c=*r++)) if (c!=*d++) break;
if (c) continue;
d = id+32;
r = p->version;
while (c=*r++) if (c!=*d++) break;
while ((c=*r++)) if (c!=*d++) break;
if (c) continue;
return (p->info);
@ -6712,3 +6708,5 @@ static void ncr_getclock (ncb_p np)
/*=========================================================================*/
#endif /* KERNEL */

View File

@ -1,6 +1,6 @@
/**************************************************************************
**
** $Id: pci.c,v 1.5 1994/09/28 16:34:07 se Exp $
** $Id: pci.c,v 2.12 94/10/11 22:20:37 wolf Oct11 $
**
** General subroutines for the PCI bus on 80*86 systems.
** pci_configure ()
@ -33,27 +33,17 @@
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**
**-------------------------------------------------------------------------
***************************************************************************
*/
#include <pci.h>
#if NPCI > 0
/*========================================================
**
** Configuration
**
**========================================================
*/
/*
** maximum number of devices which share one interrupt line
*/
#ifndef PCI_MAX_DPI
#define PCI_MAX_DPI (4)
#endif /*PCI_MAX_DPI*/
#ifndef __FreeBSD2__
#if __FreeBSD__ >= 2
#define __FreeBSD2__
#endif
#endif
/*========================================================
**
@ -64,101 +54,54 @@
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/malloc.h>
#include <sys/errno.h>
#include <vm/vm.h>
#include <vm/vm_param.h>
#include <i386/isa/icu.h>
#include <i386/isa/isa.h>
#include <i386/isa/isa_device.h>
#include <i386/pci/pci.h>
#include <i386/pci/pci_device.h>
#include <i386/pci/pcibios.h>
#include <i386/isa/icu.h>
#include <i386/pci/pcireg.h>
/*
** Function prototypes missing in system headers
*/
#if ! (__FreeBSD__ >= 2)
#ifndef __FreeBSD2__
extern pmap_t pmap_kernel(void);
static vm_offset_t pmap_mapdev (vm_offset_t paddr, vm_size_t vsize);
#endif
/*========================================================
**
** Autoconfiguration (of isa bus)
**
**========================================================
*/
/*
** per slot data structure for passing interupts..
*/
static struct {
u_short number;
u_short isanum;
struct {
int (*proc)(int dev);
dev_t unit;
} vector[PCI_MAX_DPI];
} pcidata [NPCI];
* Type of the first (asm) part of an interrupt handler.
*/
typedef void inthand_t __P((u_int cs, u_int ef, u_int esp, u_int ss));
/*
** check device ready
*/
static int pciprobe (struct isa_device *dev)
{
if (dev->id_unit >= NPCI)
return (0);
if (!pci_conf_mode())
return (0);
return (-1);
}
* Usual type of the second (C) part of an interrupt handler. Some bogus
* ones need the arg to be the interrupt frame (and not a copy of it, which
* is all that is possible in C).
*/
typedef void inthand2_t __P((int unit));
/*
** initialize the driver structure
*/
static int pciattach (struct isa_device *isdp)
{
pcidata[isdp->id_unit].number = 0;
pcidata[isdp->id_unit].isanum = ffs(isdp->id_irq)-1;
return (1);
}
/*
** ISA driver structure
*/
struct isa_driver pcidriver = {
pciprobe,
pciattach,
"pci"
};
/*========================================================
** XXX @FreeBSD2@
**
** Interrupt forward from isa to pci devices.
**
**========================================================
** Unfortunately, the mptr argument is _no_ pointer in 2.0 FreeBSD.
** We would prefer a pointer because it enables us to install
** new interrupt handlers at any time.
** In 2.0 FreeBSD later installed interrupt handlers may change
** the xyz_imask, but this would not be recognized by handlers
** which are installed before.
*/
static int
register_intr __P((int intr, int device_id, unsigned int flags,
inthand2_t *handler, unsigned int * mptr, int unit));
extern unsigned intr_mask[ICU_LEN];
void pciintr (int unit)
{
u_short i;
if (unit >= NPCI) return;
for (i=0; i<pcidata[unit].number; i++) {
(void)(*pcidata[unit].vector[i].proc)
(pcidata[unit].vector[i].unit);
};
}
#endif /* !__FreeBSD2__ */
/*========================================================
**
@ -183,52 +126,82 @@ void pciintr (int unit)
#define PCI_PMEM_START 0xc0000000
#endif
static vm_offset_t pci_paddr = PCI_PMEM_START;
static vm_offset_t pci_paddr = PCI_PMEM_START;
/*--------------------------------------------------------
**
** The pci device interrupt lines should have been
** assigned by the bios. But if the bios failed to
** to it, we set it.
**
**--------------------------------------------------------
*/
#ifndef PCI_IRQ
#define PCI_IRQ 0
#endif
static u_long pci_irq = PCI_IRQ;
/*---------------------------------------------------------
**
** pci_configure ()
**
** Probe all devices on pci bus and attach them.
**
** May be called more than once.
** Any device is attached only once.
** (Attached devices are remembered in pci_seen.)
**
**---------------------------------------------------------
*/
static void not_supported (pcici_t tag, u_long type);
static unsigned long pci_seen[NPCI];
static int pci_conf_count;
void pci_configure()
{
u_char device,last_device;
u_short bus,last_bus;
u_short bus;
pcici_t tag;
pcidi_t type;
u_long data;
int unit;
int intpin;
int isanum;
int pci_mode;
int pci_mechanism;
int pciint;
int irq;
char* name=0;
int newdev=0;
struct pci_driver *drp;
struct pci_driver *drp=0;
struct pci_device *dvp;
/*
** check pci bus present
*/
pci_mode = pci_conf_mode ();
if (!pci_mode) return;
last_bus = pci_last_bus ();
last_device = pci_mode==1 ? 31 : 15;
pci_mechanism = pci_conf_mode ();
if (!pci_mechanism) return;
last_device = pci_mechanism==1 ? 31 : 15;
/*
** hello world ..
*/
for (bus=0;bus<NPCI;bus++) {
#ifndef PCI_QUIET
printf ("pci*: mode=%d, scanning bus 0..%d, device 0..%d.\n",
pci_mode, last_bus, last_device);
printf ("pci%d: scanning device 0..%d, mechanism=%d.\n",
bus, last_device, pci_mechanism);
#endif
for (bus=0;bus<=last_bus; bus++)
for (device=0; device<=last_device; device ++) {
if (pci_seen[bus] & (1ul << device))
continue;
tag = pcitag (bus, device, 0);
type = pci_conf_read (tag, PCI_ID_REG);
@ -238,137 +211,90 @@ void pci_configure()
** lookup device in ioconfiguration:
*/
for (dvp = pci_devtab; dvp->pd_device_id; dvp++) {
if (dvp->pd_device_id == type) break;
};
drp = dvp->pd_driver;
if (!dvp->pd_device_id) {
/*
** not found
** try to dig out some information.
**
** By Garrett Wollman
** <wollman@halloran-eldar.lcs.mit.edu>
*/
int data = pci_conf_read(tag, PCI_CLASS_REG);
vm_offset_t va;
vm_offset_t pa;
int reg;
switch (data & PCI_CLASS_MASK) {
case PCI_CLASS_PREHISTORIC:
if ((data & PCI_SUBCLASS_MASK)
!= PCI_SUBCLASS_PREHISTORIC_VGA)
break;
case PCI_CLASS_DISPLAY:
for (reg = PCI_MAP_REG_START;
reg < PCI_MAP_REG_END;
reg += 4) {
data = pci_map_mem(tag, reg, &va, &pa);
if (data == 0)
printf (
"pci%d:%d: mapped VGA-like device at physaddr 0x%lx\n",
bus, device, (u_long)pa);
}
for (dvp = pci_devtab; dvp->pd_name; dvp++) {
drp = dvp->pd_driver;
if (!drp)
continue;
};
if ((name=(*drp->probe)(tag, type)))
break;
};
if (!dvp->pd_name) {
#ifndef PCI_QUIET
if (pci_conf_count)
continue;
printf("pci%d:%d: ", bus, device);
not_supported (tag, type);
#endif
};
if (!drp) {
if(dvp->pd_flags & PDF_LOADABLE) {
printf("%s: loadable device on pci%d:%d\n",
dvp->pd_name, bus, device);
}
continue;
}
};
pci_seen[bus] |= (1ul << device);
/*
** found it.
** probe returns the device unit.
** Get and increment the unit.
*/
unit = (*drp->probe) (tag);
unit = (*drp->count)++;
if (unit<0) {
printf ("%s <%s>: probe failed on pci%d:%d\n",
dvp->pd_name, drp->name, bus, device);
continue;
};
/*
** ignore device ?
*/
printf ("%s%d <%s>", dvp->pd_name, unit, drp->name);
if (!*name) continue;
/*
** Announce this device
*/
newdev++;
printf ("%s%d <%s>", dvp->pd_name, unit, name);
/*
** install interrupts
** Get the int pin number (pci interrupt number a-d)
** from the pci configuration space.
*/
data = pci_conf_read (tag, PCI_INTERRUPT_REG);
intpin = PCI_INTERRUPT_PIN_EXTRACT(data);
if (intpin) {
int idx=NPCI;
pciint = PCI_INTERRUPT_PIN_EXTRACT(data);
if (pciint) {
printf (" int %c", 0x60+pciint);
/*
** Usage of int line register (if set by bios)
** Matt Thomas <thomas@lkg.dec.com>
** If the interrupt line register is not set,
** set it now from PCI_IRQ.
*/
isanum = PCI_INTERRUPT_LINE_EXTRACT(data);
if (isanum) {
if (!(PCI_INTERRUPT_LINE_EXTRACT(data))) {
/*
** @INT@ FIXME!!!
**
** Should try to use "register_interupt"
** at this point.
*/
irq = pci_irq & 0x0f;
pci_irq >>= 4;
printf (" line=%d", isanum);
for (idx = 0; idx < NPCI; idx++) {
if (pcidata[idx].isanum == isanum)
break;
};
data = PCI_INTERRUPT_LINE_INSERT(data, irq);
printf (" (config)");
pci_conf_write (tag, PCI_INTERRUPT_REG, data);
};
/*
** Or take the device number as index ...
*/
if (idx >= NPCI) idx = device;
irq = PCI_INTERRUPT_LINE_EXTRACT(data);
/*
** And install the interrupt.
** If it's zero, the isa irq number is unknown,
** and we cannot bind the pci interrupt to isa.
*/
if (idx<NPCI) {
u_short entry = pcidata[idx].number;
printf (" irq %c", 0x60+intpin);
if (entry < PCI_MAX_DPI) {
pcidata[idx].vector[entry].proc = drp->intr;
pcidata[idx].vector[entry].unit = unit;
entry++;
};
printf (" isa=%d [%d]",pcidata[idx].isanum, entry);
pcidata[idx].number=entry;
} else {
printf (" no int");
};
if (irq)
printf (" irq %d", irq);
else
printf (" not bound");
};
/*
** enable memory access
*/
data = pci_conf_read (tag, PCI_COMMAND_STATUS_REG)
& 0xffff | PCI_COMMAND_MEM_ENABLE;
data = (pci_conf_read (tag, PCI_COMMAND_STATUS_REG)
& 0xffff) | PCI_COMMAND_MEM_ENABLE;
pci_conf_write (tag, (u_char) PCI_COMMAND_STATUS_REG, data);
@ -380,13 +306,16 @@ void pci_configure()
printf (" on pci%d:%d\n", bus, device);
(void) (*drp->attach) (tag);
}
(*drp->attach) (tag, unit);
};
};
#ifndef PCI_QUIET
printf ("pci uses physical addresses from 0x%lx to 0x%lx\n",
if (newdev)
printf ("pci uses physical addresses from 0x%lx to 0x%lx\n",
(u_long)PCI_PMEM_START, (u_long)pci_paddr);
#endif
pci_conf_count++;
}
/*-----------------------------------------------------------------------
@ -403,7 +332,8 @@ int pci_map_port (pcici_t tag, u_long reg, u_short* pa)
/*
** @MAPIO@ not yet implemented.
*/
return (ENOSYS);
printf ("pci_map_port failed: not yet implemented\n");
return (0);
}
/*-----------------------------------------------------------------------
@ -425,8 +355,11 @@ int pci_map_mem (pcici_t tag, u_long reg, vm_offset_t* va, vm_offset_t* pa)
** sanity check
*/
if (reg <= PCI_MAP_REG_START || reg >= PCI_MAP_REG_END || (reg & 3))
return (EINVAL);
if (reg < PCI_MAP_REG_START || reg >= PCI_MAP_REG_END || (reg & 3)) {
printf ("pci_map_mem failed: bad register=0x%x\n",
(unsigned)reg);
return (0);
};
/*
** get size and type of memory
@ -445,7 +378,9 @@ int pci_map_mem (pcici_t tag, u_long reg, vm_offset_t* va, vm_offset_t* pa)
break;
default: /* unknown */
return (EINVAL);
printf ("pci_map_mem failed: bad memory type=0x%x\n",
(unsigned) data);
return (0);
};
/*
@ -455,18 +390,19 @@ int pci_map_mem (pcici_t tag, u_long reg, vm_offset_t* va, vm_offset_t* pa)
vsize = round_page (-(data & PCI_MAP_MEMORY_ADDRESS_MASK));
if (!vsize) return (EINVAL);
if (!vsize) return (0);
/*
** align physical address to virtual size
*/
if (data = pci_paddr % vsize)
if ((data = pci_paddr % vsize))
pci_paddr += vsize - data;
vaddr = pmap_mapdev (pci_paddr, vsize);
vaddr = (vm_offset_t) pmap_mapdev (pci_paddr, vsize);
if (!vaddr) return (EINVAL);
if (!vaddr) return (0);
#ifndef PCI_QUIET
/*
@ -474,7 +410,7 @@ int pci_map_mem (pcici_t tag, u_long reg, vm_offset_t* va, vm_offset_t* pa)
*/
printf ("\treg%d: virtual=0x%lx physical=0x%lx\n",
reg, (u_long)vaddr, (u_long)pci_paddr);
(unsigned) reg, (u_long)vaddr, (u_long)pci_paddr);
#endif
/*
@ -496,50 +432,77 @@ int pci_map_mem (pcici_t tag, u_long reg, vm_offset_t* va, vm_offset_t* pa)
pci_paddr += vsize;
return (0);
return (1);
}
/*-----------------------------------------------------------
/*-----------------------------------------------------------------------
**
** Mapping of physical to virtual memory
** Map pci interrupts to isa interrupts.
**
**-----------------------------------------------------------
**-----------------------------------------------------------------------
*/
#if ! (__FreeBSD__ >= 2)
static unsigned int pci_int_mask [16];
extern vm_map_t kernel_map;
static vm_offset_t pmap_mapdev (vm_offset_t paddr, vm_size_t vsize)
int pci_map_int (pcici_t tag, int(*func)(), void* arg, unsigned* maskptr)
{
vm_offset_t vaddr,value;
u_long result;
int irq;
unsigned mask;
vaddr = vm_map_min (kernel_map);
irq = PCI_INTERRUPT_LINE_EXTRACT(
pci_conf_read (tag, PCI_INTERRUPT_REG));
result = vm_map_find (kernel_map, (void*)0, (vm_offset_t) 0,
&vaddr, vsize, TRUE);
if (result != KERN_SUCCESS) {
printf (" vm_map_find failed(%d)\n", result);
if (irq >= 16 || irq <= 0) {
printf ("pci_map_int failed: no int line set.\n");
return (0);
};
}
/*
** map physical
*/
mask = 1ul << irq;
value = vaddr;
while (vsize >= NBPG) {
pmap_enter (pmap_kernel(), vaddr, paddr,
VM_PROT_READ|VM_PROT_WRITE, TRUE);
vaddr += NBPG;
paddr += NBPG;
vsize -= NBPG;
};
return (value);
}
if (!maskptr)
maskptr = &pci_int_mask[irq];
INTRMASK (*maskptr, mask);
register_intr(
irq, /* isa irq */
0, /* deviced?? */
0, /* flags? */
(inthand2_t*) func, /* handler */
#ifdef __FreeBSD2__
*maskptr, /* mask */
#else
maskptr, /* mask pointer */
#endif
(int) arg); /* handler arg */
#ifdef __FreeBSD2__
/*
** 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;
};
#endif
INTREN (mask);
return (1);
}
/*-----------------------------------------------------------
**
@ -554,7 +517,7 @@ struct vt {
static struct vt VendorTable[] = {
{0x1002, "ATI TECHNOLOGIES INC"},
{0x1011, "DIGITAL EQUIPMENT CORP."},
{0x1011, "DIGITAL EQUIPMENT CORPORATION"},
{0x101A, "NCR"},
{0x102B, "MATROX"},
{0x1045, "OPTI"},
@ -604,18 +567,107 @@ void not_supported (pcici_t tag, u_long type)
case 1:
case 5:
printf (" map(%lx): io(%lx)\n", reg, data & ~3);
printf (" map(%x): io(%lx)\n",
reg, data & ~3);
break;
case 0:
printf (" map(%lx): mem32(%lx)\n", reg, data & ~7);
printf (" map(%x): mem32(%lx)\n",
reg, data & ~7);
break;
case 2:
printf (" map(%lx): mem20(%lx)\n", reg, data & ~7);
printf (" map(%x): mem20(%lx)\n",
reg, data & ~7);
break;
case 4:
printf (" map(%lx): mem64(%lx)\n", reg, data & ~7);
printf (" map(%x): mem64(%lx)\n",
reg, data & ~7);
break;
}
}
}
#endif
#ifndef __FreeBSD2__
/*-----------------------------------------------------------
**
** Mapping of physical to virtual memory
**
**-----------------------------------------------------------
*/
extern vm_map_t kernel_map;
static vm_offset_t pmap_mapdev (vm_offset_t paddr, vm_size_t vsize)
{
vm_offset_t vaddr,value;
u_long result;
vaddr = vm_map_min (kernel_map);
result = vm_map_find (kernel_map, (void*)0, (vm_offset_t) 0,
&vaddr, vsize, TRUE);
if (result != KERN_SUCCESS) {
printf (" vm_map_find failed(%d)\n", result);
return (0);
};
/*
** map physical
*/
value = vaddr;
while (vsize >= NBPG) {
pmap_enter (pmap_kernel(), vaddr, paddr,
VM_PROT_READ|VM_PROT_WRITE, TRUE);
vaddr += NBPG;
paddr += NBPG;
vsize -= NBPG;
};
return (value);
}
/*------------------------------------------------------------
**
** Emulate the register_intr() function of FreeBSD 2.0
**
** requires a patch:
** FreeBSD 2.0: "/sys/i386/isa/vector.s"
** 386bsd0.1: "/sys/i386/isa/icu.s"
** 386bsd1.0: Please ask Jesus Monroy Jr.
**
**------------------------------------------------------------
*/
#include <machine/segments.h>
int pci_int_unit [16];
inthand2_t* (pci_int_hdlr [16]);
unsigned int * pci_int_mptr [16];
unsigned int pci_int_count[16];
extern void
Vpci3(), Vpci4(), Vpci5(), Vpci6(), Vpci7(), Vpci8(), Vpci9(),
Vpci10(), Vpci11(), Vpci12(), Vpci13(), Vpci14(), Vpci15();
static inthand_t* pci_int_glue[16] = {
0, 0, 0, Vpci3, Vpci4, Vpci5, Vpci6, Vpci7, Vpci8,
Vpci9, Vpci10, Vpci11, Vpci12, Vpci13, Vpci14, Vpci15 };
static int
register_intr __P((int intr, int device_id, unsigned int flags,
inthand2_t *handler, unsigned int* mptr, int unit))
{
if (intr >= 16 || intr <= 2)
return (EINVAL);
if (pci_int_hdlr [intr])
return (EBUSY);
pci_int_hdlr [intr] = handler;
pci_int_unit [intr] = unit;
pci_int_mptr [intr] = mptr;
setidt(NRSVIDT + intr, pci_int_glue[intr], SDT_SYS386IGT, SEL_KPL);
return (0);
}
#endif /* __FreeBSD2__ */
#endif /* NPCI */

View File

@ -1,6 +1,6 @@
/**************************************************************************
**
** $Id: pci_config.c,v 1.5 1994/09/28 16:34:09 se Exp $
** $Id: pci_config.c,v 2.3 94/10/09 21:10:21 wolf Oct11 $
**
** @PCI@ this should be part of "ioconf.c".
**
@ -32,50 +32,40 @@
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**
**-------------------------------------------------------------------------
***************************************************************************
*/
#include <sys/types.h>
#include <i386/pci/pci.h>
#include <i386/pci/pci_device.h>
#include <i386/pci/pcireg.h>
#include "ncr.h"
#include <ncr.h>
#if NNCR>0
extern struct pci_driver ncr810_device;
extern struct pci_driver ncr825_device;
extern struct pci_driver ncr_device;
#endif
#include "de.h"
#include <de.h>
#if NDE > 0
extern struct pci_driver dedevice;
#endif
extern struct pci_driver intel82378_device;
extern struct pci_driver intel82424_device;
extern struct pci_driver intel82375_device;
extern struct pci_driver intel82434_device;
extern struct pci_driver chipset_device;
extern struct pci_driver vga_device;
extern struct pci_driver ign_device;
extern struct pci_driver lkm_device;
struct pci_device pci_devtab[] = {
#if NNCR>0
{&ncr810_device, 0x00011000ul, "ncr", 0},
{&ncr825_device, 0x00031000ul, "ncr", 0},
#else
{0, 0x00011000ul, "ncr", PDF_LOADABLE},
{0, 0x00031000ul, "ncr", PDF_LOADABLE},
{&ncr_device, "ncr", 0 },
#endif
#if NDE>0
{&dedevice, 0x00021011ul, "de", 0}, /* FIXME!!! */
#else
{0, 0x00021011ul, "de", PDF_LOADABLE}, /* FIXME!!! */
{&dedevice, "de", 0 },
#endif
{0, 0x10001042ul, "wd", PDF_COVERED},
{&intel82378_device, 0x04848086, "ichip", 0},
{&intel82424_device, 0x04838086, "ichip", 0},
{&intel82375_device, 0x04828086, "ichip", 0},
{&intel82434_device, 0x04a38086, "ichip", 0},
{0, 0, 0, 0}
{&chipset_device, "chip", 0 },
{&vga_device, "graphics", 0 },
{&ign_device, "ign", 0 },
{&lkm_device, "lkm", 0 },
{0, 0, 0 }
};

View File

@ -1,6 +1,6 @@
/**************************************************************************
**
** $Id: pcibios.c,v 2.1 94/09/16 08:01:26 wolf Rel $
** $Id: pcibios.c,v 2.6 94/10/11 19:01:25 wolf Oct11 $
**
** #define for pci-bus bios functions.
**
@ -32,15 +32,22 @@
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**
**-------------------------------------------------------------------------
***************************************************************************
*/
#include <pci.h>
#if NPCI > 0
#include "types.h"
#include "i386/isa/isa.h"
#include "i386/pci/pci.h"
#include "i386/pci/pcibios.h"
#include "i386/include/cpufunc.h"
#if __FreeBSD__ >= 2
#define HAS_CPUFUNC_H
#endif
#include <types.h>
#include <i386/isa/isa.h>
#include <i386/pci/pcireg.h>
#ifdef HAS_CPUFUNC_H
#include <i386/include/cpufunc.h>
#endif
extern int printf();
@ -54,9 +61,7 @@ static char pci_mode;
**--------------------------------------------------------------------
*/
#undef DIRTY
#ifdef DIRTY
#ifndef HAS_CPUFUNC_H
#undef inl
#define inl(port) \
@ -81,7 +86,7 @@ static char pci_mode;
#define outb(port, data) \
{__asm __volatile("outb %0, %1"::"a" ((u_char)(data)), "d" ((u_short)(port)));}
#endif
#endif /* HAS_CPUFUNC_H */
/*--------------------------------------------------------------------
**
@ -194,7 +199,7 @@ u_long pci_conf_read (pcici_t tag, u_long reg)
switch (pci_mode) {
case 1:
addr = tag.cfg1 | reg & 0xfc;
addr = tag.cfg1 | (reg & 0xfc);
#ifdef PCI_DEBUG
printf ("pci_conf_read(1): addr=%x ", addr);
#endif
@ -204,7 +209,7 @@ u_long pci_conf_read (pcici_t tag, u_long reg)
break;
case 2:
addr = tag.cfg2.port | reg & 0xfc;
addr = tag.cfg2.port | (reg & 0xfc);
#ifdef PCI_DEBUG
printf ("pci_conf_read(2): addr=%x ", addr);
#endif
@ -242,7 +247,7 @@ void pci_conf_write (pcici_t tag, u_long reg, u_long data)
switch (pci_mode) {
case 1:
addr = tag.cfg1 | reg & 0xfc;
addr = tag.cfg1 | (reg & 0xfc);
#ifdef PCI_DEBUG
printf ("pci_conf_write(1): addr=%x data=%x\n",
addr, data);
@ -253,7 +258,7 @@ void pci_conf_write (pcici_t tag, u_long reg, u_long data)
break;
case 2:
addr = tag.cfg2.port | reg & 0xfc;
addr = tag.cfg2.port | (reg & 0xfc);
#ifdef PCI_DEBUG
printf ("pci_conf_write(2): addr=%x data=%x\n",
addr, data);
@ -268,26 +273,4 @@ void pci_conf_write (pcici_t tag, u_long reg, u_long data)
break;
};
}
/*--------------------------------------------------------------------
**
** Get the number of available PCI busses.
**
**--------------------------------------------------------------------
*/
/*
** A certain chipset seems to ignore the bus number.
** Until fixed, check only bus 0.
** Maybe it's a good idea to ask the real pci bios
** if available.
*/
#ifndef PCI_LAST_BUS
#define PCI_LAST_BUS (0)
#endif /* PCI_LAST_BUS */
int pci_last_bus (void)
{
return (PCI_LAST_BUS);
}
#endif /* NPCI > 0 */

View File

@ -101,8 +101,7 @@
#include <pci.h>
#if NPCI > 0
#include <i386/pci/pci.h>
#include <i386/pci/pci_device.h>
#include <i386/pci/pcireg.h>
#endif
#include <i386/isa/icu.h>
#include <i386/pci/dc21040.h>
@ -310,7 +309,7 @@ tulip_init(
int unit)
{
tulip_softc_t *sc = tulips[unit];
unsigned new_cmdmode;
/* XXX unsigned new_cmdmode; */
if (sc->tulip_if.if_flags & IFF_UP) {
sc->tulip_if.if_flags |= IFF_RUNNING;
@ -332,7 +331,7 @@ tulip_init(
sc->tulip_intrmask &= ~TULIP_STS_RXSTOPPED;
tulip_start(&sc->tulip_if);
}
tulip_cmdnode |= TULIP_CMD_THRSHLD160;
sc->tulip_cmdmode |= TULIP_CMD_THRSHLD160;
*sc->tulip_csrs.csr_intr = sc->tulip_intrmask;
*sc->tulip_csrs.csr_command = sc->tulip_cmdmode;
} else {
@ -690,13 +689,12 @@ tulip_start(
static int
tulip_intr(
int unit)
tulip_softc_t *sc)
{
tulip_softc_t *sc = tulips[unit];
tulip_uint32_t csr;
unsigned spins = 0;
tulip_intrs[unit]++;
/* XXX tulip_intrs[unit]++; */
while ((csr = *sc->tulip_csrs.csr_status) & (TULIP_STS_NORMALINTR|TULIP_STS_ABNRMLINTR)) {
*sc->tulip_csrs.csr_status = csr & sc->tulip_intrmask;
@ -706,7 +704,7 @@ tulip_intr(
if ((csr & TULIP_STS_ERRORMASK) == TULIP_STS_ERR_PARITY) {
TULIP_RESET(sc);
tulip_init(sc->tulip_unit);
return unit;
return (1);
}
}
if (csr & TULIP_STS_RXINTR)
@ -723,7 +721,7 @@ tulip_intr(
}
if (spins > sc->tulip_high_intrspins)
sc->tulip_high_intrspins = spins;
return unit;
return (1);
}
/*
@ -777,6 +775,7 @@ tulip_read_macaddr(
return 0;
}
#ifdef MULTICAST
static unsigned
tulip_mchash(
unsigned char *mca)
@ -794,20 +793,24 @@ tulip_mchash(
#endif
return crc & 0x1FF;
}
#endif MULTICAST
static void
tulip_addr_filter(
tulip_softc_t *sc)
{
tulip_uint32_t *sp = sc->tulip_setupdata;
#ifdef MULTICAST
struct ether_multistep step;
struct ether_multi *enm;
#endif
int i;
sc->tulip_flags &= ~TULIP_WANTHASH;
sc->tulip_flags |= TULIP_WANTSETUP;
sc->tulip_cmdmode &= ~TULIP_CMD_RXRUN;
sc->tulip_intrmask &= ~TULIP_STS_RXSTOPPED;
#ifdef MULTICAST
if (sc->tulip_ac.ac_multicnt > 14) {
unsigned hash;
/*
@ -830,10 +833,12 @@ tulip_addr_filter(
sp[41] = ((u_short *) sc->tulip_ac.ac_enaddr)[1];
sp[42] = ((u_short *) sc->tulip_ac.ac_enaddr)[2];
} else {
#endif
/*
* Else can get perfect filtering for 16 addresses.
*/
i = 0;
#ifdef MULTICAST
ETHER_FIRST_MULTI(step, &sc->tulip_ac, enm);
for (; enm != NULL; i++) {
*sp++ = ((u_short *) enm->enm_addrlo)[0];
@ -841,6 +846,7 @@ tulip_addr_filter(
*sp++ = ((u_short *) enm->enm_addrlo)[2];
ETHER_NEXT_MULTI(step, enm);
}
#endif
/*
* If an IP address is enabled, turn on broadcast
*/
@ -858,7 +864,9 @@ tulip_addr_filter(
*sp++ = ((u_short *) sc->tulip_ac.ac_enaddr)[1];
*sp++ = ((u_short *) sc->tulip_ac.ac_enaddr)[2];
}
#ifdef MULTICAST
}
#endif
}
static int
@ -931,6 +939,7 @@ tulip_ioctl(
break;
}
#ifdef MULTICAST
case SIOCADDMULTI:
case SIOCDELMULTI: {
/*
@ -948,6 +957,7 @@ tulip_ioctl(
}
break;
}
#endif /* MULTICAST */
default: {
error = EINVAL;
@ -968,7 +978,9 @@ tulip_attach(
int cnt;
ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS;
#ifdef MULTICAST
ifp->if_flags |= IFF_MULTICAST;
#endif /* MULTICAST */
*sc->tulip_csrs.csr_sia_connectivity = 0;
*sc->tulip_csrs.csr_sia_connectivity = TULIP_SIACONN_10BASET;
@ -1066,18 +1078,14 @@ tulip_initring(
* on both EISA and PCI boards, one must be careful in how defines the
* DC21040 in the config file.
*/
static int tulip_pci_probe(pcici_t config_id);
static int tulip_pci_attach(pcici_t config_id);
static char* tulip_pci_probe (pcici_t config_id, pcidi_t device_id);
static void tulip_pci_attach(pcici_t config_id, int unit);
static u_long tulip_count;
struct pci_driver dedevice = {
tulip_pci_probe,
tulip_pci_attach,
0x00021011ul,
#if __FreeBSD__ == 1
"de",
#endif
"digital dc21040 ethernet",
tulip_intr
&tulip_count,
};
#define PCI_CFID 0x00 /* Configuration ID */
@ -1090,39 +1098,41 @@ struct pci_driver dedevice = {
#define PCI_CFDA 0x40 /* Configuration Driver Area */
#define TULIP_PCI_CSRSIZE (8 / sizeof(tulip_uint32_t))
static int
static char*
tulip_pci_probe(
pcici_t config_id)
pcici_t config_id,
pcidi_t device_id)
{
int idx;
if (device_id != 0x00021011ul)
return (NULL);
for (idx = 0; idx < NDE; idx++)
if (tulips[idx] == NULL)
return idx;
return -1;
return ("digital dc21040 ethernet");
return (NULL);
}
static int
static void
tulip_pci_attach(
pcici_t config_id)
pcici_t config_id,
int unit)
{
tulip_softc_t *sc;
int retval, idx, revinfo, unit;
signed int csr;
int retval, idx /* XXX , revinfo, */;
/* XXX signed int csr; */
vm_offset_t va_csrs, pa_csrs;
int result;
/* XXX int result;*/
tulip_desc_t *rxdescs, *txdescs;
unit = tulip_pci_probe(config_id);
sc = (tulip_softc_t *) malloc(sizeof(*sc), M_DEVBUF, M_NOWAIT);
if (sc == NULL)
return -1;
return;
rxdescs = (tulip_desc_t *)
malloc(sizeof(tulip_desc_t) * TULIP_RXDESCS, M_DEVBUF, M_NOWAIT);
if (rxdescs == NULL) {
free((caddr_t) sc, M_DEVBUF);
return -1;
return;
}
txdescs = (tulip_desc_t *)
@ -1130,7 +1140,7 @@ tulip_pci_attach(
if (txdescs == NULL) {
free((caddr_t) rxdescs, M_DEVBUF);
free((caddr_t) sc, M_DEVBUF);
return -1;
return;
}
bzero(sc, sizeof(sc)); /* Zero out the softc*/
@ -1148,13 +1158,12 @@ tulip_pci_attach(
sc->tulip_unit = unit;
sc->tulip_name = "de";
retval = pci_map_mem(config_id, PCI_CBMA, &va_csrs, &pa_csrs);
if (retval) {
printf("de%d: pci_map_mem failed.\n", unit);
if (!retval) {
kmem_free(kernel_map, sc->tulip_rxspace, TULIP_RXSPACE + NBPG);
free((caddr_t) txdescs, M_DEVBUF);
free((caddr_t) rxdescs, M_DEVBUF);
free((caddr_t) sc, M_DEVBUF);
return -1;
return;
}
tulips[unit] = sc;
tulip_initcsrs(sc, (volatile tulip_uint32_t *) va_csrs, TULIP_PCI_CSRSIZE);
@ -1171,10 +1180,10 @@ tulip_pci_attach(
(sc->tulip_revinfo & 0xF0) >> 4, sc->tulip_revinfo & 0x0F,
"unknown");
} else {
pci_map_int (config_id, tulip_intr, (void*) sc, &net_imask);
TULIP_RESET(sc);
tulip_attach(sc);
}
return 1;
}
#endif /* NPCI > 0 */
#endif /* NDE > 0 */

View File

@ -1,6 +1,6 @@
/**************************************************************************
**
** $Id: ncr.c,v 1.5 1994/09/24 02:42:11 rgrimes Exp $
** $Id: ncr.c,v 2.11 94/10/11 19:03:07 wolf Oct11 $
**
** Device driver for the NCR 53C810 PCI-SCSI-Controller.
**
@ -9,11 +9,11 @@
**-------------------------------------------------------------------------
**
** Written for 386bsd and FreeBSD by
** wolf@dentaro.gun.de Wolfgang Stanglmeier
** se@mi.Uni-Koeln.de Stefan Esser
** Wolfgang Stanglmeier <wolf@dentaro.gun.de>
** Stefan Esser <se@mi.Uni-Koeln.de>
**
** Ported to NetBSD by
** mycroft@gnu.ai.mit.edu
** Charles M. Hannum <mycroft@gnu.ai.mit.edu>
**
**-------------------------------------------------------------------------
**
@ -41,18 +41,11 @@
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**
**-------------------------------------------------------------------------
***************************************************************************
*/
#ifndef __NetBSD__
#ifdef KERNEL
#include <ncr.h>
#else /* KERNEL */
#define NNCR 1
#endif /* KERNEL */
#endif /* !__NetBSD__ */
#define NCR_VERSION (2)
#define MAX_UNITS (16)
/*==========================================================
@ -107,7 +100,7 @@
*/
#ifndef SCSI_NCR_MAX_TAGS
#define SCSI_NCR_MAX_TAGS (8)
#define SCSI_NCR_MAX_TAGS (0)
#endif /* SCSI_NCR_MAX_TAGS */
/*==========================================================
@ -178,6 +171,7 @@
#include <sys/types.h>
#include <sys/param.h>
#include <sys/time.h>
#include <sys/proc.h>
#ifdef KERNEL
#include <sys/systm.h>
@ -190,17 +184,13 @@
#include <vm/vm.h>
#endif /* KERNEL */
#include <i386/pci/ncr_reg.h>
#include <i386/pci/ncrreg.h>
#ifdef __NetBSD__
#include <sys/device.h>
#include <i386/pci/pcivar.h>
#include <i386/pci/pcireg.h>
#else
#include <i386/pci/pci.h>
#include <i386/pci/pcibios.h>
#include <i386/pci/pci_device.h>
#endif
#include <i386/pci/pcireg.h>
#include <scsi/scsi_all.h>
#include <scsi/scsiconf.h>
@ -369,6 +359,7 @@ int ncr_debug = 0;
*/
#define CCB_MAGIC (0xf2691ad2)
#define MAX_TAGS (16) /* hard limit */
/*==========================================================
**
@ -394,6 +385,7 @@ int ncr_debug = 0;
extern void timeout();
extern void untimeout();
#endif /* KERNEL */
#define bio_imask biomask
#define LUN lu
#define TARGET targ
#define PRINT_ADDR(xp) printf ("ncr0: targ %d lun %d ",xp->targ,xp->lu)
@ -946,6 +938,8 @@ struct ncb {
#ifdef __NetBSD__
struct device sc_dev;
struct intrhand sc_ih;
#else
int unit;
#endif
/*-----------------------------------------------
@ -1195,6 +1189,7 @@ static void ncr_getclock (ncb_p np);
static ccb_p ncr_get_ccb (ncb_p np, u_long flags, u_long t,u_long l);
static U_INT32 ncr_info (int unit);
static void ncr_init (ncb_p np, char * msg, u_long code);
static int ncr_intr (ncb_p np);
static void ncr_int_ma (ncb_p np);
static void ncr_int_sir (ncb_p np);
static void ncr_int_sto (ncb_p np);
@ -1223,11 +1218,9 @@ static void ncr_wakeup (ncb_p np, u_long code);
#ifdef __NetBSD__
static int ncr_probe (struct device *, struct device *, void *);
static void ncr_attach (struct device *, struct device *, void *);
static int ncr_intr (ncb_p np);
#else
static int ncr_probe (pcici_t config_id);
static int ncr_attach (pcici_t config_id);
static int ncr_intr (int dev);
static char* ncr_probe (pcici_t tag, pcidi_t type);
static void ncr_attach (pcici_t tag, int unit);
#endif
/*==========================================================
@ -1241,9 +1234,8 @@ static int ncr_intr (int dev);
#ifdef DIRTY
#include <i386/include/cpufunc.h>
#ifdef __NetBSD__
#include <i386/include/cpufunc.h>
#include <i386/include/pio.h>
#include <i386/isa/isareg.h>
#define DELAY(x) delay(x)
@ -1326,7 +1318,7 @@ static u_long getirr (void)
static char ident[] =
"\n$Id: ncr.c,v 1.4 1994/09/16 13:33:56 davidg Exp $\n";
"\n$Id: ncr.c,v 2.11 94/10/11 19:03:07 wolf Oct11 $\n";
u_long ncr_version = NCR_VERSION
+ (u_long) sizeof (struct ncb)
@ -1337,9 +1329,8 @@ u_long ncr_version = NCR_VERSION
#ifdef KERNEL
#ifndef __NetBSD__
u_long ncr_units;
u_long nncr=NNCR;
ncb_p ncrp [NNCR];
u_long nncr=MAX_UNITS;
ncb_p ncrp [MAX_UNITS];
#endif
int ncr_cache; /* may _NOT_ be static */
@ -1371,20 +1362,12 @@ struct cfdriver ncrcd = {
#else /* !__NetBSD__ */
struct pci_driver ncr810_device = {
ncr_probe,
ncr_attach,
NCR_810_ID,
"ncr 53c810 scsi",
ncr_intr
};
static u_long ncr_count;
struct pci_driver ncr825_device = {
struct pci_driver ncr_device = {
ncr_probe,
ncr_attach,
NCR_825_ID,
"ncr 53c825 scsi",
ncr_intr
&ncr_count
};
#endif /* !__NetBSD__ */
@ -1429,14 +1412,8 @@ struct scsi_switch ncr_switch =
static char *ncr_name (ncb_p np)
{
static char name[10];
int idx;
for (idx = 0; idx < NNCR; idx++)
if (ncrp[idx] == np) {
sprintf(name, "ncr%d", idx);
return (name);
}
return ("ncr?");
sprintf(name, "ncr%d", np->unit);
return (name);
}
#endif
@ -3092,7 +3069,7 @@ static void ncr_script_copy_and_bind (struct script *script, ncb_p np)
#ifdef SCSI_NCR_DEBUG
if (ncr_debug & DEBUG_SCRIPT)
printf ("%x: <%x>\n",
(u_long)(src-1), opcode);
(unsigned)(src-1), (unsigned)opcode);
#endif /* SCSI_NCR_DEBUG */
/*
@ -3245,13 +3222,22 @@ ncr_probe(parent, self, aux)
#else /* !__NetBSD__ */
static int ncr_probe(pcici_t config_id)
static char* ncr_probe (pcici_t tag, pcidi_t type)
{
if (ncr_units >= NNCR) return (-1);
return (ncr_units);
switch (type) {
case NCR_810_ID:
return ("ncr 53c810 scsi");
case NCR_825_ID:
return ("ncr 53c825 wide scsi");
}
return (0);
}
#endif /* !__NetBSD__ */
/*==========================================================
**
@ -3307,39 +3293,36 @@ ncr_attach(parent, self, aux)
#else /* !__NetBSD__ */
static int ncr_attach (pcici_t config_id)
static void ncr_attach (pcici_t config_id, int unit)
{
int retval;
ncb_p np = ncrp[ncr_units];
ncb_p np;
#if ! (__FreeBSD__ >= 2)
extern unsigned bio_imask;
#endif
/*
** allocate structure
*/
if (!np) {
np = (ncb_p) malloc (sizeof (struct ncb),
M_DEVBUF, M_NOWAIT);
if (!np) return (0);
ncrp[ncr_units]=np;
}
np = (ncb_p) malloc (sizeof (struct ncb), M_DEVBUF, M_WAITOK);
if (!np) return;
ncrp[unit]=np;
/*
** initialize structure.
*/
bzero (np, sizeof (*np));
np->unit = unit;
/*
** Try to map the controller chip to
** virtual and physical memory.
*/
retval = pci_map_mem (config_id, 0x14, &np->vaddr, &np->paddr);
if (retval) {
printf ("%s: pci_map_mem failed.\n", ncr_name (np));
return (retval);
};
if (!pci_map_mem (config_id, 0x14, &np->vaddr, &np->paddr))
return;
#endif /* !__NetBSD__ */
@ -3409,9 +3392,18 @@ static int ncr_attach (pcici_t config_id)
if (ncr_snooptest (np)) {
printf ("CACHE INCORRECTLY CONFIGURED.\n");
return (0);
return;
};
#ifndef __NetBSD__
/*
** Install the interrupt handler.
*/
if (!pci_map_int (config_id, ncr_intr, np, &bio_imask))
printf ("\tinterruptless mode: reduced performance.\n");
#endif
/*
** After SCSI devices have been opened, we cannot
** reset the bus safely, so we do it here.
@ -3431,7 +3423,7 @@ static int ncr_attach (pcici_t config_id)
ncr_name (np));
DELAY (1000000);
#endif
printf ("%s scanning for targets 0..%d ($Revision: 1.5 $)\n",
printf ("%s scanning for targets 0..%d ($Revision: 2.11 $)\n",
ncr_name (np), MAX_TARGET-1);
/*
@ -3443,7 +3435,7 @@ static int ncr_attach (pcici_t config_id)
#ifdef __NetBSD__
np->sc_link.adapter_softc = np;
#else /* !__NetBSD__ */
np->sc_link.adapter_unit = ncr_units;
np->sc_link.adapter_unit = unit;
#endif /* !__NetBSD__ */
np->sc_link.adapter_targ = np->myaddr;
np->sc_link.adapter = &ncr_switch;
@ -3455,7 +3447,7 @@ static int ncr_attach (pcici_t config_id)
scsi_attachdevs (&np->sc_link);
#endif /* !__NetBSD__ */
#else /* ANCIENT */
scsi_attachdevs (ncr_units, np->myaddr, &ncr_switch);
scsi_attachdevs (unit, np->myaddr, &ncr_switch);
#endif /* ANCIENT */
/*
@ -3468,10 +3460,7 @@ static int ncr_attach (pcici_t config_id)
** Done.
*/
#ifndef __NetBSD__
ncr_units++;
return(1);
#endif
return;
}
/*==========================================================
@ -3483,46 +3472,27 @@ static int ncr_attach (pcici_t config_id)
**==========================================================
*/
#ifdef __NetBSD__
int
ncr_intr(np)
ncb_p np;
{
int n = 0;
#else /* !__NetBSD__ */
static int ncr_intr (int dev)
{
ncb_p np;
int n=0;
/*
** Sanity check
*/
assert (dev<NNCR);
if (dev >= ncr_units) return (0);
np = ncrp[dev];
#endif /* !__NetBSD__ */
#ifdef SCSI_NCR_DEBUG
if (ncr_debug & DEBUG_TINY) printf ("[");
#endif /* SCSI_NCR_DEBUG */
/*
** Repeat until no outstanding ints
*/
while (INB(nc_istat) & (INTF|SIP|DIP)) {
ncr_exception (np);
n=1;
};
if (INB(nc_istat) & (INTF|SIP|DIP)) {
/*
** Repeat until no outstanding ints
*/
do {
ncr_exception (np);
} while (INB(nc_istat) & (INTF|SIP|DIP));
/*
** Slowdown timeout function.
*/
if (n) np->ticks = 100;
n=1;
np->ticks = 100;
};
#ifdef SCSI_NCR_DEBUG
if (ncr_debug & DEBUG_TINY) printf ("]\n");
@ -3637,7 +3607,7 @@ static INT32 ncr_start (struct scsi_xfer * xp)
if (ncr_debug & DEBUG_TINY) {
PRINT_ADDR(xp);
printf ("CMD=%x F=%x L=%x ", cmd->opcode,
xp->flags, xp->datalen);
(unsigned)xp->flags, (unsigned) xp->datalen);
}
#endif /* SCSI_NCR_DEBUG */
@ -3765,8 +3735,12 @@ static INT32 ncr_start (struct scsi_xfer * xp)
cp2 = cp2->next_ccb;
if (cp2) continue;
cp->tag=lp->lasttag;
PRINT_ADDR(xp);
printf ("using tag #%d.\n", cp->tag);
#ifdef SCSI_NCR_DEBUG
if (ncr_debug & DEBUG_TAGS) {
PRINT_ADDR(xp);
printf ("using tag #%d.\n", cp->tag);
};
#endif /* SCSI_NCR_DEBUG */
};
} else {
cp->tag=0;
@ -3813,7 +3787,7 @@ static INT32 ncr_start (struct scsi_xfer * xp)
}
/*
** can be overwritten by ncrstat
** can be overwritten by ncrcontrol
*/
switch (np->order) {
case M_SIMPLE_TAG:
@ -3991,7 +3965,9 @@ static INT32 ncr_start (struct scsi_xfer * xp)
#ifdef SCSI_NCR_DEBUG
if(ncr_debug & DEBUG_QUEUE)
printf ("%s: queuepos=%d tryoffset=%d.\n", ncr_name (np),
np->squeueput, np->script->startpos[0]-(vtophys(&np->script->tryloop)));
np->squeueput,
(unsigned)(np->script->startpos[0]-
(vtophys(&np->script->tryloop))));
#endif /* SCSI_NCR_DEBUG */
/*
@ -4049,7 +4025,7 @@ static INT32 ncr_start (struct scsi_xfer * xp)
if (!(xp->flags & ITSDONE)) {
printf ("%s: abortion failed at %x.\n",
ncr_name (np), INL(nc_dsp));
ncr_name (np), (unsigned) INL(nc_dsp));
ncr_init (np, "timeout", HS_TIMEOUT);
};
@ -4114,7 +4090,7 @@ void ncr_complete (ncb_p np, ccb_p cp)
#ifdef SCSI_NCR_DEBUG
if (ncr_debug & DEBUG_TINY)
printf ("CCB=%x STAT=%x/%x\n", (u_long)cp & 0xfff,
printf ("CCB=%x STAT=%x/%x\n", (unsigned)cp & 0xfff,
cp->host_status,cp->scsi_status);
#endif /* SCSI_NCR_DEBUG */
@ -4279,7 +4255,7 @@ void ncr_complete (ncb_p np, ccb_p cp)
*/
PRINT_ADDR(xp);
printf ("COMMAND FAILED (%x %x) @%x.\n",
cp->host_status, cp->scsi_status, cp);
cp->host_status, cp->scsi_status, (unsigned)cp);
xp->error = XS_DRIVER_STUFFUP;
}
@ -4361,6 +4337,8 @@ void ncr_wakeup (ncb_p np, u_long code)
** complete all jobs that are not IDLE.
*/
int s=splbio();
ccb_p cp = &np->ccb;
while (cp) {
switch (cp->host_status) {
@ -4387,6 +4365,7 @@ void ncr_wakeup (ncb_p np, u_long code)
};
cp = cp -> link_ccb;
};
splx (s);
}
/*==========================================================
@ -4758,7 +4737,7 @@ static void ncr_usercmd (ncb_p np)
break;
case UC_SETTAGS:
if (np->user.data > SCSI_NCR_MAX_TAGS)
if (np->user.data > MAX_TAGS)
break;
for (t=0; t<MAX_TARGET; t++) {
if (!((np->user.target>>t)&1)) continue;
@ -4895,7 +4874,7 @@ static void ncr_timeout (ncb_p np)
if (cp->phys.header.launch.l_paddr ==
vtophys (&np->script->select)) {
printf ("%s: timeout ccb=%x (skip)\n",
ncr_name (np), cp);
ncr_name (np), (unsigned)cp);
cp->phys.header.launch.l_paddr
= vtophys (&np->script->skip);
};
@ -4967,10 +4946,10 @@ static void ncr_timeout (ncb_p np)
*/
if (np->mcount == 100) {
if (np->imask & (np->imask-1)) {
printf ("%s: please configure intr mask %x.\n",
printf ("%s: uses one of the irq in %x.\n",
ncr_name (np), np->imask);
} else {
printf ("%s: please configure intr %d.\n",
printf ("%s: please configure irq %d.\n",
ncr_name (np), ffs (np->imask)-1);
};
np->mcount++;
@ -5022,7 +5001,8 @@ void ncr_exception (ncb_p np)
printf ("<%d|%x:%x|%x:%x>",
INB(nc_scr0),
dstat,sist,
INL(nc_dsp),INL(nc_dbc));
(unsigned)INL(nc_dsp),
(unsigned)INL(nc_dbc));
#endif /* SCSI_NCR_DEBUG */
if ((dstat==DFE) && (sist==PAR)) return;
@ -5117,7 +5097,8 @@ void ncr_exception (ncb_p np)
ncr_name (np), INB (nc_ctest0)&7, dstat, sist,
INB (nc_sbcl),
INB (nc_sxfer),INB (nc_scntl3),
dsp = INL (nc_dsp), INL (nc_dbc));
(unsigned) (dsp = INL (nc_dsp)),
(unsigned) INL (nc_dbc));
/*----------------------------------------
** clean up the dma fifo
@ -5243,7 +5224,7 @@ void ncr_exception (ncb_p np)
**==========================================================
**
** There seems to be a bug in the 53c810.
** Although a STO-Interupt is pending,
** Although a STO-interrupt is pending,
** it continues executing script commands.
** But it will fail and interrupt (IID) on
** the next instruction where it's looking
@ -5381,11 +5362,14 @@ static void ncr_int_ma (ncb_p np)
*/
if (ncr_debug & (DEBUG_TINY|DEBUG_PHASE)) {
printf ("P%d%d ",cmd&7, sbcl&7);
printf ("RL=%d D=%d SS0=%x ",rest,delta,ss0);
printf ("RL=%d D=%d SS0=%x ",
(unsigned) rest, (unsigned) delta, ss0);
};
if (ncr_debug & DEBUG_PHASE) {
printf ("\nCP=%x CP2=%x DSP=%x NXT=%x VDSP=%x CMD=%x ",
cp, np->header.cp, dsp, nxtdsp, vdsp, cmd);
(unsigned)cp, (unsigned)np->header.cp,
(unsigned)dsp,
(unsigned)nxtdsp, (unsigned)vdsp, cmd);
};
#endif /* SCSI_NCR_DEBUG */
@ -5407,7 +5391,10 @@ static void ncr_int_ma (ncb_p np)
#ifdef SCSI_NCR_DEBUG
if (ncr_debug & DEBUG_PHASE) {
printf ("OCMD=%x\nTBLP=%x OLEN=%x OADR=%x\n",
vdsp[0] >> 24, tblp, olen, oadr);
(unsigned) (vdsp[0] >> 24),
(unsigned) tblp,
(unsigned) olen,
(unsigned) oadr);
};
#endif /* SCSI_NCR_DEBUG */
@ -5419,7 +5406,8 @@ static void ncr_int_ma (ncb_p np)
if (cmd & 0x06) {
PRINT_ADDR(cp->xfer);
printf ("phase change %d-%d %d@%x resid=%d.\n",
cmd&7, sbcl&7, olen, oadr, rest);
cmd&7, sbcl&7, (unsigned)olen,
(unsigned)oadr, (unsigned)rest);
OUTB (nc_dcntl, (STD|NOCOM));
return;
@ -5447,7 +5435,10 @@ static void ncr_int_ma (ncb_p np)
PRINT_ADDR(cp->xfer);
printf ("newcmd[%d] %x %x %x %x.\n",
newcmd - cp->patch,
newcmd[0], newcmd[1], newcmd[2], newcmd[3]);
(unsigned)newcmd[0],
(unsigned)newcmd[1],
(unsigned)newcmd[2],
(unsigned)newcmd[3]);
}
#endif /* SCSI_NCR_DEBUG */
/*
@ -5941,7 +5932,7 @@ void ncr_int_sir (ncb_p np)
PRINT_ADDR(cp->xfer);
printf ("M_REJECT received (%x:%x).\n",
np->lastmsg, np->msgout[0]);
(unsigned)np->lastmsg, np->msgout[0]);
break;
case SIR_REJECT_SENT:
@ -5989,10 +5980,10 @@ void ncr_int_sir (ncb_p np)
PRINT_ADDR(cp->xfer);
printf ("M_DISCONNECT received, but datapointer not saved:\n"
" data=%x save=%x goal=%x.\n",
INL (nc_temp),
np->header.savep,
np->header.goalp);
"\tdata=%x save=%x goal=%x.\n",
(unsigned) INL (nc_temp),
(unsigned) np->header.savep,
(unsigned) np->header.goalp);
break;
/*--------------------------------------------------------------------
@ -6047,7 +6038,6 @@ void ncr_int_sir (ncb_p np)
**
**-----------------------------------------------
*/
/*
** Look for a disconnected job.
*/
@ -6209,6 +6199,8 @@ static void ncr_alloc_ccb (ncb_p np, struct scsi_xfer * xp)
tp->jump_lcb.l_cmd = (SCR_JUMP);
tp->jump_lcb.l_paddr = vtophys (&np->script->abort);
np->jump_tcb.l_paddr = vtophys (&tp->jump_tcb);
ncr_setmaxtags (tp, SCSI_NCR_MAX_TAGS);
}
/*
@ -6267,7 +6259,7 @@ static void ncr_alloc_ccb (ncb_p np, struct scsi_xfer * xp)
#ifdef SCSI_NCR_DEBUG
if (ncr_debug & DEBUG_ALLOC) {
PRINT_ADDR(xp);
printf ("new ccb @%x.\n", cp);
printf ("new ccb @%x.\n", (unsigned) cp);
}
#endif /* SCSI_NCR_DEBUG */
@ -6414,7 +6406,7 @@ static int ncr_scatter
#ifdef SCSI_NCR_DEBUG
if(ncr_debug & DEBUG_SCATTER)
printf("ncr?:\tscattering virtual=0x%x size=%d chunk=%d.\n",
(u_long) vaddr, (u_long) datalen, chunk);
(unsigned) vaddr, (unsigned) datalen, (unsigned) chunk);
#endif /* SCSI_NCR_DEBUG */
/*
@ -6456,7 +6448,10 @@ static int ncr_scatter
#ifdef SCSI_NCR_DEBUG
if(ncr_debug & DEBUG_SCATTER)
printf ("\tseg #%d addr=%x size=%d (rest=%d).\n",
segment, segaddr, segsize, datalen);
segment,
(unsigned) segaddr,
(unsigned) segsize,
(unsigned) datalen);
#endif /* SCSI_NCR_DEBUG */
phys->data[segment].addr = segaddr;
@ -6466,7 +6461,7 @@ static int ncr_scatter
if (datalen) {
printf("ncr?: scatter/gather failed (residue=%d).\n",
datalen);
(unsigned) datalen);
return (-1);
};
@ -6478,7 +6473,7 @@ static int ncr_scatter
**
** Test the pci bus snoop logic :-(
**
** Has to be called with disabled interupts.
** Has to be called with interrupts disabled.
**
**
**==========================================================
@ -6522,17 +6517,17 @@ static int ncr_snooptest (struct ncb* np)
*/
if (host_wr != ncr_rd) {
printf ("CACHE TEST FAILED: host wrote %d, ncr read %d.\n",
host_wr, ncr_rd);
(int) host_wr, (int) ncr_rd);
err |= 1;
};
if (host_rd != ncr_wr) {
printf ("CACHE TEST FAILED: ncr wrote %d, host read %d.\n",
ncr_wr, host_rd);
(int) ncr_wr, (int) host_rd);
err |= 2;
};
if (ncr_bk != ncr_wr) {
printf ("CACHE TEST FAILED: ncr wrote %d, read back %d.\n",
ncr_wr, ncr_bk);
(int) ncr_wr, (int) ncr_bk);
err |= 4;
};
return (err);
@ -6627,6 +6622,7 @@ static struct table_entry device_tab[] =
{
{"WangDAT", "Model 2600", "01.7", QUIRK_NOMSG},
{"WangDAT", "Model 3200", "02.2", QUIRK_NOMSG},
{"WangDAT", "Model 1300", "02.4", QUIRK_NOMSG},
{"", "", "", 0} /* catch all: must be last entry. */
};
@ -6639,17 +6635,17 @@ static u_long ncr_lookup(char * id)
d = id+8;
r = p->manufacturer;
while (c=*r++) if (c!=*d++) break;
while ((c=*r++)) if (c!=*d++) break;
if (c) continue;
d = id+16;
r = p->model;
while (c=*r++) if (c!=*d++) break;
while ((c=*r++)) if (c!=*d++) break;
if (c) continue;
d = id+32;
r = p->version;
while (c=*r++) if (c!=*d++) break;
while ((c=*r++)) if (c!=*d++) break;
if (c) continue;
return (p->info);
@ -6712,3 +6708,5 @@ static void ncr_getclock (ncb_p np)
/*=========================================================================*/
#endif /* KERNEL */

View File

@ -1,6 +1,6 @@
/**************************************************************************
**
** $Id: pci.c,v 1.5 1994/09/28 16:34:07 se Exp $
** $Id: pci.c,v 2.12 94/10/11 22:20:37 wolf Oct11 $
**
** General subroutines for the PCI bus on 80*86 systems.
** pci_configure ()
@ -33,27 +33,17 @@
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**
**-------------------------------------------------------------------------
***************************************************************************
*/
#include <pci.h>
#if NPCI > 0
/*========================================================
**
** Configuration
**
**========================================================
*/
/*
** maximum number of devices which share one interrupt line
*/
#ifndef PCI_MAX_DPI
#define PCI_MAX_DPI (4)
#endif /*PCI_MAX_DPI*/
#ifndef __FreeBSD2__
#if __FreeBSD__ >= 2
#define __FreeBSD2__
#endif
#endif
/*========================================================
**
@ -64,101 +54,54 @@
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/malloc.h>
#include <sys/errno.h>
#include <vm/vm.h>
#include <vm/vm_param.h>
#include <i386/isa/icu.h>
#include <i386/isa/isa.h>
#include <i386/isa/isa_device.h>
#include <i386/pci/pci.h>
#include <i386/pci/pci_device.h>
#include <i386/pci/pcibios.h>
#include <i386/isa/icu.h>
#include <i386/pci/pcireg.h>
/*
** Function prototypes missing in system headers
*/
#if ! (__FreeBSD__ >= 2)
#ifndef __FreeBSD2__
extern pmap_t pmap_kernel(void);
static vm_offset_t pmap_mapdev (vm_offset_t paddr, vm_size_t vsize);
#endif
/*========================================================
**
** Autoconfiguration (of isa bus)
**
**========================================================
*/
/*
** per slot data structure for passing interupts..
*/
static struct {
u_short number;
u_short isanum;
struct {
int (*proc)(int dev);
dev_t unit;
} vector[PCI_MAX_DPI];
} pcidata [NPCI];
* Type of the first (asm) part of an interrupt handler.
*/
typedef void inthand_t __P((u_int cs, u_int ef, u_int esp, u_int ss));
/*
** check device ready
*/
static int pciprobe (struct isa_device *dev)
{
if (dev->id_unit >= NPCI)
return (0);
if (!pci_conf_mode())
return (0);
return (-1);
}
* Usual type of the second (C) part of an interrupt handler. Some bogus
* ones need the arg to be the interrupt frame (and not a copy of it, which
* is all that is possible in C).
*/
typedef void inthand2_t __P((int unit));
/*
** initialize the driver structure
*/
static int pciattach (struct isa_device *isdp)
{
pcidata[isdp->id_unit].number = 0;
pcidata[isdp->id_unit].isanum = ffs(isdp->id_irq)-1;
return (1);
}
/*
** ISA driver structure
*/
struct isa_driver pcidriver = {
pciprobe,
pciattach,
"pci"
};
/*========================================================
** XXX @FreeBSD2@
**
** Interrupt forward from isa to pci devices.
**
**========================================================
** Unfortunately, the mptr argument is _no_ pointer in 2.0 FreeBSD.
** We would prefer a pointer because it enables us to install
** new interrupt handlers at any time.
** In 2.0 FreeBSD later installed interrupt handlers may change
** the xyz_imask, but this would not be recognized by handlers
** which are installed before.
*/
static int
register_intr __P((int intr, int device_id, unsigned int flags,
inthand2_t *handler, unsigned int * mptr, int unit));
extern unsigned intr_mask[ICU_LEN];
void pciintr (int unit)
{
u_short i;
if (unit >= NPCI) return;
for (i=0; i<pcidata[unit].number; i++) {
(void)(*pcidata[unit].vector[i].proc)
(pcidata[unit].vector[i].unit);
};
}
#endif /* !__FreeBSD2__ */
/*========================================================
**
@ -183,52 +126,82 @@ void pciintr (int unit)
#define PCI_PMEM_START 0xc0000000
#endif
static vm_offset_t pci_paddr = PCI_PMEM_START;
static vm_offset_t pci_paddr = PCI_PMEM_START;
/*--------------------------------------------------------
**
** The pci device interrupt lines should have been
** assigned by the bios. But if the bios failed to
** to it, we set it.
**
**--------------------------------------------------------
*/
#ifndef PCI_IRQ
#define PCI_IRQ 0
#endif
static u_long pci_irq = PCI_IRQ;
/*---------------------------------------------------------
**
** pci_configure ()
**
** Probe all devices on pci bus and attach them.
**
** May be called more than once.
** Any device is attached only once.
** (Attached devices are remembered in pci_seen.)
**
**---------------------------------------------------------
*/
static void not_supported (pcici_t tag, u_long type);
static unsigned long pci_seen[NPCI];
static int pci_conf_count;
void pci_configure()
{
u_char device,last_device;
u_short bus,last_bus;
u_short bus;
pcici_t tag;
pcidi_t type;
u_long data;
int unit;
int intpin;
int isanum;
int pci_mode;
int pci_mechanism;
int pciint;
int irq;
char* name=0;
int newdev=0;
struct pci_driver *drp;
struct pci_driver *drp=0;
struct pci_device *dvp;
/*
** check pci bus present
*/
pci_mode = pci_conf_mode ();
if (!pci_mode) return;
last_bus = pci_last_bus ();
last_device = pci_mode==1 ? 31 : 15;
pci_mechanism = pci_conf_mode ();
if (!pci_mechanism) return;
last_device = pci_mechanism==1 ? 31 : 15;
/*
** hello world ..
*/
for (bus=0;bus<NPCI;bus++) {
#ifndef PCI_QUIET
printf ("pci*: mode=%d, scanning bus 0..%d, device 0..%d.\n",
pci_mode, last_bus, last_device);
printf ("pci%d: scanning device 0..%d, mechanism=%d.\n",
bus, last_device, pci_mechanism);
#endif
for (bus=0;bus<=last_bus; bus++)
for (device=0; device<=last_device; device ++) {
if (pci_seen[bus] & (1ul << device))
continue;
tag = pcitag (bus, device, 0);
type = pci_conf_read (tag, PCI_ID_REG);
@ -238,137 +211,90 @@ void pci_configure()
** lookup device in ioconfiguration:
*/
for (dvp = pci_devtab; dvp->pd_device_id; dvp++) {
if (dvp->pd_device_id == type) break;
};
drp = dvp->pd_driver;
if (!dvp->pd_device_id) {
/*
** not found
** try to dig out some information.
**
** By Garrett Wollman
** <wollman@halloran-eldar.lcs.mit.edu>
*/
int data = pci_conf_read(tag, PCI_CLASS_REG);
vm_offset_t va;
vm_offset_t pa;
int reg;
switch (data & PCI_CLASS_MASK) {
case PCI_CLASS_PREHISTORIC:
if ((data & PCI_SUBCLASS_MASK)
!= PCI_SUBCLASS_PREHISTORIC_VGA)
break;
case PCI_CLASS_DISPLAY:
for (reg = PCI_MAP_REG_START;
reg < PCI_MAP_REG_END;
reg += 4) {
data = pci_map_mem(tag, reg, &va, &pa);
if (data == 0)
printf (
"pci%d:%d: mapped VGA-like device at physaddr 0x%lx\n",
bus, device, (u_long)pa);
}
for (dvp = pci_devtab; dvp->pd_name; dvp++) {
drp = dvp->pd_driver;
if (!drp)
continue;
};
if ((name=(*drp->probe)(tag, type)))
break;
};
if (!dvp->pd_name) {
#ifndef PCI_QUIET
if (pci_conf_count)
continue;
printf("pci%d:%d: ", bus, device);
not_supported (tag, type);
#endif
};
if (!drp) {
if(dvp->pd_flags & PDF_LOADABLE) {
printf("%s: loadable device on pci%d:%d\n",
dvp->pd_name, bus, device);
}
continue;
}
};
pci_seen[bus] |= (1ul << device);
/*
** found it.
** probe returns the device unit.
** Get and increment the unit.
*/
unit = (*drp->probe) (tag);
unit = (*drp->count)++;
if (unit<0) {
printf ("%s <%s>: probe failed on pci%d:%d\n",
dvp->pd_name, drp->name, bus, device);
continue;
};
/*
** ignore device ?
*/
printf ("%s%d <%s>", dvp->pd_name, unit, drp->name);
if (!*name) continue;
/*
** Announce this device
*/
newdev++;
printf ("%s%d <%s>", dvp->pd_name, unit, name);
/*
** install interrupts
** Get the int pin number (pci interrupt number a-d)
** from the pci configuration space.
*/
data = pci_conf_read (tag, PCI_INTERRUPT_REG);
intpin = PCI_INTERRUPT_PIN_EXTRACT(data);
if (intpin) {
int idx=NPCI;
pciint = PCI_INTERRUPT_PIN_EXTRACT(data);
if (pciint) {
printf (" int %c", 0x60+pciint);
/*
** Usage of int line register (if set by bios)
** Matt Thomas <thomas@lkg.dec.com>
** If the interrupt line register is not set,
** set it now from PCI_IRQ.
*/
isanum = PCI_INTERRUPT_LINE_EXTRACT(data);
if (isanum) {
if (!(PCI_INTERRUPT_LINE_EXTRACT(data))) {
/*
** @INT@ FIXME!!!
**
** Should try to use "register_interupt"
** at this point.
*/
irq = pci_irq & 0x0f;
pci_irq >>= 4;
printf (" line=%d", isanum);
for (idx = 0; idx < NPCI; idx++) {
if (pcidata[idx].isanum == isanum)
break;
};
data = PCI_INTERRUPT_LINE_INSERT(data, irq);
printf (" (config)");
pci_conf_write (tag, PCI_INTERRUPT_REG, data);
};
/*
** Or take the device number as index ...
*/
if (idx >= NPCI) idx = device;
irq = PCI_INTERRUPT_LINE_EXTRACT(data);
/*
** And install the interrupt.
** If it's zero, the isa irq number is unknown,
** and we cannot bind the pci interrupt to isa.
*/
if (idx<NPCI) {
u_short entry = pcidata[idx].number;
printf (" irq %c", 0x60+intpin);
if (entry < PCI_MAX_DPI) {
pcidata[idx].vector[entry].proc = drp->intr;
pcidata[idx].vector[entry].unit = unit;
entry++;
};
printf (" isa=%d [%d]",pcidata[idx].isanum, entry);
pcidata[idx].number=entry;
} else {
printf (" no int");
};
if (irq)
printf (" irq %d", irq);
else
printf (" not bound");
};
/*
** enable memory access
*/
data = pci_conf_read (tag, PCI_COMMAND_STATUS_REG)
& 0xffff | PCI_COMMAND_MEM_ENABLE;
data = (pci_conf_read (tag, PCI_COMMAND_STATUS_REG)
& 0xffff) | PCI_COMMAND_MEM_ENABLE;
pci_conf_write (tag, (u_char) PCI_COMMAND_STATUS_REG, data);
@ -380,13 +306,16 @@ void pci_configure()
printf (" on pci%d:%d\n", bus, device);
(void) (*drp->attach) (tag);
}
(*drp->attach) (tag, unit);
};
};
#ifndef PCI_QUIET
printf ("pci uses physical addresses from 0x%lx to 0x%lx\n",
if (newdev)
printf ("pci uses physical addresses from 0x%lx to 0x%lx\n",
(u_long)PCI_PMEM_START, (u_long)pci_paddr);
#endif
pci_conf_count++;
}
/*-----------------------------------------------------------------------
@ -403,7 +332,8 @@ int pci_map_port (pcici_t tag, u_long reg, u_short* pa)
/*
** @MAPIO@ not yet implemented.
*/
return (ENOSYS);
printf ("pci_map_port failed: not yet implemented\n");
return (0);
}
/*-----------------------------------------------------------------------
@ -425,8 +355,11 @@ int pci_map_mem (pcici_t tag, u_long reg, vm_offset_t* va, vm_offset_t* pa)
** sanity check
*/
if (reg <= PCI_MAP_REG_START || reg >= PCI_MAP_REG_END || (reg & 3))
return (EINVAL);
if (reg < PCI_MAP_REG_START || reg >= PCI_MAP_REG_END || (reg & 3)) {
printf ("pci_map_mem failed: bad register=0x%x\n",
(unsigned)reg);
return (0);
};
/*
** get size and type of memory
@ -445,7 +378,9 @@ int pci_map_mem (pcici_t tag, u_long reg, vm_offset_t* va, vm_offset_t* pa)
break;
default: /* unknown */
return (EINVAL);
printf ("pci_map_mem failed: bad memory type=0x%x\n",
(unsigned) data);
return (0);
};
/*
@ -455,18 +390,19 @@ int pci_map_mem (pcici_t tag, u_long reg, vm_offset_t* va, vm_offset_t* pa)
vsize = round_page (-(data & PCI_MAP_MEMORY_ADDRESS_MASK));
if (!vsize) return (EINVAL);
if (!vsize) return (0);
/*
** align physical address to virtual size
*/
if (data = pci_paddr % vsize)
if ((data = pci_paddr % vsize))
pci_paddr += vsize - data;
vaddr = pmap_mapdev (pci_paddr, vsize);
vaddr = (vm_offset_t) pmap_mapdev (pci_paddr, vsize);
if (!vaddr) return (EINVAL);
if (!vaddr) return (0);
#ifndef PCI_QUIET
/*
@ -474,7 +410,7 @@ int pci_map_mem (pcici_t tag, u_long reg, vm_offset_t* va, vm_offset_t* pa)
*/
printf ("\treg%d: virtual=0x%lx physical=0x%lx\n",
reg, (u_long)vaddr, (u_long)pci_paddr);
(unsigned) reg, (u_long)vaddr, (u_long)pci_paddr);
#endif
/*
@ -496,50 +432,77 @@ int pci_map_mem (pcici_t tag, u_long reg, vm_offset_t* va, vm_offset_t* pa)
pci_paddr += vsize;
return (0);
return (1);
}
/*-----------------------------------------------------------
/*-----------------------------------------------------------------------
**
** Mapping of physical to virtual memory
** Map pci interrupts to isa interrupts.
**
**-----------------------------------------------------------
**-----------------------------------------------------------------------
*/
#if ! (__FreeBSD__ >= 2)
static unsigned int pci_int_mask [16];
extern vm_map_t kernel_map;
static vm_offset_t pmap_mapdev (vm_offset_t paddr, vm_size_t vsize)
int pci_map_int (pcici_t tag, int(*func)(), void* arg, unsigned* maskptr)
{
vm_offset_t vaddr,value;
u_long result;
int irq;
unsigned mask;
vaddr = vm_map_min (kernel_map);
irq = PCI_INTERRUPT_LINE_EXTRACT(
pci_conf_read (tag, PCI_INTERRUPT_REG));
result = vm_map_find (kernel_map, (void*)0, (vm_offset_t) 0,
&vaddr, vsize, TRUE);
if (result != KERN_SUCCESS) {
printf (" vm_map_find failed(%d)\n", result);
if (irq >= 16 || irq <= 0) {
printf ("pci_map_int failed: no int line set.\n");
return (0);
};
}
/*
** map physical
*/
mask = 1ul << irq;
value = vaddr;
while (vsize >= NBPG) {
pmap_enter (pmap_kernel(), vaddr, paddr,
VM_PROT_READ|VM_PROT_WRITE, TRUE);
vaddr += NBPG;
paddr += NBPG;
vsize -= NBPG;
};
return (value);
}
if (!maskptr)
maskptr = &pci_int_mask[irq];
INTRMASK (*maskptr, mask);
register_intr(
irq, /* isa irq */
0, /* deviced?? */
0, /* flags? */
(inthand2_t*) func, /* handler */
#ifdef __FreeBSD2__
*maskptr, /* mask */
#else
maskptr, /* mask pointer */
#endif
(int) arg); /* handler arg */
#ifdef __FreeBSD2__
/*
** 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;
};
#endif
INTREN (mask);
return (1);
}
/*-----------------------------------------------------------
**
@ -554,7 +517,7 @@ struct vt {
static struct vt VendorTable[] = {
{0x1002, "ATI TECHNOLOGIES INC"},
{0x1011, "DIGITAL EQUIPMENT CORP."},
{0x1011, "DIGITAL EQUIPMENT CORPORATION"},
{0x101A, "NCR"},
{0x102B, "MATROX"},
{0x1045, "OPTI"},
@ -604,18 +567,107 @@ void not_supported (pcici_t tag, u_long type)
case 1:
case 5:
printf (" map(%lx): io(%lx)\n", reg, data & ~3);
printf (" map(%x): io(%lx)\n",
reg, data & ~3);
break;
case 0:
printf (" map(%lx): mem32(%lx)\n", reg, data & ~7);
printf (" map(%x): mem32(%lx)\n",
reg, data & ~7);
break;
case 2:
printf (" map(%lx): mem20(%lx)\n", reg, data & ~7);
printf (" map(%x): mem20(%lx)\n",
reg, data & ~7);
break;
case 4:
printf (" map(%lx): mem64(%lx)\n", reg, data & ~7);
printf (" map(%x): mem64(%lx)\n",
reg, data & ~7);
break;
}
}
}
#endif
#ifndef __FreeBSD2__
/*-----------------------------------------------------------
**
** Mapping of physical to virtual memory
**
**-----------------------------------------------------------
*/
extern vm_map_t kernel_map;
static vm_offset_t pmap_mapdev (vm_offset_t paddr, vm_size_t vsize)
{
vm_offset_t vaddr,value;
u_long result;
vaddr = vm_map_min (kernel_map);
result = vm_map_find (kernel_map, (void*)0, (vm_offset_t) 0,
&vaddr, vsize, TRUE);
if (result != KERN_SUCCESS) {
printf (" vm_map_find failed(%d)\n", result);
return (0);
};
/*
** map physical
*/
value = vaddr;
while (vsize >= NBPG) {
pmap_enter (pmap_kernel(), vaddr, paddr,
VM_PROT_READ|VM_PROT_WRITE, TRUE);
vaddr += NBPG;
paddr += NBPG;
vsize -= NBPG;
};
return (value);
}
/*------------------------------------------------------------
**
** Emulate the register_intr() function of FreeBSD 2.0
**
** requires a patch:
** FreeBSD 2.0: "/sys/i386/isa/vector.s"
** 386bsd0.1: "/sys/i386/isa/icu.s"
** 386bsd1.0: Please ask Jesus Monroy Jr.
**
**------------------------------------------------------------
*/
#include <machine/segments.h>
int pci_int_unit [16];
inthand2_t* (pci_int_hdlr [16]);
unsigned int * pci_int_mptr [16];
unsigned int pci_int_count[16];
extern void
Vpci3(), Vpci4(), Vpci5(), Vpci6(), Vpci7(), Vpci8(), Vpci9(),
Vpci10(), Vpci11(), Vpci12(), Vpci13(), Vpci14(), Vpci15();
static inthand_t* pci_int_glue[16] = {
0, 0, 0, Vpci3, Vpci4, Vpci5, Vpci6, Vpci7, Vpci8,
Vpci9, Vpci10, Vpci11, Vpci12, Vpci13, Vpci14, Vpci15 };
static int
register_intr __P((int intr, int device_id, unsigned int flags,
inthand2_t *handler, unsigned int* mptr, int unit))
{
if (intr >= 16 || intr <= 2)
return (EINVAL);
if (pci_int_hdlr [intr])
return (EBUSY);
pci_int_hdlr [intr] = handler;
pci_int_unit [intr] = unit;
pci_int_mptr [intr] = mptr;
setidt(NRSVIDT + intr, pci_int_glue[intr], SDT_SYS386IGT, SEL_KPL);
return (0);
}
#endif /* __FreeBSD2__ */
#endif /* NPCI */