File: [local] / sys / arch / macppc / pci / vgafb_pci.c (download)
Revision 1.1.1.1 (vendor branch), Tue Mar 4 16:07:18 2008 UTC (16 years, 3 months ago) by nbrk
Branch: OPENBSD_4_2_BASE, MAIN
CVS Tags: jornada-partial-support-wip, HEAD Changes since 1.1: +0 -0 lines
Import of OpenBSD 4.2 release kernel tree with initial code to support
Jornada 720/728, StrongARM 1110-based handheld PC.
At this point kernel roots on NFS and boots into vfs_mountroot() and traps.
What is supported:
- glass console, Jornada framebuffer (jfb) works in 16bpp direct color mode
(needs some palette tweaks for non black/white/blue colors, i think)
- saic, SA11x0 interrupt controller (needs cleanup)
- sacom, SA11x0 UART (supported only as boot console for now)
- SA11x0 GPIO controller fully supported (but can't handle multiple interrupt
handlers on one gpio pin)
- sassp, SSP port on SA11x0 that attaches spibus
- Jornada microcontroller (jmcu) to control kbd, battery, etc throught
the SPI bus (wskbd attaches on jmcu, but not tested)
- tod functions seem work
- initial code for SA-1111 (chip companion) : this is TODO
Next important steps, i think:
- gpio and intc on sa1111
- pcmcia support for sa11x0 (and sa1111 help logic)
- REAL root on nfs when we have PCMCIA support (we may use any of supported pccard NICs)
- root on wd0! (using already supported PCMCIA-ATA)
|
/* $OpenBSD: vgafb_pci.c,v 1.18 2006/12/17 22:18:14 miod Exp $ */
/* $NetBSD: vga_pci.c,v 1.4 1996/12/05 01:39:38 cgd Exp $ */
/*
* Copyright (c) 1995, 1996 Carnegie-Mellon University.
* All rights reserved.
*
* Author: Chris G. Demetriou
*
* Permission to use, copy, modify and distribute this software and
* its documentation is hereby granted, provided that both the copyright
* notice and this permission notice appear in all copies of the
* software, derivative works or modified versions, and any portions
* thereof, and that both notices appear in supporting documentation.
*
* CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
* CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
* FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
*
* Carnegie Mellon requests users of this software to return to
*
* Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
* School of Computer Science
* Carnegie Mellon University
* Pittsburgh PA 15213-3890
*
* any improvements or extensions that they make and grant Carnegie the
* rights to redistribute these changes.
*/
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/device.h>
#include <sys/malloc.h>
#ifndef i386
#include <machine/autoconf.h>
#endif
#include <machine/pte.h>
#include <dev/cons.h>
#include <dev/pci/pcireg.h>
#include <dev/pci/pcivar.h>
#include <dev/pci/pcidevs.h>
#include <dev/wscons/wsconsio.h>
#include <dev/wscons/wsdisplayvar.h>
#include <dev/rasops/rasops.h>
#include <dev/wsfont/wsfont.h>
#include <arch/macppc/pci/vgafbvar.h>
#include <arch/macppc/pci/vgafb_pcivar.h>
#define PCI_VENDORID(x) ((x) & 0xFFFF)
#define PCI_CHIPID(x) (((x) >> 16) & 0xFFFF)
struct vgafb_pci_softc {
struct device sc_dev;
pcitag_t sc_pcitag; /* PCI tag, in case we need it. */
struct vgafb_config *sc_vc; /* VGA configuration */
};
int vgafb_pci_probe(struct pci_attach_args *pa, int id, u_int32_t *ioaddr,
u_int32_t *iosize, u_int32_t *memaddr, u_int32_t *memsize,
u_int32_t *cacheable, u_int32_t *mmioaddr, u_int32_t *mmiosize);
int vgafb_pci_match(struct device *, void *, void *);
void vgafb_pci_attach(struct device *, struct device *, void *);
paddr_t vgafbpcimmap(void *, off_t, int);
int vgafbpciioctl(void *, u_long, caddr_t, int, struct proc *);
struct cfattach vgafb_pci_ca = {
sizeof(struct vgafb_pci_softc), (cfmatch_t)vgafb_pci_match, vgafb_pci_attach,
};
pcitag_t vgafb_pci_console_tag;
struct vgafb_config vgafb_pci_console_vc;
#if 0
#define DEBUG_VGAFB
#endif
int
vgafb_pci_probe(struct pci_attach_args *pa, int id, u_int32_t *ioaddr,
u_int32_t *iosize, u_int32_t *memaddr, u_int32_t *memsize,
u_int32_t *cacheable, u_int32_t *mmioaddr, u_int32_t *mmiosize)
{
u_long addr;
u_int32_t size, tcacheable;
pci_chipset_tag_t pc = pa->pa_pc;
int retval;
int i;
*iosize = 0x0;
*memsize = 0x0;
*mmiosize = 0x0;
for (i = PCI_MAPREG_START; i <= PCI_MAPREG_PPB_END; i += 4) {
#ifdef DEBUG_VGAFB
printf("vgafb confread %x %x\n",
i, pci_conf_read(pc, pa->pa_tag, i));
#endif
/* need to check more than just two base addresses? */
if (PCI_MAPREG_TYPE(pci_conf_read(pc, pa->pa_tag, i)) ==
PCI_MAPREG_TYPE_IO) {
retval = pci_io_find(pc, pa->pa_tag, i,
&addr, &size);
if (retval != 0) {
continue;
}
#ifdef DEBUG_VGAFB
printf("vgafb_pci_probe: io %x addr %x size %x\n", i, addr, size);
#endif
if (*iosize == 0) {
*ioaddr = addr;
*iosize = size;
}
} else {
retval = pci_mem_find(pc, pa->pa_tag, i,
&addr, &size, &tcacheable);
if (retval != 0) {
continue;
}
#ifdef DEBUG_VGAFB
printf("vgafb_pci_probe: mem %x addr %x size %x\n", i, addr, size);
#endif
if (size == 0 || addr == 0) {
/* ignore this entry */
} else if (*memsize == 0) {
/*
* first memory slot found goes into memory,
* this is for the case of no mmio
*/
*memaddr = addr;
*memsize = size;
*cacheable = tcacheable;
} else {
/*
* Oh, we have a second 'memory'
* region, is this region the vga memory
* or mmio, we guess that memory is
* the larger of the two.
*/
if (*memaddr > size) {
/* this is the mmio */
*mmioaddr = addr;
/* ATI driver maps 0x80000 mmio, grr */
if (size < 0x80000) {
size = 0x80000;
}
*mmiosize = size;
} else {
/* this is the memory */
*mmioaddr = *memaddr;
*memaddr = addr;
*mmiosize = *memsize;
*memsize = size;
*cacheable = tcacheable;
/* ATI driver maps 0x80000 mmio, grr */
if (*mmiosize < 0x80000) {
*mmiosize = 0x80000;
}
}
}
}
}
#ifdef DEBUG_VGAFB
printf("vgafb_pci_probe: id %x ioaddr %x, iosize %x, memaddr %x,\n memsize %x, mmioaddr %x, mmiosize %x\n",
id, *ioaddr, *iosize, *memaddr, *memsize, *mmioaddr, *mmiosize);
#endif
if (*iosize == 0) {
if (id == 0) {
#ifdef powerpc
/* this is only used if on openfirmware system and
* the device does not have a iobase config register,
* eg CirrusLogic 5434 VGA. (they hardcode iobase to 0
* thus giving standard PC addresses for the registers)
*/
int s;
u_int32_t sizedata;
/*
* Open Firmware (yuck) shuts down devices before
* entering a program so we need to bring them back
* 'online' to respond to bus accesses... so far
* this is true on the power.4e.
*/
s = splhigh();
sizedata = pci_conf_read(pc, pa->pa_tag,
PCI_COMMAND_STATUS_REG);
sizedata |= (PCI_COMMAND_MASTER_ENABLE |
PCI_COMMAND_IO_ENABLE |
PCI_COMMAND_PARITY_ENABLE |
PCI_COMMAND_SERR_ENABLE);
pci_conf_write(pc, pa->pa_tag, PCI_COMMAND_STATUS_REG,
sizedata);
splx(s);
#endif
/* if this is the first card, allow it
* to be accessed in vga iospace
*/
*ioaddr = 0;
*iosize = 0x10000; /* 64k, good as any */
} else {
/* iospace not available, assume 640x480, pray */
*ioaddr = 0;
*iosize = 0;
}
}
#ifdef DEBUG_VGAFB
printf("vgafb_pci_probe: id %x ioaddr %x, iosize %x, memaddr %x,\n memsize %x, mmioaddr %x, mmiosize %x\n",
id, *ioaddr, *iosize, *memaddr, *memsize, *mmioaddr, *mmiosize);
#endif
/* io and mmio spaces are not required to attach */
if (/* *iosize == 0 || */ *memsize == 0 /* || *mmiosize == 0 */)
return (0);
return (1);
}
int
vgafb_pci_match(parent, match, aux)
struct device *parent;
void *match;
void *aux;
{
struct pci_attach_args *pa = aux;
int potential;
static int id = 0;
int myid;
myid = id;
potential = 0;
/*
* If it's prehistoric/vga or display/vga, we might match.
* For the console device, this is jut a sanity check.
*/
if (PCI_CLASS(pa->pa_class) == PCI_CLASS_PREHISTORIC &&
PCI_SUBCLASS(pa->pa_class) == PCI_SUBCLASS_PREHISTORIC_VGA)
potential = 1;
if (PCI_CLASS(pa->pa_class) == PCI_CLASS_DISPLAY &&
PCI_SUBCLASS(pa->pa_class) == PCI_SUBCLASS_DISPLAY_VGA)
potential = 1;
if (PCI_CLASS(pa->pa_class) == PCI_CLASS_DISPLAY &&
PCI_SUBCLASS(pa->pa_class) == PCI_SUBCLASS_DISPLAY_MISC)
potential = 1;
if (!potential)
return (0);
/* If it's the console, we have a winner! */
if (!bcmp(&pa->pa_tag, &vgafb_pci_console_tag, sizeof(pa->pa_tag))) {
id++;
return (1);
}
#ifdef DEBUG_VGAFB
{
int i;
pci_chipset_tag_t pc = pa->pa_pc;
for (i = 0x10; i < 0x24; i+=4) {
printf("vgafb confread %x %x\n",
i, pci_conf_read(pc, pa->pa_tag, i));
}
}
#endif
return (0);
}
void
vgafb_pci_attach(struct device *parent, struct device *self, void *aux)
{
struct pci_attach_args *pa = aux;
struct vgafb_pci_softc *sc = (struct vgafb_pci_softc *)self;
struct vgafb_config *vc;
u_int32_t memaddr, memsize, cacheable;
u_int32_t ioaddr, iosize;
u_int32_t mmioaddr, mmiosize;
int console;
static int id = 0;
int myid;
myid = id;
vgafb_pci_probe(pa, myid, &ioaddr, &iosize,
&memaddr, &memsize, &cacheable, &mmioaddr, &mmiosize);
console = (!bcmp(&pa->pa_tag, &vgafb_pci_console_tag, sizeof(pa->pa_tag)));
if (console)
vc = sc->sc_vc = &vgafb_pci_console_vc;
else {
vc = sc->sc_vc = (struct vgafb_config *)
malloc(sizeof(struct vgafb_config), M_DEVBUF, M_WAITOK);
/* set up bus-independent VGA configuration */
vgafb_common_setup(pa->pa_iot, pa->pa_memt, vc,
ioaddr, iosize, memaddr, memsize, mmioaddr, mmiosize);
}
vc->vc_mmap = vgafbpcimmap;
vc->vc_ioctl = vgafbpciioctl;
vc->membase = memaddr;
vc->memsize = memsize;
vc->mmiobase = mmioaddr;
vc->mmiosize = mmiosize;
sc->sc_pcitag = pa->pa_tag;
if (iosize == 0)
printf (", no io");
if (mmiosize != 0)
printf (", mmio");
printf("\n");
vgafb_wsdisplay_attach(self, vc, console);
id++;
}
void
vgafb_pci_console(bus_space_tag_t iot, u_int32_t ioaddr, u_int32_t iosize,
bus_space_tag_t memt, u_int32_t memaddr, u_int32_t memsize,
pci_chipset_tag_t pc, int bus, int device, int function)
{
struct vgafb_config *vc = &vgafb_pci_console_vc;
u_int32_t mmioaddr;
u_int32_t mmiosize;
static struct pci_attach_args spa;
struct pci_attach_args *pa = &spa;
/* for later recognition */
vgafb_pci_console_tag = pci_make_tag(pc, bus, device, function);
pa->pa_iot = iot;
pa->pa_memt = memt;
pa->pa_tag = vgafb_pci_console_tag;
/*
pa->pa_pc = XXX;
*/
/* XXX probe pci before pci bus config? */
mmioaddr =0;
mmiosize =0;
#if 0
vgafb_pci_probe(pa, 0, &ioaddr, &iosize,
&memaddr, &memsize, &cacheable, mmioaddr, mmiosize);
#endif
/* set up bus-independent VGA configuration */
vgafb_common_setup(iot, memt, vc,
ioaddr, iosize, memaddr, memsize, mmioaddr, mmiosize);
vgafb_cnattach(iot, memt, pc, bus, device, function);
vc->nscreens++;
}
int
vgafbpciioctl(void *v, u_long cmd, caddr_t data, int flag, struct proc *p)
{
struct vgafb_pci_softc *sc = v;
return (vgafb_ioctl(sc->sc_vc, cmd, data, flag, p));
}
paddr_t
vgafbpcimmap(void *v, off_t offset, int prot)
{
struct vgafb_pci_softc *sc = v;
return (vgafb_mmap(sc->sc_vc, offset, prot));
}
int
vgafb_alloc_screen(void *v, const struct wsscreen_descr *type, void **cookiep,
int *curxp, int *curyp, long *attrp)
{
struct vgafb_config *vc = v;
long defattr;
if (vc->nscreens > 0)
return (ENOMEM);
*cookiep = &vc->dc_rinfo; /* one and only for now */
*curxp = 0;
*curyp = 0;
vc->dc_rinfo.ri_ops.alloc_attr(&vc->dc_rinfo, 0, 0, 0, &defattr);
*attrp = defattr;
vc->nscreens++;
return (0);
}
void
vgafb_free_screen(void *v, void *cookie)
{
struct vgafb_config *vc = v;
if (vc == &vgafb_pci_console_vc)
panic("vgafb_free_screen: console");
vc->nscreens--;
}
int
vgafb_show_screen(void *v, void *cookie, int waitok,
void (*cb)(void *, int, int), void *cbarg)
{
return (0);
}