diff options
author | peter <peter@FreeBSD.org> | 1995-12-30 19:02:48 +0000 |
---|---|---|
committer | peter <peter@FreeBSD.org> | 1995-12-30 19:02:48 +0000 |
commit | ab124e78b0271ddb904b761b31e5c9a0cf24e070 (patch) | |
tree | 0cf1447720c45721ed3d214a4eaaa6834bda155d /sys/i386/pci/pci.c | |
parent | 15748830d0fcd29294a1969a1012655e74908c1e (diff) | |
download | FreeBSD-src-ab124e78b0271ddb904b761b31e5c9a0cf24e070.zip FreeBSD-src-ab124e78b0271ddb904b761b31e5c9a0cf24e070.tar.gz |
recording cvs-1.6 file death
Diffstat (limited to 'sys/i386/pci/pci.c')
-rw-r--r-- | sys/i386/pci/pci.c | 778 |
1 files changed, 0 insertions, 778 deletions
diff --git a/sys/i386/pci/pci.c b/sys/i386/pci/pci.c deleted file mode 100644 index 6ef7163..0000000 --- a/sys/i386/pci/pci.c +++ /dev/null @@ -1,778 +0,0 @@ -/************************************************************************** -** -** $Id: pci.c,v 1.8 1994/10/25 23:09:08 se Exp $ -** -** General subroutines for the PCI bus on 80*86 systems. -** pci_configure () -** -** 386bsd / FreeBSD -** -**------------------------------------------------------------------------- -** -** Copyright (c) 1994 Wolfgang Stanglmeier. All rights reserved. -** -** Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions -** are met: -** 1. Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** 2. Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in the -** documentation and/or other materials provided with the distribution. -** 3. The name of the author may not be used to endorse or promote products -** derived from this software without specific prior written permission. -** -** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR -** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES -** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, -** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (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 - -#ifndef __FreeBSD2__ -#if __FreeBSD__ >= 2 -#define __FreeBSD2__ -#endif -#endif - -/*======================================================== -** -** #includes and declarations -** -**======================================================== -*/ - -#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/isa.h> -#include <i386/isa/isa_device.h> -#include <i386/isa/icu.h> -#include <i386/pci/pcireg.h> - -#ifdef __FreeBSD2__ -#include <sys/devconf.h> - -struct pci_devconf { - struct kern_devconf pdc_kdc; - struct pci_info pdc_pi; -}; -#endif - -/* -** Function prototypes missing in system headers -*/ - -#ifndef __FreeBSD2__ -extern pmap_t pmap_kernel(void); -static vm_offset_t pmap_mapdev (vm_offset_t paddr, vm_size_t vsize); - -/* - * Type of the first (asm) part of an interrupt handler. - */ -typedef void inthand_t __P((u_int cs, u_int ef, u_int esp, u_int ss)); - -/* - * Usual type of the second (C) part of an interrupt handler. Some bogus - * ones need the arg to be the interrupt frame (and not a copy of it, which - * is all that is possible in C). - */ -typedef void inthand2_t __P((int unit)); - -/* -** XXX @FreeBSD2@ -** -** Unfortunately, the mptr argument is _no_ pointer in 2.0 FreeBSD. -** We would prefer a pointer because it enables us to install -** new interrupt handlers at any time. -** (This is just going to be changed ... <se> :) -** In 2.0 FreeBSD later installed interrupt handlers may change -** the xyz_imask, but this would not be recognized by handlers -** which are installed before. -*/ - -static int -register_intr __P((int intr, int device_id, unsigned int flags, - inthand2_t *handler, unsigned int * mptr, int unit)); -extern unsigned intr_mask[ICU_LEN]; - -#endif /* !__FreeBSD2__ */ - -/*======================================================== -** -** Autoconfiguration of pci devices. -** -** This is reverse to the isa configuration. -** (1) find a pci device. -** (2) look for a driver. -** -**======================================================== -*/ - -/*-------------------------------------------------------- -** -** The pci devices can be mapped to any address. -** As default we start at the last gigabyte. -** -**-------------------------------------------------------- -*/ - -#ifndef PCI_PMEM_START -#define PCI_PMEM_START 0xc0000000 -#endif - -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; - -#ifdef __FreeBSD2__ -static int -pci_externalize (struct proc *, struct kern_devconf *, void *, size_t); - -static int -pci_internalize (struct proc *, struct kern_devconf *, void *, size_t); - -#endif /* __FreeBSD2__ */ - -void pci_configure() -{ - u_char device,last_device; - u_short bus; - pcici_t tag; - pcidi_t type; - u_long data; - int unit; - int pci_mechanism; - int pciint; - int irq; - char* name=0; - vm_offset_t old_addr=pci_paddr; - - struct pci_driver *drp=0; - struct pci_device *dvp; - -#ifdef __FreeBSD2__ - struct pci_devconf *pdcp; -#endif - - /* - ** check pci bus present - */ - - 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%d: scanning device 0..%d, mechanism=%d.\n", - bus, last_device, pci_mechanism); -#endif - for (device=0; device<=last_device; device ++) { - - if (pci_seen[bus] & (1ul << device)) - continue; - - tag = pcitag (bus, device, 0); - type = pci_conf_read (tag, PCI_ID_REG); - - if ((!type) || (type==0xfffffffful)) continue; - - /* - ** lookup device in ioconfiguration: - */ - - for (dvp = pci_devtab; dvp->pd_name; dvp++) { - drp = dvp->pd_driver; - if (!drp) - continue; - if ((name=(*drp->probe)(tag, type))) - break; - }; - - if (!dvp->pd_name) { -#ifndef PCI_QUIET - if (pci_conf_count) - continue; - printf("pci%d:%d: ", bus, device); - not_supported (tag, type); -#endif - continue; - }; - - pci_seen[bus] |= (1ul << device); - /* - ** Get and increment the unit. - */ - - unit = (*drp->count)++; - - /* - ** ignore device ? - */ - - if (!*name) continue; - - /* - ** Announce this device - */ - - printf ("%s%d <%s>", dvp->pd_name, unit, name); - - /* - ** Get the int pin number (pci interrupt number a-d) - ** from the pci configuration space. - */ - - data = pci_conf_read (tag, PCI_INTERRUPT_REG); - pciint = PCI_INTERRUPT_PIN_EXTRACT(data); - - if (pciint) { - - printf (" int %c", 0x60+pciint); - - /* - ** If the interrupt line register is not set, - ** set it now from PCI_IRQ. - */ - - if (!(PCI_INTERRUPT_LINE_EXTRACT(data))) { - - irq = pci_irq & 0x0f; - pci_irq >>= 4; - - data = PCI_INTERRUPT_LINE_INSERT(data, irq); - printf (" (config)"); - pci_conf_write (tag, PCI_INTERRUPT_REG, data); - }; - - irq = PCI_INTERRUPT_LINE_EXTRACT(data); - - /* - ** If it's zero, the isa irq number is unknown, - ** and we cannot bind the pci interrupt to isa. - */ - - 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; - - pci_conf_write (tag, (u_char) PCI_COMMAND_STATUS_REG, data); - - /* - ** show pci slot. - */ - - printf (" on pci%d:%d\n", bus, device); - -#ifdef __FreeBSD2__ - - /* - ** Allocate a devconf structure - */ - - pdcp = (struct pci_devconf *) - malloc (sizeof (struct pci_devconf),M_DEVBUF,M_WAITOK); - - /* - ** Fill in. - ** - ** Sorry, this is not yet complete. - ** We should, and eventually will, set the - ** parent pointer to a pci bus devconf structure, - ** and arrange to set the state field dynamically. - ** - ** But I'll go to vacation today, and after all, - ** wasn't there a new feature freeze on Oct 1.? - */ - - pdcp -> pdc_pi.pi_bus = bus; - pdcp -> pdc_pi.pi_device = device; - - pdcp -> pdc_kdc.kdc_name = dvp->pd_name; - pdcp -> pdc_kdc.kdc_unit = unit; - - pdcp -> pdc_kdc.kdc_md.mddc_devtype = MDDT_PCI; - - pdcp -> pdc_kdc.kdc_externalize = pci_externalize; - pdcp -> pdc_kdc.kdc_internalize = pci_internalize; - - pdcp -> pdc_kdc.kdc_datalen = PCI_EXTERNAL_LEN; - pdcp -> pdc_kdc.kdc_parentdata = &pdcp->pdc_pi; - pdcp -> pdc_kdc.kdc_state = DC_UNKNOWN; - pdcp -> pdc_kdc.kdc_description = name; - - /* - ** And register this device - */ - - dev_attach (&pdcp->pdc_kdc); - -#endif /* __FreeBSD2__ */ - - - /* - ** attach device - ** may produce additional log messages, - ** i.e. when installing subdevices. - */ - - (*drp->attach) (tag, unit); - }; - }; - -#ifndef PCI_QUIET - if (pci_paddr != old_addr) - printf ("pci uses physical addresses from 0x%lx to 0x%lx\n", - (u_long)PCI_PMEM_START, (u_long)pci_paddr); -#endif - pci_conf_count++; -} - -/*----------------------------------------------------------------------- -** -** Map device into port space. -** -** PCI-Specification: 6.2.5.1: address maps -** -**----------------------------------------------------------------------- -*/ - -int pci_map_port (pcici_t tag, u_long reg, u_short* pa) -{ - /* - ** @MAPIO@ not yet implemented. - */ - printf ("pci_map_port failed: not yet implemented\n"); - return (0); -} - -/*----------------------------------------------------------------------- -** -** Map device into virtual and physical space -** -** PCI-Specification: 6.2.5.1: address maps -** -**----------------------------------------------------------------------- -*/ - -int pci_map_mem (pcici_t tag, u_long reg, vm_offset_t* va, vm_offset_t* pa) -{ - u_long data; - vm_size_t vsize; - vm_offset_t vaddr; - - /* - ** sanity check - */ - - if (reg < PCI_MAP_REG_START || reg >= PCI_MAP_REG_END || (reg & 3)) { - printf ("pci_map_mem failed: bad register=0x%x\n", - (unsigned)reg); - return (0); - }; - - /* - ** get size and type of memory - ** - ** type is in the lowest four bits. - ** If device requires 2^n bytes, the next - ** n-4 bits are read as 0. - */ - - pci_conf_write (tag, reg, 0xfffffffful); - data = pci_conf_read (tag, reg); - - switch (data & 0x0f) { - - case PCI_MAP_MEMORY_TYPE_32BIT: /* 32 bit non cachable */ - break; - - default: /* unknown */ - printf ("pci_map_mem failed: bad memory type=0x%x\n", - (unsigned) data); - return (0); - }; - - /* - ** mask out the type, - ** and round up to a page size - */ - - vsize = round_page (-(data & PCI_MAP_MEMORY_ADDRESS_MASK)); - - if (!vsize) return (0); - - /* - ** align physical address to virtual size - */ - - if ((data = pci_paddr % vsize)) - pci_paddr += vsize - data; - - vaddr = (vm_offset_t) pmap_mapdev (pci_paddr, vsize); - - - if (!vaddr) return (0); - -#ifndef PCI_QUIET - /* - ** display values. - */ - - printf ("\treg%d: virtual=0x%lx physical=0x%lx\n", - (unsigned) reg, (u_long)vaddr, (u_long)pci_paddr); -#endif - - /* - ** return them to the driver - */ - - *va = vaddr; - *pa = pci_paddr; - - /* - ** set device address - */ - - pci_conf_write (tag, reg, pci_paddr); - - /* - ** and don't forget to increment pci_paddr - */ - - pci_paddr += vsize; - - return (1); -} - -/*------------------------------------------------------------ -** -** Interface functions for the devconf module. -** -**------------------------------------------------------------ -*/ - -static int -pci_externalize (struct proc *p, struct kern_devconf *kdcp, void *u, size_t l) -{ - struct pci_externalize_buffer buffer; - struct pci_info * pip = kdcp->kdc_parentdata; - pcici_t tag; - int i; - - if (l < sizeof buffer) { - return ENOMEM; - }; - - tag = pcitag (pip->pi_bus, pip->pi_device, 0); - - buffer.peb_pci_info = *pip; - - for (i=0; i<PCI_EXT_CONF_LEN; i++) { - buffer.peb_config[i] = pci_conf_read (tag, i*4); - }; - - return copyout(&buffer, u, sizeof buffer); -} - - -static int -pci_internalize (struct proc *p, struct kern_devconf *kdcp, void *u, size_t s) -{ - return EOPNOTSUPP; -} - -/*----------------------------------------------------------------------- -** -** Map pci interrupts to isa interrupts. -** -**----------------------------------------------------------------------- -*/ - -static unsigned int pci_int_mask [16]; - -int pci_map_int (pcici_t tag, int(*func)(), void* arg, unsigned* maskptr) -{ - int irq; - unsigned mask; - - irq = PCI_INTERRUPT_LINE_EXTRACT( - pci_conf_read (tag, PCI_INTERRUPT_REG)); - - if (irq >= 16 || irq <= 0) { - printf ("pci_map_int failed: no int line set.\n"); - return (0); - } - - mask = 1ul << irq; - - if (!maskptr) - maskptr = &pci_int_mask[irq]; - - INTRMASK (*maskptr, mask); - - register_intr( - irq, /* isa irq */ - 0, /* deviced?? */ - 0, /* flags? */ - (inthand2_t*) func, /* handler */ - maskptr, /* mask pointer */ - (int) arg); /* handler arg */ - -#ifdef __FreeBSD2__ - /* - ** XXX See comment at beginning of file. - ** - ** Have to update all the interrupt masks ... Grrrrr!!! - */ - { - unsigned * mp = &intr_mask[0]; - /* - ** update the isa interrupt masks. - */ - for (mp=&intr_mask[0]; mp<&intr_mask[ICU_LEN]; mp++) - if (*mp & *maskptr) - *mp |= mask; - /* - ** update the pci interrupt masks. - */ - for (mp=&pci_int_mask[0]; mp<&pci_int_mask[16]; mp++) - if (*mp & *maskptr) - *mp |= mask; - }; -#endif - - INTREN (mask); - - return (1); -} - -/*----------------------------------------------------------- -** -** Display of unknown devices. -** -**----------------------------------------------------------- -*/ -struct vt { - u_short ident; - char* name; -}; - -static struct vt VendorTable[] = { - {0x1002, "ATI TECHNOLOGIES INC"}, - {0x1011, "DIGITAL EQUIPMENT CORPORATION"}, - {0x101A, "NCR"}, - {0x102B, "MATROX"}, - {0x1045, "OPTI"}, - {0x5333, "S3 INC."}, - {0x8086, "INTEL CORPORATION"}, - {0,0} -}; - -static const char *const majclasses[] = { - "old", "storage", "network", "display", - "multimedia", "memory", "bridge" -}; - -void not_supported (pcici_t tag, u_long type) -{ - u_char reg; - u_long data; - struct vt * vp; - - /* - ** lookup the names. - */ - - for (vp=VendorTable; vp->ident; vp++) - if (vp->ident == (type & 0xffff)) - break; - - /* - ** and display them. - */ - - if (vp->ident) printf (vp->name); - else printf ("vendor=0x%lx", type & 0xffff); - - printf (", device=0x%lx", type >> 16); - - data = (pci_conf_read(tag, PCI_CLASS_REG) >> 24) & 0xff; - if (data < sizeof(majclasses) / sizeof(majclasses[0])) - printf(", class=%s", majclasses[data]); - - printf (" [not supported]\n"); - - for (reg=PCI_MAP_REG_START; reg<PCI_MAP_REG_END; reg+=4) { - data = pci_conf_read (tag, reg); - if (!data) continue; - switch (data&7) { - - case 1: - case 5: - printf (" map(%x): io(%lx)\n", - reg, data & ~3); - break; - case 0: - printf (" map(%x): mem32(%lx)\n", - reg, data & ~7); - break; - case 2: - printf (" map(%x): mem20(%lx)\n", - reg, data & ~7); - break; - case 4: - printf (" map(%x): mem64(%lx)\n", - reg, data & ~7); - break; - } - } -} - -#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 */ |