diff --git a/sys/dev/pci/pci.c b/sys/dev/pci/pci.c index f07228452a7c..93b2d17db16b 100644 --- a/sys/dev/pci/pci.c +++ b/sys/dev/pci/pci.c @@ -1,598 +1,620 @@ /************************************************************************** ** -** $Id: pci.c,v 2.0.0.8 94/08/21 19:57:39 wolf Exp $ +** $Id: pci.c,v 1.2 1994/09/01 02:01:34 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. ** **------------------------------------------------------------------------- ** -** $Log: pci.c,v $ +** $Log: pci.c,v $ + * Revision 1.2 1994/09/01 02:01:34 se + * Submitted by: Wolfgang Stanglmeier + * Merged in changes required for NetBSD support (by mycroft@gnu.ai.mit.edu) + * and support for multiple NCR chips. + * ** Revision 2.0.0.8 94/08/21 19:57:39 wolf ** Unneeded declarations removed (FreeBSD2.0) ** ** Revision 2.0.0.7 94/08/21 19:25:54 wolf ** pci_intr simplified. ** new not_supported() function. ** Vendor and device ids moved into tables. ** ** Revision 2.0.0.6 94/08/18 22:58:23 wolf ** Symbolic names for pci configuration space registers. ** last_device: from configuration mode ** last_bus: from pcibios. ** PCI_MAX_DPI: changed to 4 (settable by config) ** interrupt configuration by line or pin ** ** Revision 2.0.0.5 94/08/11 19:04:10 wolf ** display of interrupt line configuration register. ** ** Revision 2.0.0.4 94/08/01 20:36:28 wolf ** Tiny clean up. ** ** Revision 2.0.0.3 94/08/01 18:52:33 wolf ** New vendor entry: S3. ** Scan pci busses #0..#255 as default. ** Number of scanned busses and devices settable as option. ** Show these numbers before starting the scan. ** ** Revision 2.0.0.2 94/07/27 09:27:19 wolf ** New option PCI_QUIET: suppress log messages. ** ** Revision 2.0.0.1 94/07/19 19:06:44 wolf ** New vendor entry: MATROX ** ** Revision 2.0 94/07/10 15:53:29 wolf ** FreeBSD release. ** ** Revision 1.0 94/06/07 20:02:19 wolf ** Beta release. ** *************************************************************************** */ #include #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*/ /*======================================================== ** ** #includes and declarations ** **======================================================== */ -#include -#include -#include -#include +#include +#include +#include #include #include #include #include #include #include #include #include char ident_pci_c[] = - "\n$Id: pci.c,v 2.0.0.8 94/08/21 19:57:39 wolf Exp $\n" + "\n$Id: pci.c,v 1.2 1994/09/01 02:01:34 se Exp $\n" "Copyright (c) 1994, Wolfgang Stanglmeier\n"; /* ** Function prototypes missing in system headers */ -extern int printf(); -extern int ffs(); #if ! (__FreeBSD__ >= 2) extern pmap_t pmap_kernel(void); #endif /*======================================================== ** ** Autoconfiguration (of isa bus) ** **======================================================== */ /* ** per device (interrupt) data structure. */ static struct { u_short number; u_short isanum; struct { int (*proc)(int dev); dev_t unit; } vector[PCI_MAX_DPI]; } pcidata [NPCI]; /* ** 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); } /* ** 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" }; /*======================================================== ** ** Interrupt forward from isa to pci devices. ** **======================================================== */ void pciintr (int unit) { u_short i; if (unit >= NPCI) return; for (i=0; ipd_driver; dvp++) { - if (drp->device_id == type) break; + for (dvp = pci_devtab; dvp->pd_device_id; dvp++) { + if (dvp->pd_device_id == type) break; }; - -#ifdef PCI_QUIET - if (!drp) continue; -#endif - printf ("on pci%d:%d ", bus, device); + drp = dvp->pd_driver; + + if (!dvp->pd_device_id) { + int data = pci_conf_read(tag, PCI_CLASS_REV_REG); + enum pci_majclass class = PCI_MAJCLASS_OF(data); + vm_offset_t va; + vm_offset_t pa; + int reg; + + switch(class) { + case PCI_MJC_OLD: + if(PCI_MINCLASS_OF(data) != PCI_MIN_OVGA) + break; + case PCI_MJC_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 %lx\n", + bus, device, (u_long)pa); + + } + continue; + default: #ifndef PCI_QUIET + printf("pci%d:%d: ", bus, device); + not_supported (tag, type); +#endif + } + } + if (!drp) { - not_supported (tag, type); + if(dvp->pd_flags & PDF_LOADABLE) { + printf("%s: loadable device on pci%d:%d\n", + dvp->pd_name, bus, device); + } continue; - }; -#endif + } /* ** found it. ** probe returns the device unit. */ - - printf ("<%s>", drp -> vendor); - unit = (*drp->probe) (tag); if (unit<0) { - printf (" probe failed.\n"); + printf ("%s <%s>: probe failed on pci%d:%d\n", + drp->name, drp->vendor, bus, device); continue; }; + if (drp->name) { + printf ("%s%d <%s>", drp->name, unit, drp->vendor); + } else { + printf ("pci%d: <%s>", bus, drp->vendor); + } + /* ** install interrupts */ data = pci_conf_read (tag, PCI_INTERRUPT_REG); intpin = PCI_INTERRUPT_PIN_EXTRACT(data); if (intpin) { int idx=NPCI; /* ** Usage of int line register (if set by bios) ** Matt Thomas */ isanum = PCI_INTERRUPT_LINE_EXTRACT(data); if (isanum) { printf (" il=%d", isanum); for (idx = 0; idx < NPCI; idx++) { if (pcidata[idx].isanum == isanum) break; - }; - }; + } + } /* ** Or believe to the interrupt pin register. */ if (idx >= NPCI) idx = intpin-1; /* ** And install the interrupt. */ if (idxintr; pcidata[idx].vector[entry].unit = unit; entry++; }; printf (" isa=%d [%d]",pcidata[idx].isanum, entry); pcidata[idx].number=entry; } else { printf (" not installed"); - }; - }; + } + } /* ** 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); + printf (" on pci%d:%d\n", bus, device); + /* ** attach device ** may produce additional log messages, ** i.e. when installing subdevices. */ - - printf (" as %s%d\n", drp->name,unit); (void) (*drp->attach) (tag); + } - }; - - printf ("pci uses physical addresses from %x to %x\n", - PCI_PMEM_START, pci_paddr); +#ifndef PCI_QUIET + printf ("pci uses physical addresses from %lx to %lx\n", + (u_long)PCI_PMEM_START, (u_long)pci_paddr); +#endif } /*----------------------------------------------------------------------- ** ** Map device into port space. ** ** PCI-Specification: 6.2.5.1: address maps ** **----------------------------------------------------------------------- */ extern vm_map_t kernel_map; int pci_map_port (pcici_t tag, u_long reg, u_short* pa) { /* ** @MAPIO@ not yet implemented. */ return (ENOSYS); } /*----------------------------------------------------------------------- ** ** 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, result; vm_size_t vsize; vm_offset_t vaddr; /* ** sanity check */ if (reg <= PCI_MAP_REG_START || reg >= PCI_MAP_REG_END || (reg & 3)) return (EINVAL); /* ** 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 */ return (EINVAL); }; /* ** mask out the type, ** and round up to a page size */ vsize = round_page (-(data & PCI_MAP_MEMORY_ADDRESS_MASK)); - printf (" memory size=0x%x", vsize); - if (!vsize) return (EINVAL); - /* - ** try to map device to virtual space - */ - - 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 (ENOMEM); - }; - /* ** align physical address to virtual size */ if (data = pci_paddr % vsize) pci_paddr += vsize - data; + vaddr = pmap_mapdev (pci_paddr, vsize); + +#if 0 /* ** display values. */ - printf (" virtual=0x%x physical=0x%x\n", vaddr, pci_paddr); + printf (" virtual=0x%lx physical=0x%lx\n", (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); - /* - ** map physical - */ - - while (vsize >= NBPG) { - pmap_enter (pmap_kernel(), vaddr, pci_paddr, - VM_PROT_READ|VM_PROT_WRITE, TRUE); - vaddr += NBPG; - pci_paddr += NBPG; - vsize -= NBPG; - }; - return (0); } struct vt { u_short ident; char* name; }; struct dt { u_long ident; char* name; }; static struct vt VendorTable[] = { {0x1002, "ATI TECHNOLOGIES INC"}, {0x1011, "DIGITAL EQUIPMENT COMPANY"}, {0x101A, "NCR"}, {0x102B, "MATROX"}, {0x1045, "OPTI"}, {0x5333, "S3 INC."}, {0x8086, "INTEL CORPORATION"}, {0,0} }; static struct dt DeviceTable[] = { {0x04848086, " 82378IB pci-isa bridge"}, {0x04838086, " 82424ZX cache dram controller"}, {0x04828086, " 82375EB pci-eisa bridge"}, {0x04A38086, " 82434LX pci cache memory controller"}, {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; struct dt * dp; /* ** lookup the names. */ for (vp=VendorTable; vp->ident; vp++) if (vp->ident == (type & 0xffff)) break; for (dp=DeviceTable; dp->ident; dp++) if (dp->ident == type) break; /* ** and display them. */ if (vp->ident) printf (vp->name); - else printf ("vendor=%x", type & 0xffff); + else printf ("vendor=%lx", type & 0xffff); if (dp->ident) printf (dp->name); - else printf (", device=%x", type >> 16); + else printf (", device=%lx", type >> 16); + + data = pci_conf_read(tag, PCI_CLASS_REV_REG); + if (PCI_MAJCLASS_OF(data) < sizeof(majclasses) / sizeof(majclasses[0])) + printf(", class=%s", majclasses[PCI_MAJCLASS_OF(data)]); printf (" [not supported]\n"); for (reg=PCI_MAP_REG_START; reg + * Merged in changes required for NetBSD support (by mycroft@gnu.ai.mit.edu) + * and support for multiple NCR chips. + * ** Revision 2.0.0.8 94/08/21 19:57:39 wolf ** Unneeded declarations removed (FreeBSD2.0) ** ** Revision 2.0.0.7 94/08/21 19:25:54 wolf ** pci_intr simplified. ** new not_supported() function. ** Vendor and device ids moved into tables. ** ** Revision 2.0.0.6 94/08/18 22:58:23 wolf ** Symbolic names for pci configuration space registers. ** last_device: from configuration mode ** last_bus: from pcibios. ** PCI_MAX_DPI: changed to 4 (settable by config) ** interrupt configuration by line or pin ** ** Revision 2.0.0.5 94/08/11 19:04:10 wolf ** display of interrupt line configuration register. ** ** Revision 2.0.0.4 94/08/01 20:36:28 wolf ** Tiny clean up. ** ** Revision 2.0.0.3 94/08/01 18:52:33 wolf ** New vendor entry: S3. ** Scan pci busses #0..#255 as default. ** Number of scanned busses and devices settable as option. ** Show these numbers before starting the scan. ** ** Revision 2.0.0.2 94/07/27 09:27:19 wolf ** New option PCI_QUIET: suppress log messages. ** ** Revision 2.0.0.1 94/07/19 19:06:44 wolf ** New vendor entry: MATROX ** ** Revision 2.0 94/07/10 15:53:29 wolf ** FreeBSD release. ** ** Revision 1.0 94/06/07 20:02:19 wolf ** Beta release. ** *************************************************************************** */ #include #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*/ /*======================================================== ** ** #includes and declarations ** **======================================================== */ -#include -#include -#include -#include +#include +#include +#include #include #include #include #include #include #include #include #include char ident_pci_c[] = - "\n$Id: pci.c,v 2.0.0.8 94/08/21 19:57:39 wolf Exp $\n" + "\n$Id: pci.c,v 1.2 1994/09/01 02:01:34 se Exp $\n" "Copyright (c) 1994, Wolfgang Stanglmeier\n"; /* ** Function prototypes missing in system headers */ -extern int printf(); -extern int ffs(); #if ! (__FreeBSD__ >= 2) extern pmap_t pmap_kernel(void); #endif /*======================================================== ** ** Autoconfiguration (of isa bus) ** **======================================================== */ /* ** per device (interrupt) data structure. */ static struct { u_short number; u_short isanum; struct { int (*proc)(int dev); dev_t unit; } vector[PCI_MAX_DPI]; } pcidata [NPCI]; /* ** 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); } /* ** 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" }; /*======================================================== ** ** Interrupt forward from isa to pci devices. ** **======================================================== */ void pciintr (int unit) { u_short i; if (unit >= NPCI) return; for (i=0; ipd_driver; dvp++) { - if (drp->device_id == type) break; + for (dvp = pci_devtab; dvp->pd_device_id; dvp++) { + if (dvp->pd_device_id == type) break; }; - -#ifdef PCI_QUIET - if (!drp) continue; -#endif - printf ("on pci%d:%d ", bus, device); + drp = dvp->pd_driver; + + if (!dvp->pd_device_id) { + int data = pci_conf_read(tag, PCI_CLASS_REV_REG); + enum pci_majclass class = PCI_MAJCLASS_OF(data); + vm_offset_t va; + vm_offset_t pa; + int reg; + + switch(class) { + case PCI_MJC_OLD: + if(PCI_MINCLASS_OF(data) != PCI_MIN_OVGA) + break; + case PCI_MJC_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 %lx\n", + bus, device, (u_long)pa); + + } + continue; + default: #ifndef PCI_QUIET + printf("pci%d:%d: ", bus, device); + not_supported (tag, type); +#endif + } + } + if (!drp) { - not_supported (tag, type); + if(dvp->pd_flags & PDF_LOADABLE) { + printf("%s: loadable device on pci%d:%d\n", + dvp->pd_name, bus, device); + } continue; - }; -#endif + } /* ** found it. ** probe returns the device unit. */ - - printf ("<%s>", drp -> vendor); - unit = (*drp->probe) (tag); if (unit<0) { - printf (" probe failed.\n"); + printf ("%s <%s>: probe failed on pci%d:%d\n", + drp->name, drp->vendor, bus, device); continue; }; + if (drp->name) { + printf ("%s%d <%s>", drp->name, unit, drp->vendor); + } else { + printf ("pci%d: <%s>", bus, drp->vendor); + } + /* ** install interrupts */ data = pci_conf_read (tag, PCI_INTERRUPT_REG); intpin = PCI_INTERRUPT_PIN_EXTRACT(data); if (intpin) { int idx=NPCI; /* ** Usage of int line register (if set by bios) ** Matt Thomas */ isanum = PCI_INTERRUPT_LINE_EXTRACT(data); if (isanum) { printf (" il=%d", isanum); for (idx = 0; idx < NPCI; idx++) { if (pcidata[idx].isanum == isanum) break; - }; - }; + } + } /* ** Or believe to the interrupt pin register. */ if (idx >= NPCI) idx = intpin-1; /* ** And install the interrupt. */ if (idxintr; pcidata[idx].vector[entry].unit = unit; entry++; }; printf (" isa=%d [%d]",pcidata[idx].isanum, entry); pcidata[idx].number=entry; } else { printf (" not installed"); - }; - }; + } + } /* ** 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); + printf (" on pci%d:%d\n", bus, device); + /* ** attach device ** may produce additional log messages, ** i.e. when installing subdevices. */ - - printf (" as %s%d\n", drp->name,unit); (void) (*drp->attach) (tag); + } - }; - - printf ("pci uses physical addresses from %x to %x\n", - PCI_PMEM_START, pci_paddr); +#ifndef PCI_QUIET + printf ("pci uses physical addresses from %lx to %lx\n", + (u_long)PCI_PMEM_START, (u_long)pci_paddr); +#endif } /*----------------------------------------------------------------------- ** ** Map device into port space. ** ** PCI-Specification: 6.2.5.1: address maps ** **----------------------------------------------------------------------- */ extern vm_map_t kernel_map; int pci_map_port (pcici_t tag, u_long reg, u_short* pa) { /* ** @MAPIO@ not yet implemented. */ return (ENOSYS); } /*----------------------------------------------------------------------- ** ** 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, result; vm_size_t vsize; vm_offset_t vaddr; /* ** sanity check */ if (reg <= PCI_MAP_REG_START || reg >= PCI_MAP_REG_END || (reg & 3)) return (EINVAL); /* ** 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 */ return (EINVAL); }; /* ** mask out the type, ** and round up to a page size */ vsize = round_page (-(data & PCI_MAP_MEMORY_ADDRESS_MASK)); - printf (" memory size=0x%x", vsize); - if (!vsize) return (EINVAL); - /* - ** try to map device to virtual space - */ - - 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 (ENOMEM); - }; - /* ** align physical address to virtual size */ if (data = pci_paddr % vsize) pci_paddr += vsize - data; + vaddr = pmap_mapdev (pci_paddr, vsize); + +#if 0 /* ** display values. */ - printf (" virtual=0x%x physical=0x%x\n", vaddr, pci_paddr); + printf (" virtual=0x%lx physical=0x%lx\n", (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); - /* - ** map physical - */ - - while (vsize >= NBPG) { - pmap_enter (pmap_kernel(), vaddr, pci_paddr, - VM_PROT_READ|VM_PROT_WRITE, TRUE); - vaddr += NBPG; - pci_paddr += NBPG; - vsize -= NBPG; - }; - return (0); } struct vt { u_short ident; char* name; }; struct dt { u_long ident; char* name; }; static struct vt VendorTable[] = { {0x1002, "ATI TECHNOLOGIES INC"}, {0x1011, "DIGITAL EQUIPMENT COMPANY"}, {0x101A, "NCR"}, {0x102B, "MATROX"}, {0x1045, "OPTI"}, {0x5333, "S3 INC."}, {0x8086, "INTEL CORPORATION"}, {0,0} }; static struct dt DeviceTable[] = { {0x04848086, " 82378IB pci-isa bridge"}, {0x04838086, " 82424ZX cache dram controller"}, {0x04828086, " 82375EB pci-eisa bridge"}, {0x04A38086, " 82434LX pci cache memory controller"}, {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; struct dt * dp; /* ** lookup the names. */ for (vp=VendorTable; vp->ident; vp++) if (vp->ident == (type & 0xffff)) break; for (dp=DeviceTable; dp->ident; dp++) if (dp->ident == type) break; /* ** and display them. */ if (vp->ident) printf (vp->name); - else printf ("vendor=%x", type & 0xffff); + else printf ("vendor=%lx", type & 0xffff); if (dp->ident) printf (dp->name); - else printf (", device=%x", type >> 16); + else printf (", device=%lx", type >> 16); + + data = pci_conf_read(tag, PCI_CLASS_REV_REG); + if (PCI_MAJCLASS_OF(data) < sizeof(majclasses) / sizeof(majclasses[0])) + printf(", class=%s", majclasses[PCI_MAJCLASS_OF(data)]); printf (" [not supported]\n"); for (reg=PCI_MAP_REG_START; reg + * Merged in changes required for NetBSD support (by mycroft@gnu.ai.mit.edu) + * and support for multiple NCR chips. + * ** Revision 2.0.0.1 94/08/18 23:07:28 wolf ** Copyright message. ** Hook for DEC ethernet driver "de". ** ** Revision 2.0 94/07/10 15:53:30 wolf ** FreeBSD release. ** ** Revision 1.0 94/06/07 20:04:37 wolf ** Beta release. ** *************************************************************************** */ -#include "types.h" -#include "i386/pci/pci.h" -#include "i386/pci/pci_device.h" +#include +#include +#include #include "ncr.h" #if NNCR>0 extern struct pci_driver ncrdevice; #endif #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; struct pci_device pci_devtab[] = { #if NNCR>0 - {&ncrdevice}, + {&ncrdevice, 0x00011000ul, "ncr", 0}, +#else + {0, 0x00011000ul, "ncr", PDF_LOADABLE}, #endif #if NDE>0 - {&dedevice}, + {&dedevice, 0x00011011ul, "de", 0}, /* FIXME!!! */ +#else + {0, 0x00011011ul, "de", PDF_LOADABLE}, /* FIXME!!! */ #endif - {0} + {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} }; diff --git a/sys/i386/pci/pci_device.h b/sys/i386/pci/pci_device.h index c7bbe6561786..59c4751d6d32 100644 --- a/sys/i386/pci/pci_device.h +++ b/sys/i386/pci/pci_device.h @@ -1,112 +1,122 @@ /************************************************************************** ** -** $Id: pci_device.h,v 2.0.0.1 94/08/18 23:06:43 wolf Exp $ +** $Id: pci_device.h,v 1.2 1994/09/01 02:01:41 se Exp $ ** ** #define for pci based device drivers ** ** 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. ** **------------------------------------------------------------------------- ** -** $Log: pci_device.h,v $ +** $Log: pci_device.h,v $ + * Revision 1.2 1994/09/01 02:01:41 se + * Submitted by: Wolfgang Stanglmeier + * Merged in changes required for NetBSD support (by mycroft@gnu.ai.mit.edu) + * and support for multiple NCR chips. + * ** Revision 2.0.0.1 94/08/18 23:06:43 wolf ** Copyright message. ** ** Revision 2.0 94/07/10 15:53:31 wolf ** FreeBSD release. ** ** Revision 1.0 94/06/07 20:02:22 wolf ** Beta release. ** *************************************************************************** */ #ifndef __PCI_DEVICE_H__ #define __PCI_DEVICE_H__ /*------------------------------------------------------------ ** ** Per driver structure. ** **------------------------------------------------------------ */ struct pci_driver { int (*probe )(pcici_t pci_ident); /* test whether device is present */ int (*attach)(pcici_t pci_ident); /* setup driver for a device */ pcidi_t device_id; /* device pci id */ char *name; /* device name */ char *vendor; /* device long name */ int (*intr)(int); /* interupt handler */ }; /*----------------------------------------------------------- ** ** Per device structure. ** ** It is initialized by the config utility and should live in ** "ioconf.c". At the moment there is only one field. ** ** This is a first attempt to include the pci bus to 386bsd. ** So this structure may grow .. ** **----------------------------------------------------------- */ struct pci_device { struct pci_driver * pd_driver; + pcidi_t pd_device_id; /* device pci id */ + const char *pd_name; /* for future loadable drivers */ + int pd_flags; }; +#define PDF_LOADABLE 0x01 +#define PDF_COVERED 0x02 /*----------------------------------------------------------- ** ** This table should be generated in file "ioconf.c" ** by the config program. ** It is used at boot time by the configuration function ** pci_configure() ** **----------------------------------------------------------- */ extern struct pci_device pci_devtab[]; /*----------------------------------------------------------- ** ** This functions may be used by drivers to map devices ** to virtual and physical addresses. The va and pa ** addresses are "in/out" parameters. If they are 0 ** on entry, the mapping function assigns an address. ** **----------------------------------------------------------- */ int pci_map_mem (pcici_t tag, u_long entry, u_long * va, u_long * pa); int pci_map_port(pcici_t tag, u_long entry, u_short * pa); #endif /*__PCI_DEVICE_H__*/ diff --git a/sys/i386/pci/pci_intel.c b/sys/i386/pci/pci_intel.c index 8d1d10ae9efb..e743c1188ae8 100644 --- a/sys/i386/pci/pci_intel.c +++ b/sys/i386/pci/pci_intel.c @@ -1,310 +1,313 @@ /************************************************************************** ** -** $Id: pci_intel.c,v 1.1 94/09/05 22:38:38 wolf Exp $ +** $Id: pci_intel.c,v 1.1 1994/09/06 22:39:11 se Exp $ ** ** Device driver for INTEL PCI chipsets. ** ** 386bsd / FreeBSD ** **------------------------------------------------------------------------- ** ** Written for 386bsd and FreeBSD by ** wolf@dentaro.gun.de Wolfgang Stanglmeier ** se@mi.Uni-Koeln.de Stefan Esser ** **------------------------------------------------------------------------- ** ** 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. ** **------------------------------------------------------------------------- ** -** $Log: pci_intel.c,v $ +** $Log: pci_intel.c,v $ + * Revision 1.1 1994/09/06 22:39:11 se + * Initial revision + * * Revision 1.1 94/09/05 22:38:38 wolf * Initial revision * * Revision 1.1 94/09/04 16:05:20 wolf * Initial revision * *************************************************************************** */ /*========================================================== ** ** Include files ** **========================================================== */ #include #include #include #include static int probe1(pcici_t config_id); static int return0(int unit); static int intel_attach(pcici_t config_id, pcidi_t type); static int intel_82424zx_attach(pcici_t config_id, pcidi_t type); static int intel_82434lx_attach(pcici_t config_id, pcidi_t type); extern void printf(); static char confread(pcici_t config_id, int port); struct condmsg { unsigned char port; unsigned char mask; unsigned char value; char flags; char *text; }; #define M_EQ 0 /* mask and return true if equal */ #define M_NE 1 /* mask and return true if not equal */ #define TRUE 2 /* don't read config, always true */ struct pci_driver intel82378_device = { probe1, intel_attach, 0x04848086, 0, "intel 82378IB pci-isa bridge", return0 }; struct pci_driver intel82424_device = { probe1, intel_82424zx_attach, 0x04838086, 0, "intel 82424ZX cache dram controller", return0 }; struct pci_driver intel82375_device = { probe1, intel_attach, 0x04828086, 0, "intel 82375EB pci-eisa bridge", return0 }; struct pci_driver intel82434_device = { probe1, intel_82434lx_attach, 0x04a38086, 0, "intel 82434LX pci cache memory controller", return0 }; struct condmsg conf82424zx[] = { { 0x00, 0x00, 0x00, TRUE, "\tCPU: " }, { 0x50, 0xe0, 0x00, M_EQ, "486DX" }, { 0x50, 0xe0, 0x20, M_EQ, "486SX" }, { 0x50, 0xe0, 0x40, M_EQ, "486DX2 or 486DX4" }, { 0x50, 0xe0, 0x80, M_EQ, "Overdrive (writeback)" }, { 0x00, 0x00, 0x00, TRUE, ", bus=" }, { 0x50, 0x03, 0x00, M_EQ, "25MHz" }, { 0x50, 0x03, 0x01, M_EQ, "33MHz" }, { 0x53, 0x01, 0x01, TRUE, ", CPU->Memory posting "}, { 0x53, 0x01, 0x00, M_EQ, "OFF" }, { 0x53, 0x01, 0x01, M_EQ, "ON" }, { 0x56, 0x30, 0x00, M_NE, "\t\nWarning:" }, { 0x56, 0x20, 0x00, M_NE, " NO cache parity!" }, { 0x56, 0x10, 0x00, M_NE, " NO DRAM parity!" }, { 0x55, 0x04, 0x04, M_EQ, "\nWarning: refresh OFF! " }, { 0x00, 0x00, 0x00, TRUE, "\t\nCache: " }, { 0x52, 0x01, 0x00, M_EQ, "None" }, { 0x52, 0xc1, 0x01, M_EQ, "64KB" }, { 0x52, 0xc1, 0x41, M_EQ, "128KB" }, { 0x52, 0xc1, 0x81, M_EQ, "256KB" }, { 0x52, 0xc1, 0xc1, M_EQ, "512KB" }, { 0x52, 0x03, 0x01, M_EQ, " writethrough" }, { 0x52, 0x03, 0x03, M_EQ, " writeback" }, { 0x52, 0x01, 0x01, M_EQ, ", cache clocks=" }, { 0x52, 0x05, 0x01, M_EQ, "3-1-1-1" }, { 0x52, 0x05, 0x05, M_EQ, "2-1-1-1" }, { 0x00, 0x00, 0x00, TRUE, "\t\nDRAM:" }, { 0x55, 0x43, 0x00, M_NE, " page mode" }, { 0x55, 0x02, 0x02, M_EQ, " code fetch" }, { 0x55, 0x43, 0x43, M_EQ, "," }, { 0x55, 0x43, 0x42, M_EQ, " and" }, { 0x55, 0x40, 0x40, M_EQ, " read" }, { 0x55, 0x03, 0x03, M_EQ, " and" }, { 0x55, 0x43, 0x41, M_EQ, " and" }, { 0x55, 0x01, 0x01, M_EQ, " write" }, { 0x55, 0x43, 0x00, M_NE, "," }, { 0x00, 0x00, 0x00, TRUE, " memory clocks=" }, { 0x55, 0x20, 0x00, M_EQ, "X-2-2-2" }, { 0x55, 0x20, 0x20, M_EQ, "X-1-2-1" }, { 0x00, 0x00, 0x00, TRUE, "\t\nPCI: CPU->PCI posting " }, { 0x53, 0x02, 0x02, M_EQ, "ON" }, { 0x53, 0x02, 0x00, M_EQ, "OFF" }, { 0x00, 0x00, 0x00, TRUE, ", CPU->PCI burst mode " }, { 0x54, 0x02, 0x02, M_EQ, "ON" }, { 0x54, 0x02, 0x00, M_EQ, "OFF" }, { 0x00, 0x00, 0x00, TRUE, ", PCI->Mem. posting " }, { 0x54, 0x01, 0x01, M_EQ, "ON" }, { 0x54, 0x01, 0x00, M_EQ, "OFF" }, { 0x00, 0x00, 0x00, TRUE, "\n" }, /* end marker */ { 0 } }; struct condmsg conf82434lx[] = { { 0x00, 0x00, 0x00, TRUE, "\tCPU: " }, { 0x50, 0xe0, 0x80, M_EQ, "Pentium" }, { 0x50, 0xe0, 0x80, M_NE, "???" }, { 0x50, 0x02, 0x00, M_EQ, ", ???MHz" }, { 0x50, 0x03, 0x02, M_EQ, ", 60MHz" }, { 0x50, 0x03, 0x03, M_EQ, ", 66MHz" }, { 0x50, 0x04, 0x00, M_EQ, " (primary cache OFF)" }, { 0x53, 0x01, 0x01, TRUE, ", CPU->Memory posting "}, { 0x53, 0x01, 0x00, M_EQ, "OFF" }, { 0x53, 0x01, 0x01, M_NE, "ON" }, { 0x53, 0x04, 0x00, M_NE, ", read around write"}, { 0x71, 0xc0, 0x00, M_NE, "\t\nWarning: NO cache parity!" }, { 0x57, 0x20, 0x00, M_NE, "\t\nWarning: NO DRAM parity!" }, { 0x55, 0x01, 0x01, M_EQ, "\t\nWarning: refresh OFF! " }, { 0x00, 0x00, 0x00, TRUE, "\t\nCache: " }, { 0x52, 0x01, 0x00, M_EQ, "None" }, { 0x52, 0x81, 0x01, M_EQ, "" }, { 0x52, 0xc1, 0x81, M_EQ, "256KB" }, { 0x52, 0xc1, 0xc1, M_EQ, "512KB" }, { 0x52, 0x03, 0x01, M_EQ, " writethrough" }, { 0x52, 0x03, 0x03, M_EQ, " writeback" }, { 0x52, 0x01, 0x01, M_EQ, ", cache clocks=" }, { 0x52, 0x20, 0x00, M_EQ, "3-2-2-2/4-2-2-2" }, { 0x52, 0x20, 0x00, M_NE, "3-1-1-1" }, { 0x00, 0x00, 0x00, TRUE, "\t\nDRAM:" }, { 0x57, 0x10, 0x00, M_EQ, " page mode" }, { 0x00, 0x00, 0x00, TRUE, " memory clocks=" }, { 0x57, 0xc0, 0x00, M_EQ, "X-4-4-4 (70ns)" }, { 0x57, 0xc0, 0x40, M_EQ, "X-4-4-4/X-3-3-3 (60ns)" }, { 0x57, 0xc0, 0x80, M_EQ, "???" }, { 0x57, 0xc0, 0xc0, M_EQ, "X-3-3-3 (50ns)" }, { 0x00, 0x00, 0x00, TRUE, "\t\nPCI: CPU->PCI posting " }, { 0x53, 0x02, 0x02, M_EQ, "ON" }, { 0x53, 0x02, 0x00, M_EQ, "OFF" }, { 0x00, 0x00, 0x00, TRUE, ", CPU->PCI burst mode " }, { 0x54, 0x02, 0x00, M_NE, "ON" }, { 0x54, 0x02, 0x00, M_EQ, "OFF" }, { 0x00, 0x00, 0x00, TRUE, ", PCI->Memory posting " }, { 0x54, 0x01, 0x00, M_NE, "ON" }, { 0x54, 0x01, 0x00, M_EQ, "OFF" }, { 0x54, 0x04, 0x00, TRUE, ", PCI clocks=" }, { 0x54, 0x04, 0x00, M_EQ, "2-2-2-2" }, { 0x54, 0x04, 0x00, M_NE, "2-1-1-1" }, { 0x00, 0x00, 0x00, TRUE, "\n" }, /* end marker */ { 0 } }; int return0(int unit) { return (0); } int probe1(pcici_t config_id) { return (1); } static char confread (pcici_t config_id, int port) { unsigned long portw = port & -3; unsigned long ports = (port - portw) << 3; unsigned long l = pci_conf_read (config_id, portw); return (l >> ports); } static void writeconfig(pcici_t config_id, struct condmsg *tbl) { while (tbl->text) { int cond = 0; if (tbl->flags == TRUE) { cond = 1; } else { unsigned char v = (unsigned char) confread(config_id, tbl->port); switch (tbl->flags) { case M_EQ: if ((v & tbl->mask) == tbl->value) cond = 1; break; case M_NE: if ((v & tbl->mask) != tbl->value) cond = 1; break; default: } } if (cond) printf ("%s", tbl->text); tbl++; } } int intel_attach(pcici_t config_id, pcidi_t type) { - printf (" [40] %x [50] %x [54] %x\n", + printf (" [40] %lx [50] %lx [54] %lx\n", pci_conf_read (config_id, 0x40), pci_conf_read (config_id, 0x50), pci_conf_read (config_id, 0x54)); return(0); } int intel_82424zx_attach(pcici_t config_id, pcidi_t type) { writeconfig (config_id, conf82424zx); return (0); } int intel_82434lx_attach(pcici_t config_id, pcidi_t type) { writeconfig (config_id, conf82424zx); return (0); } diff --git a/sys/i386/pci/pcibios.h b/sys/i386/pci/pcibios.h index 76f242f941b2..a5cf491d9862 100644 --- a/sys/i386/pci/pcibios.h +++ b/sys/i386/pci/pcibios.h @@ -1,114 +1,139 @@ /************************************************************************** ** -** $Id: pcibios.h,v 2.0.0.1 94/08/18 23:05:36 wolf Exp $ +** $Id: pcibios.h,v 1.2 1994/09/01 02:01:45 se Exp $ ** ** #define for pci-bus bios functions. ** ** 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. ** **------------------------------------------------------------------------- ** -** $Log: pcibios.h,v $ +** $Log: pcibios.h,v $ + * Revision 1.2 1994/09/01 02:01:45 se + * Submitted by: Wolfgang Stanglmeier + * Merged in changes required for NetBSD support (by mycroft@gnu.ai.mit.edu) + * and support for multiple NCR chips. + * ** Revision 2.0.0.1 94/08/18 23:05:36 wolf ** ** Copyright message. ** New function: pci_last_bus(). ** Symbolic names for pci configuration space registers. ** ** Revision 2.0 94/07/10 15:53:32 wolf ** FreeBSD release. ** ** Revision 1.0 94/06/07 20:02:23 wolf ** Beta release. ** *************************************************************************** */ #ifndef __PCIBIOS_H__ #define __PCIBIOS_H__ /* ** the availability of a pci bus. ** configuration mode (1 or 2) ** 0 if no pci bus found. */ int pci_conf_mode (void); /* ** The number of the last available pci bus. */ int pci_last_bus (void); /* ** get a "ticket" for accessing a pci device ** configuration space. */ pcici_t pcitag (unsigned char bus, unsigned char device, unsigned char func); /* ** read or write the configuration space. */ u_long pci_conf_read (pcici_t tag, u_long reg ); void pci_conf_write (pcici_t tag, u_long reg, u_long data); /* ** Names for PCI configuration space registers. ** Copied from pcireg.h */ #define PCI_ID_REG 0x00 #define PCI_COMMAND_STATUS_REG 0x04 #define PCI_COMMAND_MEM_ENABLE 0x00000002 +#define PCI_CLASS_REV_REG 0x08 +#define PCI_MAJCLASS_OF(x) (((x) >> 24) & 0xff) +#define PCI_MINCLASS_OF(x) (((x) >> 16) & 0xff) +#define PCI_PROGINT_OF(x) (((x) >> 8) & 0xff) +#define PCI_REV_OF(x) ((x) & 0xff) +enum pci_majclass { PCI_MJC_OLD = 0, PCI_MJC_STOR, PCI_MJC_NET, + PCI_MJC_DISPLAY, PCI_MJC_MEDIA, PCI_MJC_MEM, + PCI_MJC_BRIDGE }; +enum pci_old_minclass { PCI_MIN_OLD = 0, PCI_MIN_OVGA }; +enum pci_stor_minclass { PCI_MIN_SCSI = 0, PCI_MIN_IDE, PCI_MIN_FLOP, + PCI_MIN_IPI, PCI_MIN_OSTOR }; +enum pci_net_minclass { PCI_MIN_ETHER = 0, PCI_MIN_TOKEN, PCI_MIN_FDDI, + PCI_MIN_ONET }; +enum pci_disp_minclass { PCI_MIN_VGA = 0, PCI_MIN_XGA, PCI_MIN_ODISP }; +enum pci_media_minclass { PCI_MIN_VIDEO = 0, PCI_MIN_AUDIO, PCI_MIN_OMEDIA }; +enum pci_mem_minclass { PCI_MIN_RAM = 0, PCI_MIN_FLASH, PCI_MIN_OMEM }; +enum pci_bridge_minclass { PCI_MIN_HOST = 0, PCI_MIN_ISA, PCI_MIN_EISA, + PCI_MIN_MC, PCI_MIN_PCI, PCI_MIN_PCMCIA, + PCI_MIN_OBRIDGE }; + #define PCI_MAP_REG_START 0x10 #define PCI_MAP_REG_END 0x28 #define PCI_MAP_MEMORY 0x00000000 #define PCI_MAP_IO 0x00000001 #define PCI_MAP_MEMORY_TYPE_32BIT 0x00000000 #define PCI_MAP_MEMORY_TYPE_32BIT_1M 0x00000002 #define PCI_MAP_MEMORY_TYPE_64BIT 0x00000004 #define PCI_MAP_MEMORY_TYPE_MASK 0x00000006 #define PCI_MAP_MEMORY_CACHABLE 0x00000008 #define PCI_MAP_MEMORY_ADDRESS_MASK 0xfffffff0 #define PCI_INTERRUPT_REG 0x3c #define PCI_INTERRUPT_PIN_MASK 0x0000ff00 #define PCI_INTERRUPT_PIN_EXTRACT(x) ((((x) & PCI_INTERRUPT_PIN_MASK) >> 8) & 0xff) #define PCI_INTERRUPT_LINE_MASK 0x000000ff #define PCI_INTERRUPT_LINE_EXTRACT(x) ((((x) & PCI_INTERRUPT_LINE_MASK) >> 0) & 0xff) #endif diff --git a/sys/pci/pci.c b/sys/pci/pci.c index f07228452a7c..93b2d17db16b 100644 --- a/sys/pci/pci.c +++ b/sys/pci/pci.c @@ -1,598 +1,620 @@ /************************************************************************** ** -** $Id: pci.c,v 2.0.0.8 94/08/21 19:57:39 wolf Exp $ +** $Id: pci.c,v 1.2 1994/09/01 02:01:34 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. ** **------------------------------------------------------------------------- ** -** $Log: pci.c,v $ +** $Log: pci.c,v $ + * Revision 1.2 1994/09/01 02:01:34 se + * Submitted by: Wolfgang Stanglmeier + * Merged in changes required for NetBSD support (by mycroft@gnu.ai.mit.edu) + * and support for multiple NCR chips. + * ** Revision 2.0.0.8 94/08/21 19:57:39 wolf ** Unneeded declarations removed (FreeBSD2.0) ** ** Revision 2.0.0.7 94/08/21 19:25:54 wolf ** pci_intr simplified. ** new not_supported() function. ** Vendor and device ids moved into tables. ** ** Revision 2.0.0.6 94/08/18 22:58:23 wolf ** Symbolic names for pci configuration space registers. ** last_device: from configuration mode ** last_bus: from pcibios. ** PCI_MAX_DPI: changed to 4 (settable by config) ** interrupt configuration by line or pin ** ** Revision 2.0.0.5 94/08/11 19:04:10 wolf ** display of interrupt line configuration register. ** ** Revision 2.0.0.4 94/08/01 20:36:28 wolf ** Tiny clean up. ** ** Revision 2.0.0.3 94/08/01 18:52:33 wolf ** New vendor entry: S3. ** Scan pci busses #0..#255 as default. ** Number of scanned busses and devices settable as option. ** Show these numbers before starting the scan. ** ** Revision 2.0.0.2 94/07/27 09:27:19 wolf ** New option PCI_QUIET: suppress log messages. ** ** Revision 2.0.0.1 94/07/19 19:06:44 wolf ** New vendor entry: MATROX ** ** Revision 2.0 94/07/10 15:53:29 wolf ** FreeBSD release. ** ** Revision 1.0 94/06/07 20:02:19 wolf ** Beta release. ** *************************************************************************** */ #include #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*/ /*======================================================== ** ** #includes and declarations ** **======================================================== */ -#include -#include -#include -#include +#include +#include +#include #include #include #include #include #include #include #include #include char ident_pci_c[] = - "\n$Id: pci.c,v 2.0.0.8 94/08/21 19:57:39 wolf Exp $\n" + "\n$Id: pci.c,v 1.2 1994/09/01 02:01:34 se Exp $\n" "Copyright (c) 1994, Wolfgang Stanglmeier\n"; /* ** Function prototypes missing in system headers */ -extern int printf(); -extern int ffs(); #if ! (__FreeBSD__ >= 2) extern pmap_t pmap_kernel(void); #endif /*======================================================== ** ** Autoconfiguration (of isa bus) ** **======================================================== */ /* ** per device (interrupt) data structure. */ static struct { u_short number; u_short isanum; struct { int (*proc)(int dev); dev_t unit; } vector[PCI_MAX_DPI]; } pcidata [NPCI]; /* ** 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); } /* ** 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" }; /*======================================================== ** ** Interrupt forward from isa to pci devices. ** **======================================================== */ void pciintr (int unit) { u_short i; if (unit >= NPCI) return; for (i=0; ipd_driver; dvp++) { - if (drp->device_id == type) break; + for (dvp = pci_devtab; dvp->pd_device_id; dvp++) { + if (dvp->pd_device_id == type) break; }; - -#ifdef PCI_QUIET - if (!drp) continue; -#endif - printf ("on pci%d:%d ", bus, device); + drp = dvp->pd_driver; + + if (!dvp->pd_device_id) { + int data = pci_conf_read(tag, PCI_CLASS_REV_REG); + enum pci_majclass class = PCI_MAJCLASS_OF(data); + vm_offset_t va; + vm_offset_t pa; + int reg; + + switch(class) { + case PCI_MJC_OLD: + if(PCI_MINCLASS_OF(data) != PCI_MIN_OVGA) + break; + case PCI_MJC_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 %lx\n", + bus, device, (u_long)pa); + + } + continue; + default: #ifndef PCI_QUIET + printf("pci%d:%d: ", bus, device); + not_supported (tag, type); +#endif + } + } + if (!drp) { - not_supported (tag, type); + if(dvp->pd_flags & PDF_LOADABLE) { + printf("%s: loadable device on pci%d:%d\n", + dvp->pd_name, bus, device); + } continue; - }; -#endif + } /* ** found it. ** probe returns the device unit. */ - - printf ("<%s>", drp -> vendor); - unit = (*drp->probe) (tag); if (unit<0) { - printf (" probe failed.\n"); + printf ("%s <%s>: probe failed on pci%d:%d\n", + drp->name, drp->vendor, bus, device); continue; }; + if (drp->name) { + printf ("%s%d <%s>", drp->name, unit, drp->vendor); + } else { + printf ("pci%d: <%s>", bus, drp->vendor); + } + /* ** install interrupts */ data = pci_conf_read (tag, PCI_INTERRUPT_REG); intpin = PCI_INTERRUPT_PIN_EXTRACT(data); if (intpin) { int idx=NPCI; /* ** Usage of int line register (if set by bios) ** Matt Thomas */ isanum = PCI_INTERRUPT_LINE_EXTRACT(data); if (isanum) { printf (" il=%d", isanum); for (idx = 0; idx < NPCI; idx++) { if (pcidata[idx].isanum == isanum) break; - }; - }; + } + } /* ** Or believe to the interrupt pin register. */ if (idx >= NPCI) idx = intpin-1; /* ** And install the interrupt. */ if (idxintr; pcidata[idx].vector[entry].unit = unit; entry++; }; printf (" isa=%d [%d]",pcidata[idx].isanum, entry); pcidata[idx].number=entry; } else { printf (" not installed"); - }; - }; + } + } /* ** 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); + printf (" on pci%d:%d\n", bus, device); + /* ** attach device ** may produce additional log messages, ** i.e. when installing subdevices. */ - - printf (" as %s%d\n", drp->name,unit); (void) (*drp->attach) (tag); + } - }; - - printf ("pci uses physical addresses from %x to %x\n", - PCI_PMEM_START, pci_paddr); +#ifndef PCI_QUIET + printf ("pci uses physical addresses from %lx to %lx\n", + (u_long)PCI_PMEM_START, (u_long)pci_paddr); +#endif } /*----------------------------------------------------------------------- ** ** Map device into port space. ** ** PCI-Specification: 6.2.5.1: address maps ** **----------------------------------------------------------------------- */ extern vm_map_t kernel_map; int pci_map_port (pcici_t tag, u_long reg, u_short* pa) { /* ** @MAPIO@ not yet implemented. */ return (ENOSYS); } /*----------------------------------------------------------------------- ** ** 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, result; vm_size_t vsize; vm_offset_t vaddr; /* ** sanity check */ if (reg <= PCI_MAP_REG_START || reg >= PCI_MAP_REG_END || (reg & 3)) return (EINVAL); /* ** 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 */ return (EINVAL); }; /* ** mask out the type, ** and round up to a page size */ vsize = round_page (-(data & PCI_MAP_MEMORY_ADDRESS_MASK)); - printf (" memory size=0x%x", vsize); - if (!vsize) return (EINVAL); - /* - ** try to map device to virtual space - */ - - 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 (ENOMEM); - }; - /* ** align physical address to virtual size */ if (data = pci_paddr % vsize) pci_paddr += vsize - data; + vaddr = pmap_mapdev (pci_paddr, vsize); + +#if 0 /* ** display values. */ - printf (" virtual=0x%x physical=0x%x\n", vaddr, pci_paddr); + printf (" virtual=0x%lx physical=0x%lx\n", (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); - /* - ** map physical - */ - - while (vsize >= NBPG) { - pmap_enter (pmap_kernel(), vaddr, pci_paddr, - VM_PROT_READ|VM_PROT_WRITE, TRUE); - vaddr += NBPG; - pci_paddr += NBPG; - vsize -= NBPG; - }; - return (0); } struct vt { u_short ident; char* name; }; struct dt { u_long ident; char* name; }; static struct vt VendorTable[] = { {0x1002, "ATI TECHNOLOGIES INC"}, {0x1011, "DIGITAL EQUIPMENT COMPANY"}, {0x101A, "NCR"}, {0x102B, "MATROX"}, {0x1045, "OPTI"}, {0x5333, "S3 INC."}, {0x8086, "INTEL CORPORATION"}, {0,0} }; static struct dt DeviceTable[] = { {0x04848086, " 82378IB pci-isa bridge"}, {0x04838086, " 82424ZX cache dram controller"}, {0x04828086, " 82375EB pci-eisa bridge"}, {0x04A38086, " 82434LX pci cache memory controller"}, {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; struct dt * dp; /* ** lookup the names. */ for (vp=VendorTable; vp->ident; vp++) if (vp->ident == (type & 0xffff)) break; for (dp=DeviceTable; dp->ident; dp++) if (dp->ident == type) break; /* ** and display them. */ if (vp->ident) printf (vp->name); - else printf ("vendor=%x", type & 0xffff); + else printf ("vendor=%lx", type & 0xffff); if (dp->ident) printf (dp->name); - else printf (", device=%x", type >> 16); + else printf (", device=%lx", type >> 16); + + data = pci_conf_read(tag, PCI_CLASS_REV_REG); + if (PCI_MAJCLASS_OF(data) < sizeof(majclasses) / sizeof(majclasses[0])) + printf(", class=%s", majclasses[PCI_MAJCLASS_OF(data)]); printf (" [not supported]\n"); for (reg=PCI_MAP_REG_START; reg