The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/pci/vga_pci.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*      $NetBSD: vga_pci.c,v 1.23 2003/06/29 22:30:29 fvdl Exp $        */
    2 
    3 /*
    4  * Copyright (c) 1995, 1996 Carnegie-Mellon University.
    5  * All rights reserved.
    6  *
    7  * Author: Chris G. Demetriou
    8  * 
    9  * Permission to use, copy, modify and distribute this software and
   10  * its documentation is hereby granted, provided that both the copyright
   11  * notice and this permission notice appear in all copies of the
   12  * software, derivative works or modified versions, and any portions
   13  * thereof, and that both notices appear in supporting documentation.
   14  * 
   15  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" 
   16  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND 
   17  * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
   18  * 
   19  * Carnegie Mellon requests users of this software to return to
   20  *
   21  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
   22  *  School of Computer Science
   23  *  Carnegie Mellon University
   24  *  Pittsburgh PA 15213-3890
   25  *
   26  * any improvements or extensions that they make and grant Carnegie the
   27  * rights to redistribute these changes.
   28  */
   29 
   30 #include <sys/cdefs.h>
   31 __KERNEL_RCSID(0, "$NetBSD: vga_pci.c,v 1.23 2003/06/29 22:30:29 fvdl Exp $");
   32 
   33 #include <sys/param.h>
   34 #include <sys/systm.h>
   35 #include <sys/kernel.h>
   36 #include <sys/device.h>
   37 #include <sys/malloc.h>
   38 
   39 #include <dev/pci/pcireg.h>
   40 #include <dev/pci/pcivar.h>
   41 #include <dev/pci/pcidevs.h>
   42 #include <dev/pci/pciio.h>
   43 
   44 #include <dev/ic/mc6845reg.h>
   45 #include <dev/ic/pcdisplayvar.h>
   46 #include <dev/ic/vgareg.h>
   47 #include <dev/ic/vgavar.h>
   48 #include <dev/pci/vga_pcivar.h>
   49 
   50 #include <dev/isa/isareg.h>     /* For legacy VGA address ranges */
   51 
   52 #include <dev/wscons/wsconsio.h>
   53 #include <dev/wscons/wsdisplayvar.h>
   54 
   55 #define NBARS           6       /* number of PCI BARs */
   56 
   57 struct vga_bar {
   58         bus_addr_t vb_base;
   59         bus_size_t vb_size;
   60         pcireg_t vb_type;
   61         int vb_flags;
   62 };
   63 
   64 struct vga_pci_softc {
   65         struct vga_softc sc_vga;
   66 
   67         pci_chipset_tag_t sc_pc;
   68         pcitag_t sc_pcitag;
   69 
   70         struct vga_bar sc_bars[NBARS];
   71         struct vga_bar sc_rom;
   72 };
   73 
   74 int     vga_pci_match(struct device *, struct cfdata *, void *);
   75 void    vga_pci_attach(struct device *, struct device *, void *);
   76 static int vga_pci_lookup_quirks(struct pci_attach_args *);
   77 
   78 CFATTACH_DECL(vga_pci, sizeof(struct vga_pci_softc),
   79     vga_pci_match, vga_pci_attach, NULL, NULL);
   80 
   81 int     vga_pci_ioctl(void *, u_long, caddr_t, int, struct proc *);
   82 paddr_t vga_pci_mmap(void *, off_t, int);
   83 
   84 const struct vga_funcs vga_pci_funcs = {
   85         vga_pci_ioctl,
   86         vga_pci_mmap,
   87 };
   88 
   89 static const struct {
   90         int id;
   91         int quirks;
   92 } vga_pci_quirks[] = {
   93         {PCI_ID_CODE(PCI_VENDOR_SILMOTION, PCI_PRODUCT_SILMOTION_SM712),
   94          VGA_QUIRK_NOFASTSCROLL},
   95 };
   96 
   97 static const struct {
   98         int vid;
   99         int quirks;
  100 } vga_pci_vquirks[] = {
  101         {PCI_VENDOR_ATI, VGA_QUIRK_ONEFONT},
  102 };
  103 
  104 static int
  105 vga_pci_lookup_quirks(pa)
  106         struct pci_attach_args *pa;
  107 {
  108         int i;
  109 
  110         for (i = 0; i < sizeof(vga_pci_quirks) / sizeof (vga_pci_quirks[0]);
  111              i++) {
  112                 if (vga_pci_quirks[i].id == pa->pa_id)
  113                         return (vga_pci_quirks[i].quirks);
  114         }
  115         for (i = 0; i < sizeof(vga_pci_vquirks) / sizeof (vga_pci_vquirks[0]);
  116              i++) {
  117                 if (vga_pci_vquirks[i].vid == PCI_VENDOR(pa->pa_id))
  118                         return (vga_pci_vquirks[i].quirks);
  119         }
  120         return (0);
  121 }
  122 
  123 int
  124 vga_pci_match(struct device *parent, struct cfdata *match, void *aux)
  125 {
  126         struct pci_attach_args *pa = aux;
  127         int potential;
  128 
  129         potential = 0;
  130 
  131         /*
  132          * If it's prehistoric/vga or display/vga, we might match.
  133          * For the console device, this is jut a sanity check.
  134          */
  135         if (PCI_CLASS(pa->pa_class) == PCI_CLASS_PREHISTORIC &&
  136             PCI_SUBCLASS(pa->pa_class) == PCI_SUBCLASS_PREHISTORIC_VGA)
  137                 potential = 1;
  138         if (PCI_CLASS(pa->pa_class) == PCI_CLASS_DISPLAY &&
  139              PCI_SUBCLASS(pa->pa_class) == PCI_SUBCLASS_DISPLAY_VGA)
  140                 potential = 1;
  141 
  142         if (!potential)
  143                 return (0);
  144 
  145         /* check whether it is disabled by firmware */
  146         if ((pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG)
  147             & (PCI_COMMAND_IO_ENABLE | PCI_COMMAND_MEM_ENABLE))
  148             != (PCI_COMMAND_IO_ENABLE | PCI_COMMAND_MEM_ENABLE))
  149                 return (0);
  150 
  151         /* If it's the console, we have a winner! */
  152         if (vga_is_console(pa->pa_iot, WSDISPLAY_TYPE_PCIVGA))
  153                 return (1);
  154 
  155         /*
  156          * If we might match, make sure that the card actually looks OK.
  157          */
  158         if (!vga_common_probe(pa->pa_iot, pa->pa_memt))
  159                 return (0);
  160 
  161         return (1);
  162 }
  163 
  164 void
  165 vga_pci_attach(struct device *parent, struct device *self, void *aux)
  166 {
  167         struct vga_pci_softc *psc = (void *) self;
  168         struct vga_softc *sc = &psc->sc_vga;
  169         struct pci_attach_args *pa = aux;
  170         char devinfo[256];
  171         int bar, reg;
  172 
  173         psc->sc_pc = pa->pa_pc;
  174         psc->sc_pcitag = pa->pa_tag;
  175 
  176         pci_devinfo(pa->pa_id, pa->pa_class, 0, devinfo);
  177         printf(": %s (rev. 0x%02x)\n", devinfo,
  178             PCI_REVISION(pa->pa_class));
  179 
  180         /*
  181          * Gather info about all the BARs.  These are used to allow
  182          * the X server to map the VGA device.
  183          */
  184         for (bar = 0; bar < NBARS; bar++) {
  185                 reg = PCI_MAPREG_START + (bar * 4);
  186                 if (!pci_mapreg_probe(psc->sc_pc, psc->sc_pcitag, reg,
  187                                       &psc->sc_bars[bar].vb_type)) {
  188                         /* there is no valid mapping register */
  189                         continue;
  190                 }
  191                 if (PCI_MAPREG_TYPE(psc->sc_bars[bar].vb_type) ==
  192                     PCI_MAPREG_TYPE_IO) {
  193                         /* Don't bother fetching I/O BARs. */
  194                         continue;
  195                 }
  196                 if (PCI_MAPREG_MEM_TYPE(psc->sc_bars[bar].vb_type) ==
  197                     PCI_MAPREG_MEM_TYPE_64BIT) {
  198                         /* XXX */
  199                         printf("%s: WARNING: ignoring 64-bit BAR @ 0x%02x\n",
  200                             sc->sc_dev.dv_xname, reg);
  201                         bar++;
  202                         continue;
  203                 }
  204                 if (pci_mapreg_info(psc->sc_pc, psc->sc_pcitag, reg,
  205                      psc->sc_bars[bar].vb_type,
  206                      &psc->sc_bars[bar].vb_base,
  207                      &psc->sc_bars[bar].vb_size,
  208                      &psc->sc_bars[bar].vb_flags))
  209                         printf("%s: WARNING: strange BAR @ 0x%02x\n",
  210                                sc->sc_dev.dv_xname, reg);
  211         }
  212 
  213         /* XXX Expansion ROM? */
  214 
  215         vga_common_attach(sc, pa->pa_iot, pa->pa_memt, WSDISPLAY_TYPE_PCIVGA,
  216                           vga_pci_lookup_quirks(pa), &vga_pci_funcs);
  217 }
  218 
  219 int
  220 vga_pci_cnattach(bus_space_tag_t iot, bus_space_tag_t memt, 
  221     pci_chipset_tag_t pc, int bus, int device, int function)
  222 {
  223 
  224         return (vga_cnattach(iot, memt, WSDISPLAY_TYPE_PCIVGA, 0));
  225 }
  226 
  227 int
  228 vga_pci_ioctl(void *v, u_long cmd, caddr_t data, int flag, struct proc *p)
  229 {
  230         struct vga_config *vc = v;
  231         struct vga_pci_softc *psc = (void *) vc->softc;
  232 
  233         switch (cmd) {
  234         /* PCI config read/write passthrough. */
  235         case PCI_IOC_CFGREAD:
  236         case PCI_IOC_CFGWRITE:
  237                 return (pci_devioctl(psc->sc_pc, psc->sc_pcitag,
  238                     cmd, data, flag, p));
  239 
  240         default:
  241                 return (EPASSTHROUGH);
  242         }
  243 }
  244 
  245 paddr_t
  246 vga_pci_mmap(void *v, off_t offset, int prot)
  247 {
  248         struct vga_config *vc = v;
  249         struct vga_pci_softc *psc = (void *) vc->softc;
  250         struct vga_bar *vb;
  251         int bar;
  252 
  253         for (bar = 0; bar < NBARS; bar++) {
  254                 vb = &psc->sc_bars[bar];
  255                 if (vb->vb_size == 0)
  256                         continue;
  257                 if (offset >= vb->vb_base &&
  258                     offset < (vb->vb_base + vb->vb_size)) {
  259                         /* XXX This the right thing to do with flags? */
  260                         return (bus_space_mmap(vc->hdl.vh_memt, vb->vb_base,
  261                             (offset - vb->vb_base), prot, vb->vb_flags));
  262                 }
  263         }
  264 
  265         /* XXX Expansion ROM? */
  266 
  267         /*
  268          * Allow mmap access to the legacy ISA hole.  This is where
  269          * the legacy video BIOS will be located, and also where
  270          * the legacy VGA display buffer is located.
  271          *
  272          * XXX Security implications, here?
  273          */
  274         if (offset >= IOM_BEGIN && offset < IOM_END)
  275                 return (bus_space_mmap(vc->hdl.vh_memt, IOM_BEGIN,
  276                     (offset - IOM_BEGIN), prot, 0));
  277 
  278         /* Range not found. */
  279         return (-1);
  280 }

Cache object: cb5771c2f48643fdf91110268fd34982


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.