code:
/*	$OpenBSD: sisfb.c,v 1.4 2013/10/21 10:36:14 miod Exp $	*/

/*
 * Copyright (c) 2010 Miodrag Vallat.
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

/*
 * Minimalistic driver for the SIS315 Pro frame buffer found on the
 * Lemote Fuloong 2F systems.
 * Does not support accelaration, mode change, secondary output, or
 * anything fancy.
 */

#include <sys/param.h>
#include <sys/systm.h>
#include <sys/device.h>

#include <machine/bus.h>
#include <machine/cpu.h>

#include <uvm/uvm_extern.h>

#include <dev/pci/pcireg.h>
#include <dev/pci/pcivar.h>
#include <dev/pci/pcidevs.h>

#include <dev/ic/mc6845.h>

#include <dev/wscons/wsconsio.h>
#include <dev/wscons/wsdisplayvar.h>
#include <dev/rasops/rasops.h>

struct sisfb_softc;

/* minimal frame buffer information, suitable for early console */
struct sisfb {
	struct sisfb_softc	*sc;
	struct rasops_info	 ri;
	uint8_t			 cmap[256 * 3];

	bus_space_tag_t		 fbt;
	bus_space_handle_t	 fbh;

	bus_space_tag_t		 mmiot;
	bus_space_handle_t	 mmioh;

	bus_space_tag_t		 iot;
	bus_space_handle_t	 ioh;

	struct wsscreen_descr	 wsd;
};

struct sisfb_softc {
	struct device		 sc_dev;
	struct sisfb		*sc_fb;
	struct sisfb		 sc_fb_store;

	struct wsscreen_list	 sc_wsl;
	struct wsscreen_descr	*sc_scrlist[1];
	int			 sc_nscr;
};

int	sisfb_match(struct device *, void *, void *);
void	sisfb_attach(struct device *, struct device *, void *);

const struct cfattach sisfb_ca = {
	sizeof(struct sisfb_softc), sisfb_match, sisfb_attach
};

struct cfdriver sisfb_cd = {
	NULL, "sisfb", DV_DULL
};

int	sisfb_alloc_screen(void *, const struct wsscreen_descr *, void **, int *,
	    int *, long *);
void	sisfb_free_screen(void *, void *);
int	sisfb_ioctl(void *, u_long, caddr_t, int, struct proc *);
int	sisfb_list_font(void *, struct wsdisplay_font *);
int	sisfb_load_font(void *, void *, struct wsdisplay_font *);
paddr_t	sisfb_mmap(void *, off_t, int);
int	sisfb_show_screen(void *, void *, int, void (*)(void *, int, int),
	    void *);

struct wsdisplay_accessops sisfb_accessops = {
	.ioctl = sisfb_ioctl,
	.mmap = sisfb_mmap,
	.alloc_screen = sisfb_alloc_screen,
	.free_screen = sisfb_free_screen,
	.show_screen = sisfb_show_screen,
	.load_font = sisfb_load_font,
	.list_font = sisfb_list_font
};

int	sisfb_getcmap(uint8_t *, struct wsdisplay_cmap *);
void	sisfb_loadcmap(struct sisfb *, int, int);
int	sisfb_putcmap(uint8_t *, struct wsdisplay_cmap *);
int	sisfb_setup(struct sisfb *);

static struct sisfb sisfbcn;

const struct pci_matchid sisfb_devices[] = {
	{ PCI_VENDOR_SIS, PCI_PRODUCT_SIS_315PRO_VGA }
};

/*
 * Control Register access
 *
 * These are 8 bit registers; the choice of larger width types is intentional.
 */

#define	SIS_VGA_PORT_OFFSET	0x380

#define	SEQ_ADDR		(0x3c4 - SIS_VGA_PORT_OFFSET)
#define	SEQ_DATA		(0x3c5 - SIS_VGA_PORT_OFFSET)
#define	DAC_ADDR		(0x3c8 - SIS_VGA_PORT_OFFSET)
#define	DAC_DATA		(0x3c9 - SIS_VGA_PORT_OFFSET)
#undef	CRTC_ADDR
#define	CRTC_ADDR		(0x3d4 - SIS_VGA_PORT_OFFSET)
#define	CRTC_DATA		(0x3d5 - SIS_VGA_PORT_OFFSET)

static inline uint sisfb_crtc_read(struct sisfb *, uint);
static inline void sisfb_crtc_write(struct sisfb *, uint, uint);
static inline uint sisfb_seq_read(struct sisfb *, uint);
static inline void sisfb_seq_write(struct sisfb *, uint, uint);

static inline uint
sisfb_crtc_read(struct sisfb *fb, uint idx)
{
	uint val;
	bus_space_write_1(fb->iot, fb->ioh, CRTC_ADDR, idx);
	val = bus_space_read_1(fb->iot, fb->ioh, CRTC_DATA);
#ifdef SIS_DEBUG
	printf("CRTC %04x -> %02x\n", idx, val);
#endif
	return val;
}

static inline void
sisfb_crtc_write(struct sisfb *fb, uint idx, uint val)
{
#ifdef SIS_DEBUG
	printf("CRTC %04x <- %02x\n", idx, val);
#endif
	bus_space_write_1(fb->iot, fb->ioh, CRTC_ADDR, idx);
	bus_space_write_1(fb->iot, fb->ioh, CRTC_DATA, val);
}

static inline uint
sisfb_seq_read(struct sisfb *fb, uint idx)
{
	uint val;
	bus_space_write_1(fb->iot, fb->ioh, SEQ_ADDR, idx);
	val = bus_space_read_1(fb->iot, fb->ioh, SEQ_DATA);
#ifdef SIS_DEBUG
	printf("SEQ %04x -> %02x\n", idx, val);
#endif
	return val;
}

static inline void
sisfb_seq_write(struct sisfb *fb, uint idx, uint val)
{
#ifdef SIS_DEBUG
	printf("SEQ %04x <- %02x\n", idx, val);
#endif
	bus_space_write_1(fb->iot, fb->ioh, SEQ_ADDR, idx);
	bus_space_write_1(fb->iot, fb->ioh, SEQ_DATA, val);
}

int
sisfb_match(struct device *parent, void *vcf, void *aux)
{
	struct pci_attach_args *pa = (struct pci_attach_args *)aux;

	return pci_matchbyid(pa, sisfb_devices, nitems(sisfb_devices));
}

void
sisfb_attach(struct device *parent, struct device *self, void *aux)
{
	struct sisfb_softc *sc = (struct sisfb_softc *)self;
	struct pci_attach_args *pa = (struct pci_attach_args *)aux;
	struct wsemuldisplaydev_attach_args waa;
	bus_space_tag_t fbt, mmiot, iot;
	bus_space_handle_t fbh, mmioh, ioh;
	bus_size_t fbsize, mmiosize;
	struct sisfb *fb;
	int console;

	if (pci_mapreg_map(pa, PCI_MAPREG_START, PCI_MAPREG_TYPE_MEM,
	    BUS_SPACE_MAP_LINEAR, &fbt, &fbh, NULL, &fbsize, 0) != 0) {
		printf(": can't map frame buffer\n");
		return;
	}

	if (pci_mapreg_map(pa, PCI_MAPREG_START + 4, PCI_MAPREG_TYPE_MEM,
	    0, &mmiot, &mmioh, NULL, &mmiosize, 0) != 0) {
		printf(": can't map mmio area\n");
		goto fail1;
	}

	if (pci_mapreg_map(pa, PCI_MAPREG_START + 8, PCI_MAPREG_TYPE_IO,
	    0, &iot, &ioh, NULL, NULL, 0) != 0) {
		printf(": can't map registers\n");
		goto fail2;
	}

	console = sisfbcn.ri.ri_hw != NULL;

	if (console)
		fb = &sisfbcn;
	else
		fb = &sc->sc_fb_store;

	fb->sc = sc;
	fb->fbt = fbt;
	fb->fbh = fbh;
	fb->mmiot = mmiot;
	fb->mmioh = mmioh;
	fb->iot = iot;
	fb->ioh = ioh;
	sc->sc_fb = fb;

	if (!console) {
		if (sisfb_setup(fb) != 0) {
			printf(": can't setup frame buffer\n");
			return;
		}
	}

	printf(": %dx%dx%d frame buffer\n",
	    fb->ri.ri_width, fb->ri.ri_height, fb->ri.ri_depth);

	sc->sc_scrlist[0] = &fb->wsd;
	sc->sc_wsl.nscreens = 1;
	sc->sc_wsl.screens = (const struct wsscreen_descr **)sc->sc_scrlist;

	waa.console = console;
	waa.scrdata = &sc->sc_wsl;
	waa.accessops = &sisfb_accessops;
	waa.accesscookie = sc;
	waa.defaultscreens = 0;

	config_found((struct device *)sc, &waa, wsemuldisplaydevprint);
	return;

fail2:
	bus_space_unmap(mmiot, mmioh, mmiosize);
fail1:
	bus_space_unmap(fbt, fbh, fbsize);
}

/*
 * wsdisplay accesops
 */

int
sisfb_alloc_screen(void *v, const struct wsscreen_descr *type, void **cookiep,
    int *curxp, int *curyp, long *attrp)
{
	struct sisfb_softc *sc = (struct sisfb_softc *)v;
	struct rasops_info *ri = &sc->sc_fb->ri;

	if (sc->sc_nscr > 0)
		return ENOMEM;

	*cookiep = ri;
	*curxp = *curyp = 0;
	ri->ri_ops.alloc_attr(ri, 0, 0, 0, attrp);
	sc->sc_nscr++;

	return 0;
}

void
sisfb_free_screen(void *v, void *cookie)
{
	struct sisfb_softc *sc = (struct sisfb_softc *)v;

	sc->sc_nscr--;
}

int
sisfb_ioctl(void *v, u_long cmd, caddr_t data, int flags, struct proc *p)
{
	struct sisfb_softc *sc = (struct sisfb_softc *)v;
	struct sisfb *fb = sc->sc_fb;
	struct rasops_info *ri = &fb->ri;
	struct wsdisplay_cmap *cm;
	struct wsdisplay_fbinfo *wdf;
	int rc;

	switch (cmd) {
	case WSDISPLAYIO_GTYPE:
		*(uint *)data = WSDISPLAY_TYPE_SISFB;
		break;
	case WSDISPLAYIO_GINFO:
		wdf = (struct wsdisplay_fbinfo *)data;
		wdf->width = ri->ri_width;
		wdf->height = ri->ri_height;
		wdf->depth = ri->ri_depth;
		wdf->cmsize = 256;
		break;
	case WSDISPLAYIO_LINEBYTES:
		*(uint *)data = ri->ri_stride;
		break;
	case WSDISPLAYIO_GETCMAP:
		cm = (struct wsdisplay_cmap *)data;
		rc = sisfb_getcmap(fb->cmap, cm);
		if (rc != 0)
			return rc;
		break;
	case WSDISPLAYIO_PUTCMAP:
		cm = (struct wsdisplay_cmap *)data;
		rc = sisfb_putcmap(fb->cmap, cm);
		if (rc != 0)
			return rc;
		if (ri->ri_depth == 8)
			sisfb_loadcmap(fb, cm->index, cm->count);
		break;
	default:
		return -1;
	}

	return 0;
}

int
sisfb_show_screen(void *v, void *cookie, int waitok,
    void (*cb)(void *, int, int), void *cbarg)
{
	return 0;
}

paddr_t
sisfb_mmap(void *v, off_t offset, int prot)
{
	struct sisfb_softc *sc = (struct sisfb_softc *)v;
	struct rasops_info *ri = &sc->sc_fb->ri;

	if ((offset & PAGE_MASK) != 0)
		return -1;

	if (offset < 0 || offset >= ri->ri_stride * ri->ri_height)
		return -1;

	/*
	 * Don't allow mmap if the frame buffer area is not page aligned.
	 * XXX we should reprogram it to a page aligned boundary at attach
	 * XXX time if this isn't the case.
	 */
	if (((paddr_t)ri->ri_bits & PAGE_MASK) != 0)
		return -1;

	return XKPHYS_TO_PHYS((paddr_t)ri->ri_bits) + offset;
}

int
sisfb_load_font(void *v, void *emulcookie, struct wsdisplay_font *font)
{
	struct sisfb_softc *sc = (struct sisfb_softc *)v;
	struct rasops_info *ri = &sc->sc_fb->ri;

	return rasops_load_font(ri, emulcookie, font);
}

int
sisfb_list_font(void *v, struct wsdisplay_font *font)
{
	struct sisfb_softc *sc = (struct sisfb_softc *)v;
	struct rasops_info *ri = &sc->sc_fb->ri;

	return rasops_list_font(ri, font);
}

/*
 * Frame buffer initialization.
 */

int
sisfb_setup(struct sisfb *fb)
{
	struct rasops_info *ri;
	uint width, height, bpp;
	bus_size_t fbaddr;
	uint tmp;

	/*
	 * Unlock access to extended registers.
	 */

	sisfb_seq_write(fb, 0x05, 0x86);

	/*
	 * Try and figure out display settings.
	 */

	height = sisfb_crtc_read(fb, CRTC_VDE);
	tmp = sisfb_crtc_read(fb, CRTC_OVERFLL);
	if (ISSET(tmp, 1 << 1))
		height |= 1 << 8;
	if (ISSET(tmp, 1 << 6))
		height |= 1 << 9;
	tmp = sisfb_seq_read(fb, 0x0a);
	if (ISSET(tmp, 1 << 1))
		height |= 1 << 10;
	height++;

	width = sisfb_crtc_read(fb, CRTC_HDISPLE);
	tmp = sisfb_seq_read(fb, 0x0b);
	if (ISSET(tmp, 1 << 2))
		width |= 1 << 8;
	if (ISSET(tmp, 1 << 3))
		width |= 1 << 9;
	width++;
	width <<= 3;

	fbaddr = sisfb_crtc_read(fb, CRTC_STARTADRL) |
	    (sisfb_crtc_read(fb, CRTC_STARTADRH) << 8) |
	    (sisfb_seq_read(fb, 0x0d) << 16) |
	    ((sisfb_seq_read(fb, 0x37) & 0x03) << 24);
	fbaddr <<= 2;
#ifdef SIS_DEBUG
	printf("FBADDR %08x\n", fbaddr);
#endif

	tmp = sisfb_seq_read(fb, 0x06);
	switch (tmp & 0x1c) {
	case 0x00:
		bpp = 8;
		break;
	case 0x04:
		bpp = 15;
		break;
	case 0x08:
		bpp = 16;
		break;
	case 0x10:
		bpp = 32;
		break;
	default:
		return EINVAL;
	}

	ri = &fb->ri;
	ri->ri_width = width;
	ri->ri_height = height;
	ri->ri_depth = bpp;
	ri->ri_stride = (ri->ri_width * ri->ri_depth) / 8;
	ri->ri_flg = RI_CENTER | RI_CLEAR | RI_FULLCLEAR;
	ri->ri_bits = (void *)(bus_space_vaddr(fb->fbt, fb->fbh) + fbaddr);
	ri->ri_hw = fb;

#ifdef __MIPSEL__
	/* swap B and R */
	switch (bpp) {
	case 15:
		ri->ri_rnum = 5;
		ri->ri_rpos = 10;
		ri->ri_gnum = 5;
		ri->ri_gpos = 5;
		ri->ri_bnum = 5;
		ri->ri_bpos = 0;
		break;
	case 16:
		ri->ri_rnum = 5;
		ri->ri_rpos = 11;
		ri->ri_gnum = 6;
		ri->ri_gpos = 5;
		ri->ri_bnum = 5;
		ri->ri_bpos = 0;
		break;
	}
#endif

	bcopy(rasops_cmap, fb->cmap, sizeof(fb->cmap));
	if (bpp == 8)
		sisfb_loadcmap(fb, 0, 256);

	rasops_init(ri, 160, 160);

	strlcpy(fb->wsd.name, "std", sizeof(fb->wsd.name));
	fb->wsd.ncols = ri->ri_cols;
	fb->wsd.nrows = ri->ri_rows;
	fb->wsd.textops = &ri->ri_ops;
	fb->wsd.fontwidth = ri->ri_font->fontwidth;
	fb->wsd.fontheight = ri->ri_font->fontheight;
	fb->wsd.capabilities = ri->ri_caps;

	return 0;
}

/*
 * Colormap handling routines.
 */

void
sisfb_loadcmap(struct sisfb *fb, int baseidx, int count)
{
	uint8_t *cmap = fb->cmap + baseidx * 3;

	bus_space_write_1(fb->iot, fb->ioh, DAC_ADDR, baseidx);
	while (count-- != 0) {
		bus_space_write_1(fb->iot, fb->ioh, DAC_DATA, *cmap++ >> 2);
		bus_space_write_1(fb->iot, fb->ioh, DAC_DATA, *cmap++ >> 2);
		bus_space_write_1(fb->iot, fb->ioh, DAC_DATA, *cmap++ >> 2);
	}
}

int
sisfb_getcmap(uint8_t *cmap, struct wsdisplay_cmap *cm)
{
	uint index = cm->index, count = cm->count, i;
	uint8_t ramp[256], *dst, *src;
	int rc;

	if (index >= 256 || count > 256 - index)
		return EINVAL;

	index *= 3;

	src = cmap + index;
	dst = ramp;
	for (i = 0; i < count; i++)
		*dst++ = *src, src += 3;
	rc = copyout(ramp, cm->red, count);
	if (rc != 0)
		return rc;

	src = cmap + index + 1;
	dst = ramp;
	for (i = 0; i < count; i++)
		*dst++ = *src, src += 3;
	rc = copyout(ramp, cm->green, count);
	if (rc != 0)
		return rc;

	src = cmap + index + 2;
	dst = ramp;
	for (i = 0; i < count; i++)
		*dst++ = *src, src += 3;
	rc = copyout(ramp, cm->blue, count);
	if (rc != 0)
		return rc;

	return 0;
}

int
sisfb_putcmap(uint8_t *cmap, struct wsdisplay_cmap *cm)
{
	uint index = cm->index, count = cm->count, i;
	uint8_t ramp[256], *dst, *src;
	int rc;

	if (index >= 256 || count > 256 - index)
		return EINVAL;

	index *= 3;

	rc = copyin(cm->red, ramp, count);
	if (rc != 0)
		return rc;
	dst = cmap + index;
	src = ramp;
	for (i = 0; i < count; i++)
		*dst = *src++, dst += 3;

	rc = copyin(cm->green, ramp, count);
	if (rc != 0)
		return rc;
	dst = cmap + index + 1;
	src = ramp;
	for (i = 0; i < count; i++)
		*dst = *src++, dst += 3;

	rc = copyin(cm->blue, ramp, count);
	if (rc != 0)
		return rc;
	dst = cmap + index + 2;
	src = ramp;
	for (i = 0; i < count; i++)
		*dst = *src++, dst += 3;

	return 0;
}

/*
 * Early console code
 */

int sisfb_cnattach(bus_space_tag_t, bus_space_tag_t, pcitag_t, pcireg_t);

int
sisfb_cnattach(bus_space_tag_t memt, bus_space_tag_t iot, pcitag_t tag,
    pcireg_t id)
{
	long defattr;
	struct rasops_info *ri;
	pcireg_t bar;
	int rc;

	/* filter out unrecognized devices */
	switch (id) {
	default:
		return ENODEV;
	case PCI_ID_CODE(PCI_VENDOR_SIS, PCI_PRODUCT_SIS_315PRO_VGA):
		break;
	}

	bar = pci_conf_read_early(tag, PCI_MAPREG_START);
	if (PCI_MAPREG_TYPE(bar) != PCI_MAPREG_TYPE_MEM)
		return EINVAL;
	sisfbcn.fbt = memt;
	rc = bus_space_map(memt, PCI_MAPREG_MEM_ADDR(bar), 1 /* XXX */,
	    BUS_SPACE_MAP_LINEAR, &sisfbcn.fbh);
	if (rc != 0)
		return rc;

	bar = pci_conf_read_early(tag, PCI_MAPREG_START + 4);
	if (PCI_MAPREG_TYPE(bar) != PCI_MAPREG_TYPE_MEM)
		return EINVAL;
	sisfbcn.mmiot = memt;
	rc = bus_space_map(memt, PCI_MAPREG_MEM_ADDR(bar), 1 /* XXX */,
	    BUS_SPACE_MAP_LINEAR, &sisfbcn.mmioh);
	if (rc != 0)
		return rc;

	bar = pci_conf_read_early(tag, PCI_MAPREG_START + 8);
	if (PCI_MAPREG_TYPE(bar) != PCI_MAPREG_TYPE_IO)
		return EINVAL;
	sisfbcn.iot = iot;
	rc = bus_space_map(iot, PCI_MAPREG_MEM_ADDR(bar), 1 /* XXX */,
	    0, &sisfbcn.ioh);
	if (rc != 0)
		return rc;

	rc = sisfb_setup(&sisfbcn);
	if (rc != 0)
		return rc;

	ri = &sisfbcn.ri;
	ri->ri_ops.alloc_attr(ri, 0, 0, 0, &defattr);
	wsdisplay_cnattach(&sisfbcn.wsd, ri, 0, 0, defattr);

	return 0;
}


code:
/*	$OpenBSD: smfb.c,v 1.16 2013/10/21 10:36:14 miod Exp $	*/

/*
 * Copyright (c) 2009, 2010 Miodrag Vallat.
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

/*
 * SiliconMotion SM502 and SM712 frame buffer driver.
 *
 * Assumes its video output is an LCD panel, in 5:6:5 mode, and fixed
 * 1024x600 or 800x480 resolution, depending on the system model.
 */

#include <sys/param.h>
#include <sys/systm.h>
#include <sys/device.h>

#include <machine/autoconf.h>
#include <machine/bus.h>
#include <machine/cpu.h>

#include <uvm/uvm_extern.h>

#include <dev/ic/vgareg.h>
#include <dev/isa/isareg.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 <loongson/dev/voyagerreg.h>
#include <loongson/dev/voyagervar.h>
#include <loongson/dev/smfbreg.h>

struct smfb_softc;

/* minimal frame buffer information, suitable for early console */
struct smfb {
	struct smfb_softc	*sc;
	struct rasops_info	ri;
	int			is5xx;

	/* DPR registers */
	bus_space_tag_t		dprt;
	bus_space_handle_t	dprh;
	/* MMIO space (SM7xx) or control registers (SM5xx) */
	bus_space_tag_t		mmiot;
	bus_space_handle_t	mmioh;
	/* DCR registers (SM5xx) */
	bus_space_tag_t		dcrt;
	bus_space_handle_t	dcrh;

	struct wsscreen_descr	wsd;
};

#define	DCR_READ(fb, reg) \
	bus_space_read_4((fb)->dcrt, (fb)->dcrh, (reg))
#define	DCR_WRITE(fb, reg, val) \
	bus_space_write_4((fb)->dcrt, (fb)->dcrh, (reg), (val))
#define	DPR_READ(fb, reg) \
	bus_space_read_4((fb)->dprt, (fb)->dprh, (reg))
#define	DPR_WRITE(fb, reg, val) \
	bus_space_write_4((fb)->dprt, (fb)->dprh, (reg), (val))

struct smfb_softc {
	struct device		 sc_dev;
	struct smfb		*sc_fb;
	struct smfb		 sc_fb_store;

	struct wsscreen_list	 sc_wsl;
	struct wsscreen_descr	*sc_scrlist[1];
	int			 sc_nscr;
};

int	smfb_pci_match(struct device *, void *, void *);
void	smfb_pci_attach(struct device *, struct device *, void *);
int	smfb_voyager_match(struct device *, void *, void *);
void	smfb_voyager_attach(struct device *, struct device *, void *);
int	smfb_activate(struct device *, int);

const struct cfattach smfb_pci_ca = {
	sizeof(struct smfb_softc), smfb_pci_match, smfb_pci_attach,
	NULL, smfb_activate
};

const struct cfattach smfb_voyager_ca = {
	sizeof(struct smfb_softc), smfb_voyager_match, smfb_voyager_attach,
	smfb_activate
};

struct cfdriver smfb_cd = {
	NULL, "smfb", DV_DULL
};

int	smfb_alloc_screen(void *, const struct wsscreen_descr *, void **, int *,
	    int *, long *);
void	smfb_burner(void *, uint, uint);
void	smfb_free_screen(void *, void *);
int	smfb_ioctl(void *, u_long, caddr_t, int, struct proc *);
int	smfb_list_font(void *, struct wsdisplay_font *);
int	smfb_load_font(void *, void *, struct wsdisplay_font *);
paddr_t	smfb_mmap(void *, off_t, int);
int	smfb_show_screen(void *, void *, int, void (*)(void *, int, int),
	    void *);

struct wsdisplay_accessops smfb_accessops = {
	.ioctl = smfb_ioctl,
	.mmap = smfb_mmap,
	.alloc_screen = smfb_alloc_screen,
	.free_screen = smfb_free_screen,
	.show_screen = smfb_show_screen,
	.load_font = smfb_load_font,
	.list_font = smfb_list_font,
	.burn_screen = smfb_burner
};

int	smfb_setup(struct smfb *, bus_space_tag_t, bus_space_handle_t,
	    bus_space_tag_t, bus_space_handle_t);

void	smfb_copyrect(struct smfb *, int, int, int, int, int, int);
void	smfb_fillrect(struct smfb *, int, int, int, int, int);
int	smfb_copyrows(void *, int, int, int);
int	smfb_copycols(void *, int, int, int, int);
int	smfb_do_cursor(struct rasops_info *);
int	smfb_erasecols(void *, int, int, int, long);
int	smfb_eraserows(void *, int, int, long);
int	smfb_wait(struct smfb *);

void	smfb_wait_panel_vsync(struct smfb *, int);
uint8_t	smfb_vgats_read(struct smfb *, uint);
void	smfb_vgats_write(struct smfb *, uint, uint8_t);

void	smfb_attach_common(struct smfb_softc *, int, bus_space_tag_t,
	    bus_space_handle_t, bus_space_tag_t, bus_space_handle_t);

static struct smfb smfbcn;

const struct pci_matchid smfb_devices[] = {
	{ PCI_VENDOR_SMI, PCI_PRODUCT_SMI_SM712 }
};

int
smfb_pci_match(struct device *parent, void *vcf, void *aux)
{
	struct pci_attach_args *pa = (struct pci_attach_args *)aux;

	return pci_matchbyid(pa, smfb_devices, nitems(smfb_devices));
}

int
smfb_voyager_match(struct device *parent, void *vcf, void *aux)
{
	struct voyager_attach_args *vaa = (struct voyager_attach_args *)aux;
	struct cfdata *cf = (struct cfdata *)vcf;

	return strcmp(vaa->vaa_name, cf->cf_driver->cd_name) == 0;
}

void
smfb_pci_attach(struct device *parent, struct device *self, void *aux)
{
	struct smfb_softc *sc = (struct smfb_softc *)self;
	struct pci_attach_args *pa = (struct pci_attach_args *)aux;
	bus_space_tag_t memt;
	bus_space_handle_t memh;

	if (pci_mapreg_map(pa, PCI_MAPREG_START, PCI_MAPREG_TYPE_MEM,
	    BUS_SPACE_MAP_LINEAR, &memt, &memh, NULL, NULL, 0) != 0) {
		printf(": can't map frame buffer\n");
		return;
	}

	smfb_attach_common(sc, 0, memt, memh, memt, memh);
}

void
smfb_voyager_attach(struct device *parent, struct device *self, void *aux)
{
	struct smfb_softc *sc = (struct smfb_softc *)self;
	struct voyager_attach_args *vaa = (struct voyager_attach_args *)aux;

	smfb_attach_common(sc, 1, vaa->vaa_fbt, vaa->vaa_fbh, vaa->vaa_mmiot,
	    vaa->vaa_mmioh);
}

void
smfb_attach_common(struct smfb_softc *sc, int is5xx, bus_space_tag_t memt,
    bus_space_handle_t memh, bus_space_tag_t mmiot, bus_space_handle_t mmioh)
{
	struct wsemuldisplaydev_attach_args waa;
	int console;

	console = smfbcn.ri.ri_hw != NULL;

	if (console) {
		sc->sc_fb = &smfbcn;
		sc->sc_fb->sc = sc;
	} else {
		sc->sc_fb = &sc->sc_fb_store;
		sc->sc_fb->is5xx = is5xx;
		if (smfb_setup(sc->sc_fb, memt, memh, mmiot, mmioh) != 0) {
			printf(": can't setup frame buffer\n");
			return;
		}
	}

	/* XXX print resolution */
	printf("\n");

	sc->sc_scrlist[0] = &sc->sc_fb->wsd;
	sc->sc_wsl.nscreens = 1;
	sc->sc_wsl.screens = (const struct wsscreen_descr **)sc->sc_scrlist;

	waa.console = console;
	waa.scrdata = &sc->sc_wsl;
	waa.accessops = &smfb_accessops;
	waa.accesscookie = sc;
	waa.defaultscreens = 0;

	config_found((struct device *)sc, &waa, wsemuldisplaydevprint);
}

/*
 * wsdisplay accesops
 */

int
smfb_alloc_screen(void *v, const struct wsscreen_descr *type, void **cookiep,
    int *curxp, int *curyp, long *attrp)
{
	struct smfb_softc *sc = (struct smfb_softc *)v;
	struct rasops_info *ri = &sc->sc_fb->ri;

	if (sc->sc_nscr > 0)
		return ENOMEM;

	*cookiep = ri;
	*curxp = *curyp = 0;
	ri->ri_ops.alloc_attr(ri, 0, 0, 0, attrp);
	sc->sc_nscr++;

	return 0;
}

void
smfb_free_screen(void *v, void *cookie)
{
	struct smfb_softc *sc = (struct smfb_softc *)v;

	sc->sc_nscr--;
}

int
smfb_ioctl(void *v, u_long cmd, caddr_t data, int flags, struct proc *p)
{
	struct smfb_softc *sc = (struct smfb_softc *)v;
	struct rasops_info *ri = &sc->sc_fb->ri;
	struct wsdisplay_fbinfo *wdf;

	switch (cmd) {
	case WSDISPLAYIO_GTYPE:
		*(uint *)data = WSDISPLAY_TYPE_SMFB;
		break;
	case WSDISPLAYIO_GINFO:
		wdf = (struct wsdisplay_fbinfo *)data;
		wdf->width = ri->ri_width;
		wdf->height = ri->ri_height;
		wdf->depth = ri->ri_depth;
		wdf->cmsize = 0;
		break;
	case WSDISPLAYIO_LINEBYTES:
		*(uint *)data = ri->ri_stride;
		break;
	default:
		return -1;
	}

	return 0;
}

int
smfb_show_screen(void *v, void *cookie, int waitok,
    void (*cb)(void *, int, int), void *cbarg)
{
	return 0;
}

paddr_t
smfb_mmap(void *v, off_t offset, int prot)
{
	struct smfb_softc *sc = (struct smfb_softc *)v;
	struct rasops_info *ri = &sc->sc_fb->ri;

	if ((offset & PAGE_MASK) != 0)
		return -1;

	if (offset < 0 || offset >= ri->ri_stride * ri->ri_height)
		return -1;

	return XKPHYS_TO_PHYS((paddr_t)ri->ri_bits) + offset;
}

int
smfb_load_font(void *v, void *emulcookie, struct wsdisplay_font *font)
{
	struct smfb_softc *sc = (struct smfb_softc *)v;
	struct rasops_info *ri = &sc->sc_fb->ri;

	return rasops_load_font(ri, emulcookie, font);
}

int
smfb_list_font(void *v, struct wsdisplay_font *font)
{
	struct smfb_softc *sc = (struct smfb_softc *)v;
	struct rasops_info *ri = &sc->sc_fb->ri;

	return rasops_list_font(ri, font);
}

void
smfb_burner(void *v, uint on, uint flg)
{
	struct smfb_softc *sc = (struct smfb_softc *)v;
	struct smfb *fb = sc->sc_fb;

	if (fb->is5xx) {
		if (on) {
			/*
			 * Wait for a few cycles after restoring power,
			 * to prevent white flickering.
			 */
			DCR_WRITE(fb, DCR_PANEL_DISPLAY_CONTROL,
			    DCR_READ(fb, DCR_PANEL_DISPLAY_CONTROL) | PDC_VDD);
			smfb_wait_panel_vsync(fb, 4);
			DCR_WRITE(fb, DCR_PANEL_DISPLAY_CONTROL,
			    DCR_READ(fb, DCR_PANEL_DISPLAY_CONTROL) | PDC_DATA);
			smfb_wait_panel_vsync(fb, 4);
			DCR_WRITE(fb, DCR_PANEL_DISPLAY_CONTROL,
			    DCR_READ(fb, DCR_PANEL_DISPLAY_CONTROL) |
			    (PDC_BIAS | PDC_EN));
		} else
			DCR_WRITE(fb, DCR_PANEL_DISPLAY_CONTROL,
			    DCR_READ(fb, DCR_PANEL_DISPLAY_CONTROL) &
			    ~(PDC_EN | PDC_BIAS | PDC_DATA | PDC_VDD));
	} else {
		if (on) {
			smfb_vgats_write(fb, 0x31,
			    smfb_vgats_read(fb, 0x31) | 0x01);
		} else {
			smfb_vgats_write(fb, 0x21,
			    smfb_vgats_read(fb, 0x21) | 0x30);
			smfb_vgats_write(fb, 0x31,
			    smfb_vgats_read(fb, 0x31) & ~0x01);
		}
	}
}

/*
 * Frame buffer initialization.
 */

int
smfb_setup(struct smfb *fb, bus_space_tag_t memt, bus_space_handle_t memh,
    bus_space_tag_t mmiot, bus_space_handle_t mmioh)
{
	struct rasops_info *ri;
	int accel = 0;
	int rc;

	ri = &fb->ri;
	switch (sys_platform->system_type) {
	case LOONGSON_EBT700:
		ri->ri_width = 800;
		ri->ri_height = 480;
		break;
	default:
	case LOONGSON_GDIUM:
	case LOONGSON_LYNLOONG:
	case LOONGSON_YEELOONG:
		ri->ri_width = 1024;
		ri->ri_height = 600;
		break;
	}
	ri->ri_depth = 16;
	ri->ri_stride = (ri->ri_width * ri->ri_depth) / 8;
	ri->ri_flg = RI_CENTER | RI_CLEAR | RI_FULLCLEAR;
	ri->ri_bits = (void *)bus_space_vaddr(memt, memh);
	ri->ri_hw = fb;

#ifdef __MIPSEL__
	/* swap B and R */
	ri->ri_rnum = 5;
	ri->ri_rpos = 11;
	ri->ri_gnum = 6;
	ri->ri_gpos = 5;
	ri->ri_bnum = 5;
	ri->ri_bpos = 0;
#endif

	rasops_init(ri, 160, 160);

	strlcpy(fb->wsd.name, "std", sizeof(fb->wsd.name));
	fb->wsd.ncols = ri->ri_cols;
	fb->wsd.nrows = ri->ri_rows;
	fb->wsd.textops = &ri->ri_ops;
	fb->wsd.fontwidth = ri->ri_font->fontwidth;
	fb->wsd.fontheight = ri->ri_font->fontheight;
	fb->wsd.capabilities = ri->ri_caps;

	if (fb->is5xx) {
		fb->dcrt = mmiot;
		if ((rc = bus_space_subregion(mmiot, mmioh, SM5XX_DCR_BASE,
		    SM5XX_DCR_SIZE, &fb->dcrh)) != 0)
			return rc;
		fb->dprt = mmiot;
		if ((rc = bus_space_subregion(mmiot, mmioh, SM5XX_DPR_BASE,
		    SMXXX_DPR_SIZE, &fb->dprh)) != 0)
			return rc;
		fb->mmiot = mmiot;
		if ((rc = bus_space_subregion(mmiot, mmioh, SM5XX_MMIO_BASE,
		    SM5XX_MMIO_SIZE, &fb->mmioh)) != 0)
			return rc;
		accel = 1;
	} else {
		fb->dprt = memt;
		if ((rc = bus_space_subregion(memt, memh, SM7XX_DPR_BASE,
		    SMXXX_DPR_SIZE, &fb->dprh)) != 0)
			return rc;
		fb->mmiot = memt;
		if ((rc = bus_space_subregion(memt, memh, SM7XX_MMIO_BASE,
		    SM7XX_MMIO_SIZE, &fb->mmioh)) != 0)
			return rc;
		accel = 1;
	}

	/*
	 * Setup 2D acceleration whenever possible
	 */

	if (accel) {
		if (smfb_wait(fb) != 0)
			accel = 0;
	}
	if (accel) {
		DPR_WRITE(fb, DPR_CROP_TOPLEFT_COORDS, DPR_COORDS(0, 0));
		/* use of width both times is intentional */
		DPR_WRITE(fb, DPR_PITCH,
		    DPR_COORDS(ri->ri_width, ri->ri_width));
		DPR_WRITE(fb, DPR_SRC_WINDOW,
		    DPR_COORDS(ri->ri_width, ri->ri_width));
		DPR_WRITE(fb, DPR_BYTE_BIT_MASK, 0xffffffff);
		DPR_WRITE(fb, DPR_COLOR_COMPARE_MASK, 0);
		DPR_WRITE(fb, DPR_COLOR_COMPARE, 0);
		DPR_WRITE(fb, DPR_SRC_BASE, 0);
		DPR_WRITE(fb, DPR_DST_BASE, 0);
		DPR_READ(fb, DPR_DST_BASE);

		ri->ri_ops.copycols = smfb_copycols;
		ri->ri_ops.copyrows = smfb_copyrows;
		ri->ri_ops.erasecols = smfb_erasecols;
		ri->ri_ops.eraserows = smfb_eraserows;
	}

	return 0;
}

void
smfb_copyrect(struct smfb *fb, int sx, int sy, int dx, int dy, int w, int h)
{
	uint32_t dir;

	/* Compute rop direction */
	if (sy < dy || (sy == dy && sx <= dx)) {
		sx += w - 1;
		dx += w - 1;
		sy += h - 1;
		dy += h - 1;
		dir = DE_CTRL_RTOL;
	} else
		dir = 0;

	DPR_WRITE(fb, DPR_SRC_COORDS, DPR_COORDS(sx, sy));
	DPR_WRITE(fb, DPR_DST_COORDS, DPR_COORDS(dx, dy));
	DPR_WRITE(fb, DPR_SPAN_COORDS, DPR_COORDS(w, h));
	DPR_WRITE(fb, DPR_DE_CTRL, DE_CTRL_START | DE_CTRL_ROP_ENABLE | dir |
	    (DE_CTRL_COMMAND_BITBLT << DE_CTRL_COMMAND_SHIFT) |
	    (DE_CTRL_ROP_SRC << DE_CTRL_ROP_SHIFT));
	DPR_READ(fb, DPR_DE_CTRL);

	smfb_wait(fb);
}

void
smfb_fillrect(struct smfb *fb, int x, int y, int w, int h, int bg)
{
	struct rasops_info *ri;

	ri = &fb->ri;

	DPR_WRITE(fb, DPR_FG_COLOR, ri->ri_devcmap[bg]);
	DPR_WRITE(fb, DPR_DST_COORDS, DPR_COORDS(x, y));
	DPR_WRITE(fb, DPR_SPAN_COORDS, DPR_COORDS(w, h));
	DPR_WRITE(fb, DPR_DE_CTRL, DE_CTRL_START | DE_CTRL_ROP_ENABLE |
	    (DE_CTRL_COMMAND_SOLIDFILL << DE_CTRL_COMMAND_SHIFT) |
	    (DE_CTRL_ROP_SRC << DE_CTRL_ROP_SHIFT));
	DPR_READ(fb, DPR_DE_CTRL);

	smfb_wait(fb);
}

int
smfb_copyrows(void *cookie, int src, int dst, int num)
{
	struct rasops_info *ri = cookie;
	struct smfb *fb = ri->ri_hw;
	struct wsdisplay_font *f = ri->ri_font;

	num *= f->fontheight;
	src *= f->fontheight;
	dst *= f->fontheight;

	smfb_copyrect(fb, ri->ri_xorigin, ri->ri_yorigin + src,
	    ri->ri_xorigin, ri->ri_yorigin + dst, ri->ri_emuwidth, num);

	return 0;
}

int
smfb_copycols(void *cookie, int row, int src, int dst, int num)
{
	struct rasops_info *ri = cookie;
	struct smfb *fb = ri->ri_hw;
	struct wsdisplay_font *f = ri->ri_font;

	num *= f->fontwidth;
	src *= f->fontwidth;
	dst *= f->fontwidth;
	row *= f->fontheight;

	smfb_copyrect(fb, ri->ri_xorigin + src, ri->ri_yorigin + row,
	    ri->ri_xorigin + dst, ri->ri_yorigin + row, num, f->fontheight);

	return 0;
}

int
smfb_erasecols(void *cookie, int row, int col, int num, long attr)
{
	struct rasops_info *ri = cookie;
	struct smfb *fb = ri->ri_hw;
	struct wsdisplay_font *f = ri->ri_font;
	int bg, fg;

	ri->ri_ops.unpack_attr(cookie, attr, &fg, &bg, NULL);

	row *= f->fontheight;
	col *= f->fontwidth;
	num *= f->fontwidth;

	smfb_fillrect(fb, ri->ri_xorigin + col, ri->ri_yorigin + row,
	    num, f->fontheight, bg);

	return 0;
}

int
smfb_eraserows(void *cookie, int row, int num, long attr)
{
	struct rasops_info *ri = cookie;
	struct smfb *fb = ri->ri_hw;
	struct wsdisplay_font *f = ri->ri_font;
	int bg, fg;
	int x, y, w;

	ri->ri_ops.unpack_attr(cookie, attr, &fg, &bg, NULL);

	if ((num == ri->ri_rows) && ISSET(ri->ri_flg, RI_FULLCLEAR)) {
		num = ri->ri_height;
		x = y = 0;
		w = ri->ri_width;
	} else {
		num *= f->fontheight;
		x = ri->ri_xorigin;
		y = ri->ri_yorigin + row * f->fontheight;
		w = ri->ri_emuwidth;
	}
	smfb_fillrect(fb, x, y, w, num, bg);

	return 0;
}

int
smfb_wait(struct smfb *fb)
{
	uint32_t reg;
	int i;

	i = 10000;
	while (i-- != 0) {
		if (fb->is5xx) {
			reg = bus_space_read_4(fb->mmiot, fb->mmioh,
			    VOYAGER_SYSTEM_CONTROL);
			if ((reg & (VSC_FIFO_EMPTY | VSC_2DENGINE_BUSY)) ==
			    VSC_FIFO_EMPTY)
				return 0;
		} else {
			reg = smfb_vgats_read(fb, 0x16);
			if ((reg & 0x18) == 0x10)
				return 0;
		}
		delay(1);
	}

	return EBUSY;
}

/*
 * wait for a few panel vertical retrace cycles (5xx only)
 */
void
smfb_wait_panel_vsync(struct smfb *fb, int ncycles)
{
	while (ncycles-- != 0) {
		/* wait for end of retrace-in-progress */
		while (ISSET(bus_space_read_4(fb->mmiot, fb->mmioh,
		    VOYAGER_COMMANDLIST_STATUS), VCS_SP))
			delay(10);
		/* wait for start of retrace */
		while (!ISSET(bus_space_read_4(fb->mmiot, fb->mmioh,
		    VOYAGER_COMMANDLIST_STATUS), VCS_SP))
			delay(10);
	}
}

/*
 * vga sequencer access through mmio space (non-5xx only)
 */

uint8_t
smfb_vgats_read(struct smfb *fb, uint regno)
{
	bus_space_write_1(fb->mmiot, fb->mmioh, IO_VGA + VGA_TS_INDEX, regno);
	return bus_space_read_1(fb->mmiot, fb->mmioh, IO_VGA + VGA_TS_DATA);
}

void
smfb_vgats_write(struct smfb *fb, uint regno, uint8_t value)
{
	bus_space_write_1(fb->mmiot, fb->mmioh, IO_VGA + VGA_TS_INDEX, regno);
	bus_space_write_1(fb->mmiot, fb->mmioh, IO_VGA + VGA_TS_DATA, value);
}

/*
 * Early console code
 */

int smfb_cnattach(bus_space_tag_t, bus_space_tag_t, pcitag_t, pcireg_t);

int
smfb_cnattach(bus_space_tag_t memt, bus_space_tag_t iot, pcitag_t tag,
    pcireg_t id)
{
	long defattr;
	struct rasops_info *ri;
	bus_space_handle_t fbh, mmioh;
	pcireg_t bar;
	int rc, is5xx;

	/* filter out unrecognized devices */
	switch (id) {
	default:
		return ENODEV;
	case PCI_ID_CODE(PCI_VENDOR_SMI, PCI_PRODUCT_SMI_SM712):
		is5xx = 0;
		break;
	case PCI_ID_CODE(PCI_VENDOR_SMI, PCI_PRODUCT_SMI_SM501):
		is5xx = 1;
		break;
	}

	smfbcn.is5xx = is5xx;

	bar = pci_conf_read_early(tag, PCI_MAPREG_START);
	if (PCI_MAPREG_TYPE(bar) != PCI_MAPREG_TYPE_MEM)
		return EINVAL;
	rc = bus_space_map(memt, PCI_MAPREG_MEM_ADDR(bar), 1 /* XXX */,
	    BUS_SPACE_MAP_LINEAR, &fbh);
	if (rc != 0)
		return rc;

	if (smfbcn.is5xx) {
		bar = pci_conf_read_early(tag, PCI_MAPREG_START + 0x04);
		if (PCI_MAPREG_TYPE(bar) != PCI_MAPREG_TYPE_MEM)
			return EINVAL;
		rc = bus_space_map(memt, PCI_MAPREG_MEM_ADDR(bar), 1 /* XXX */,
		    BUS_SPACE_MAP_LINEAR, &mmioh);
		if (rc != 0)
			return rc;
	} else {
		mmioh = fbh;
	}

	rc = smfb_setup(&smfbcn, memt, fbh, memt, mmioh);
	if (rc != 0)
		return rc;

	ri = &smfbcn.ri;
	ri->ri_ops.alloc_attr(ri, 0, 0, 0, &defattr);
	wsdisplay_cnattach(&smfbcn.wsd, ri, 0, 0, defattr);

	return 0;
}

int
smfb_activate(struct device *self, int act)
{
	struct smfb_softc *sc = (struct smfb_softc *)self;

	switch (act) {
	case DVACT_SUSPEND:
		smfb_burner(sc, 0, 0);
		break;
	case DVACT_RESUME:
		smfb_burner(sc, 1, 0);
		break;
	}

	return 0;
}

license: unknown


code:
/*	$OpenBSD: smfbreg.h,v 1.5 2010/08/27 12:48:54 miod Exp $	*/

/*
 * Copyright (c) 2009, 2010 Miodrag Vallat.
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

/*
 * Silicon Motion SM712 registers
 */

/*
 * DPR (2D drawing engine)
 */

#define	DPR_COORDS(x, y)		(((x) << 16) | (y))

#define	SM5XX_DPR_BASE			0x00100000
#define	SM7XX_DPR_BASE			0x00408000
#define	SMXXX_DPR_SIZE			0x00004000

#define	DPR_SRC_COORDS			0x00
#define	DPR_DST_COORDS			0x04
#define	DPR_SPAN_COORDS			0x08
#define	DPR_DE_CTRL			0x0c
#define	DPR_PITCH			0x10
#define	DPR_FG_COLOR			0x14
#define	DPR_BG_COLOR			0x18
#define	DPR_STRETCH			0x1c
#define	DPR_COLOR_COMPARE		0x20
#define	DPR_COLOR_COMPARE_MASK		0x24
#define	DPR_BYTE_BIT_MASK		0x28
#define	DPR_CROP_TOPLEFT_COORDS		0x2c
#define	DPR_CROP_BOTRIGHT_COORDS	0x30
#define	DPR_MONO_PATTERN_LO32		0x34
#define	DPR_MONO_PATTERN_HI32		0x38
#define	DPR_SRC_WINDOW			0x3c
#define	DPR_SRC_BASE			0x40
#define	DPR_DST_BASE			0x44

#define	DE_CTRL_START			0x80000000
#define	DE_CTRL_RTOL			0x08000000
#define	DE_CTRL_COMMAND_MASK		0x001f0000
#define	DE_CTRL_COMMAND_SHIFT			16
#define	DE_CTRL_COMMAND_BITBLT			0x00
#define	DE_CTRL_COMMAND_SOLIDFILL		0x01
#define	DE_CTRL_ROP_ENABLE		0x00008000
#define	DE_CTRL_ROP_MASK		0x000000ff
#define	DE_CTRL_ROP_SHIFT			0
#define	DE_CTRL_ROP_SRC				0x0c

/*
 * VPR (Video Parameter Registers)
 */

#define	SM7XX_VPR_BASE			0x0040c000

/*
 * MMIO (SM7XX only)
 */

#define	SM7XX_MMIO_BASE			0x00700000
#define	SM7XX_MMIO_SIZE			0x00004000


code:
/*	$OpenBSD: stsec.c,v 1.4 2010/03/08 20:56:20 miod Exp $	*/

/*
 * Copyright (c) 2010 Miodrag Vallat.
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

/*
 * Gdium ST7 Embedded Controller I2C interface
 */

#include <sys/param.h>
#include <sys/kernel.h>
#include <sys/systm.h>
#include <sys/device.h>
#include <sys/sensors.h>

#include <machine/apmvar.h>
#include <dev/i2c/i2cvar.h>

#include "apm.h"

extern int gdium_revision;

#define	ST7_VERSION	0x00	/* only on later mobos */

#define	ST7_STATUS	0x00
#define	STS_LID_CLOSED		0x01
#define	STS_POWER_BTN_DOWN	0x02
#define	STS_BATTERY_PRESENT	0x04	/* not available on old mobo */
#define	STS_POWER_AVAILABLE	0x08
#define	STS_WAVELAN_BTN_DOWN	0x10	/* ``enable'' on old mobo */
#define	STS_AC_AVAILABLE	0x20
#define	ST7_CONTROL	0x01
#define	STC_DDR_CLOCK		0x01
#define	STC_CHARGE_LED_LIT	0x02
#define	STC_BEEP		0x04
#define	STC_DDR_POWER		0x08
#define	STC_TRICKLE		0x10	/* trickle charge rate */
#define	STC_RADIO_ENABLE	0x20	/* enable wavelan rf, later mobos */
#define	STC_MAIN_POWER		0x40
#define	STC_CHARGE_ENABLE	0x80
#define	ST7_BATTERY_L	0x02
#define	ST7_BATTERY_H	0x03
#define	STB_VALUE(h,l)	(((h) << 2) | ((l) & 0x03))
#define	ST7_SIGNATURE	0x04
#define	STSIG_EC_CONTROL	0x00
#define	STSIG_OS_CONTROL	0xae
/* rough battery operating state limits */
#define STSEC_BAT_MIN_VOLT	7000000	/* 7V */
#define STSEC_BAT_MAX_VOLT	8000000	/* 8V */

const struct {
	const char *desc;
	enum sensor_type type;
} stsec_sensors_template[] = {
#define	STSEC_SENSOR_AC_PRESENCE	0
	{
		.desc = "AC present",
		.type = SENSOR_INDICATOR,
	},
#define	STSEC_SENSOR_BATTERY_PRESENCE	1
	{
		.desc = "Battery present",
		.type = SENSOR_INDICATOR,
	},
#define	STSEC_SENSOR_BATTERY_STATE	2
	{
		.desc = "Battery charging",
		.type = SENSOR_INDICATOR,
	},
#define	STSEC_SENSOR_BATTERY_VOLTAGE	3
	{
		.desc = "Battery voltage",
		.type = SENSOR_VOLTS_DC,
	}
};

struct stsec_softc {
	struct device		 sc_dev;
	i2c_tag_t		 sc_tag;
	i2c_addr_t		 sc_addr;
	uint			 sc_base;

	struct ksensor		 sc_sensors[nitems(stsec_sensors_template)];
	struct ksensordev	 sc_sensordev;
	struct sensor_task	*sc_sensors_update_task;
};

int	stsec_match(struct device *, void *, void *);
void	stsec_attach(struct device *, struct device *, void *);

const struct cfattach stsec_ca = {
	sizeof(struct stsec_softc), stsec_match, stsec_attach
};

struct cfdriver stsec_cd = {
	NULL, "stsec", DV_DULL
};

int	stsec_apminfo(struct apm_power_info *);
int	stsec_read(struct stsec_softc *, uint, int *);
int	stsec_write(struct stsec_softc *, uint, int);
void	stsec_sensors_update(void *);

#if NAPM > 0
struct apm_power_info stsec_apmdata;
const char *stsec_batstate[] = {
	"high",
	"low",
	"critical",
	"charging",
	"unknown"
};
#define BATTERY_STRING(x) ((x) < nitems(stsec_batstate) ? \
	stsec_batstate[x] : stsec_batstate[4])
#endif

int
stsec_match(struct device *parent, void *vcf, void *aux)
{
	struct i2c_attach_args *ia = (struct i2c_attach_args *)aux;
	struct cfdata *cf = (struct cfdata *)vcf;

	return strcmp(ia->ia_name, cf->cf_driver->cd_name) == 0;
}

void
stsec_attach(struct device *parent, struct device *self, void *aux)
{
	struct stsec_softc *sc = (struct stsec_softc *)self;
	struct i2c_attach_args *ia = (struct i2c_attach_args *)aux;
	int rev, sig;
	int rc;
	uint i;

	sc->sc_tag = ia->ia_tag;
	sc->sc_addr = ia->ia_addr;

	/*
	 * Figure out where to get our information, and display microcode
	 * version for geek value if available.
	 */

	sc->sc_base = 0;
	switch (gdium_revision) {
	case 0:
		break;
	default:
		/* read version before sc_base is set */
		rc = stsec_read(sc, ST7_VERSION, &rev);
		if (rc != 0) {
			printf(": can't read microcode revision\n");
			return;
		}
		printf(": revision %d.%d", (rev >> 4) & 0x0f, rev & 0x0f);
		sc->sc_base = ST7_VERSION + 1;
		break;
	}

	printf("\n");

	/*
	 * Better trust the ST7 firmware to control charge operation.
	 */

	rc = stsec_read(sc, ST7_SIGNATURE, &sig);
	if (rc != 0) {
		printf("%s: can't verify charge policy\n", self->dv_xname);
		/* not fatal */
	} else {
		if (sig != STSIG_EC_CONTROL)
			stsec_write(sc, ST7_SIGNATURE, STSIG_EC_CONTROL);
	}

	/*
	 * Setup sensors. We use a quite short refresh interval to react
	 * quickly enough to button presses.
	 * XXX but we don't do anything on lid or button presses... yet
	 */

	strlcpy(sc->sc_sensordev.xname, self->dv_xname,
	    sizeof(sc->sc_sensordev.xname));
	sc->sc_sensors_update_task =
	    sensor_task_register(sc, stsec_sensors_update, 2);
	if (sc->sc_sensors_update_task == NULL) {
		printf("%s: can't initialize refresh task\n", self->dv_xname);
		return;
	}

	for (i = 0; i < nitems(sc->sc_sensors); i++) {
		sc->sc_sensors[i].type = stsec_sensors_template[i].type;
		strlcpy(sc->sc_sensors[i].desc, stsec_sensors_template[i].desc,
		    sizeof(sc->sc_sensors[i].desc));
		sensor_attach(&sc->sc_sensordev, &sc->sc_sensors[i]);
	}
	sensordev_install(&sc->sc_sensordev);
#if NAPM > 0
	/* make sure we have the apm state initialized before apm attaches */
	stsec_sensors_update(sc);
	apm_setinfohook(stsec_apminfo);
#endif
}

int
stsec_read(struct stsec_softc *sc, uint reg, int *value)
{
	uint8_t regno, data;
	int rc;

	regno = sc->sc_base + reg;
	iic_acquire_bus(sc->sc_tag, 0);
	rc = iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, sc->sc_addr,
	    &regno, sizeof regno, &data, sizeof data, 0);
	iic_release_bus(sc->sc_tag, 0);

	if (rc == 0)
		*value = (int)data;
	return rc;
}

int
stsec_write(struct stsec_softc *sc, uint reg, int val)
{
	uint8_t regno, data[1];
	int rc;

	regno = sc->sc_base + reg;
	data[0] = (uint8_t)val;
	iic_acquire_bus(sc->sc_tag, 0);
	rc = iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP, sc->sc_addr,
	    &regno, sizeof regno, data, sizeof data[0], 0);
	iic_release_bus(sc->sc_tag, 0);
	return rc;
}

void
stsec_sensors_update(void *vsc)
{
	struct stsec_softc *sc = (struct stsec_softc *)vsc;
	int status, control, batl, bath;
	ulong batuv;
	struct ksensor *ks;
	uint i;
#if NAPM > 0
	struct apm_power_info old;
	uint cap_pct;
#endif

	for (i = 0; i < nitems(sc->sc_sensors); i++)
		sc->sc_sensors[i].flags |= SENSOR_FINVALID;

	if (stsec_read(sc, ST7_STATUS, &status) != 0 ||
	    stsec_read(sc, ST7_CONTROL, &control) != 0 ||
	    stsec_read(sc, ST7_BATTERY_L, &batl) != 0 ||
	    stsec_read(sc, ST7_BATTERY_H, &bath) != 0)
		return;

	/*
	 * Battery voltage is in 10/1024V units, in the 0-1023 range.
	 */
	batuv = ((ulong)STB_VALUE(bath, batl) * 10 * 1000000) / 1024;

	ks = &sc->sc_sensors[STSEC_SENSOR_AC_PRESENCE];
	ks->value = !!ISSET(status, STS_AC_AVAILABLE);
	ks->flags &= ~SENSOR_FINVALID;

	/*
	 * Old mobo design does not have a battery presence bit; the Linux
	 * code decides there is no battery if the reported battery voltage
	 * is too low, we'll do the same.
	 */
	ks = &sc->sc_sensors[STSEC_SENSOR_BATTERY_PRESENCE];
	switch (gdium_revision) {
	case 0:
		if (ISSET(status, STS_AC_AVAILABLE))
			ks->value = batuv > 500000;
		else
			ks->value = 1;
		break;
	default:
		ks->value = !!ISSET(status, STS_BATTERY_PRESENT);
		break;
	}
	ks->flags &= ~SENSOR_FINVALID;

	ks = &sc->sc_sensors[STSEC_SENSOR_BATTERY_STATE];
	ks->value = !!ISSET(control, STC_CHARGE_ENABLE);
	ks->flags &= ~SENSOR_FINVALID;

	ks = &sc->sc_sensors[STSEC_SENSOR_BATTERY_VOLTAGE];
	ks->value = (int64_t)batuv;
	ks->flags &= ~SENSOR_FINVALID;

#if NAPM > 0
	bcopy(&stsec_apmdata, &old, sizeof(old));

	if (batuv < STSEC_BAT_MIN_VOLT)
		batuv = STSEC_BAT_MIN_VOLT;
	else if (batuv > STSEC_BAT_MAX_VOLT)
		batuv = STSEC_BAT_MAX_VOLT;
	cap_pct = (batuv - STSEC_BAT_MIN_VOLT) * 100 / (STSEC_BAT_MAX_VOLT -
	    STSEC_BAT_MIN_VOLT);
	stsec_apmdata.battery_life = cap_pct;

	stsec_apmdata.ac_state = ISSET(status, STS_AC_AVAILABLE) ? APM_AC_ON :
	    APM_AC_OFF;
	if (!sc->sc_sensors[STSEC_SENSOR_BATTERY_PRESENCE].value) {
		stsec_apmdata.battery_state = APM_BATTERY_ABSENT;
		stsec_apmdata.minutes_left = 0;
		stsec_apmdata.battery_life = 0;
	} else {
		if (ISSET(control, STC_CHARGE_ENABLE))
			stsec_apmdata.battery_state = APM_BATT_CHARGING;
		/* XXX arbitrary */
		else if (cap_pct < 10)
			stsec_apmdata.battery_state = APM_BATT_CRITICAL;
		else if (cap_pct > 60)
			stsec_apmdata.battery_state = APM_BATT_HIGH;
		else
			stsec_apmdata.battery_state = APM_BATT_LOW;

		stsec_apmdata.minutes_left = -1; /* unknown */
	}
	if (old.ac_state != stsec_apmdata.ac_state)
		apm_record_event(APM_POWER_CHANGE, "AC power",
			stsec_apmdata.ac_state ? "restored" : "lost");
	if (old.battery_state != stsec_apmdata.battery_state)
		apm_record_event(APM_POWER_CHANGE, "battery",
		    BATTERY_STRING(stsec_apmdata.battery_state));
#endif
}

#if NAPM > 0
int
stsec_apminfo(struct apm_power_info *info)
{
	 bcopy(&stsec_apmdata, info, sizeof(struct apm_power_info));
	 return 0;
}
#endif


code:
/*	$OpenBSD: voyager.c,v 1.4 2010/09/20 06:33:48 matthew Exp $	*/

/*
 * Copyright (c) 2010 Miodrag Vallat.
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

/*
 * Silicon Motion SM501/SM502 (VoyagerGX) master driver.
 */

#include <sys/param.h>
#include <sys/systm.h>
#include <sys/device.h>
#include <sys/gpio.h>

#include <machine/bus.h>
#include <machine/cpu.h>
#include <machine/intr.h>

#include <dev/gpio/gpiovar.h>

#include <dev/pci/pcireg.h>
#include <dev/pci/pcivar.h>
#include <dev/pci/pcidevs.h>

#include <loongson/dev/bonito_irq.h>	/* for BONITO_NINTS */
#include <loongson/dev/voyagerreg.h>
#include <loongson/dev/voyagervar.h>

struct voyager_softc {
	struct device		 sc_dev;

	bus_space_tag_t		 sc_fbt;
	bus_space_handle_t	 sc_fbh;
	bus_size_t		 sc_fbsize;

	bus_space_tag_t		 sc_mmiot;
	bus_space_handle_t	 sc_mmioh;
	bus_size_t		 sc_mmiosize;

	struct gpio_chipset_tag	 sc_gpio_tag;
	gpio_pin_t		 sc_gpio_pins[32 + 32];

	void			*sc_ih;
	struct intrhand		*sc_intr[32];
};

int	voyager_match(struct device *, void *, void *);
void	voyager_attach(struct device *, struct device *, void *);

const struct cfattach voyager_ca = {
	sizeof(struct voyager_softc), voyager_match, voyager_attach
};

struct cfdriver voyager_cd = {
	NULL, "voyager", DV_DULL
};

void	voyager_attach_gpio(struct voyager_softc *);
int	voyager_intr(void *);
int	voyager_print(void *, const char *);
int	voyager_search(struct device *, void *, void *);

const struct pci_matchid voyager_devices[] = {
	/*
	 * 502 shares the same device ID as 501, but uses a different
	 * revision number.
	 */
	{ PCI_VENDOR_SMI, PCI_PRODUCT_SMI_SM501 }
};

int
voyager_match(struct device *parent, void *vcf, void *aux)
{
	struct pci_attach_args *pa = (struct pci_attach_args *)aux;

	return pci_matchbyid(pa, voyager_devices, nitems(voyager_devices));
}

void
voyager_attach(struct device *parent, struct device *self, void *aux)
{
	struct voyager_softc *sc = (struct voyager_softc *)self;
	struct pci_attach_args *pa = (struct pci_attach_args *)aux;
	pci_intr_handle_t ih;
	const char *intrstr;

	printf(": ");

	/*
	 * Map registers.
	 */

	if (pci_mapreg_map(pa, PCI_MAPREG_START, PCI_MAPREG_TYPE_MEM,
	    BUS_SPACE_MAP_LINEAR, &sc->sc_fbt, &sc->sc_fbh,
	    NULL, &sc->sc_fbsize, 0) != 0) {
		printf("can't map frame buffer\n");
		return;
	}

	if (pci_mapreg_map(pa, PCI_MAPREG_START + 0x04, PCI_MAPREG_TYPE_MEM,
	    BUS_SPACE_MAP_LINEAR, &sc->sc_mmiot, &sc->sc_mmioh,
	    NULL, &sc->sc_mmiosize, 0) != 0) {
		printf("can't map mmio\n");
		goto fail1;
	}

	/*
	 * Setup interrut handling.
	 */

	bus_space_write_4(sc->sc_mmiot, sc->sc_mmioh, VOYAGER_RAW_ICR,
	    0xffffffff);
	bus_space_write_4(sc->sc_mmiot, sc->sc_mmioh, VOYAGER_IMR, 0);
	(void)bus_space_read_4(sc->sc_mmiot, sc->sc_mmioh, VOYAGER_IMR);

	if (pci_intr_map(pa, &ih) != 0) {
		printf("can't map interrupt\n");
		goto fail2;
	}
	intrstr = pci_intr_string(pa->pa_pc, ih);
	sc->sc_ih = pci_intr_establish(pa->pa_pc, ih, IPL_TTY, voyager_intr,
	    sc, self->dv_xname);
	if (sc->sc_ih == NULL) {
		printf("can't establish interrupt");
		if (intrstr != NULL)
			printf(" at %s", intrstr);
		printf("\n");
		goto fail2;
	}

	printf("%s\n", intrstr);

	/*
	 * Attach GPIO devices.
	 */
	voyager_attach_gpio(sc);

	/*
	 * Attach child devices.
	 */
	config_search(voyager_search, self, pa);

	return;
fail2:
	bus_space_unmap(sc->sc_mmiot, sc->sc_mmioh, sc->sc_mmiosize);
fail1:
	bus_space_unmap(sc->sc_fbt, sc->sc_fbh, sc->sc_fbsize);
}

int
voyager_print(void *args, const char *parentname)
{
	struct voyager_attach_args *vaa = (struct voyager_attach_args *)args;

	if (parentname != NULL)
		printf("%s at %s", vaa->vaa_name, parentname);

	return UNCONF;
}

int
voyager_search(struct device *parent, void *vcf, void *args)
{
	struct voyager_softc *sc = (struct voyager_softc *)parent;
	struct cfdata *cf = (struct cfdata *)vcf;
	struct pci_attach_args *pa = (struct pci_attach_args *)args;
	struct voyager_attach_args vaa;

	/*
	 * Caller should have attached gpio already. If it didn't, bail
	 * out here.
	 */
	if (strcmp(cf->cf_driver->cd_name, "gpio") == 0)
		return 0;

	vaa.vaa_name = cf->cf_driver->cd_name;
	vaa.vaa_pa = pa;
	vaa.vaa_fbt = sc->sc_fbt;
	vaa.vaa_fbh = sc->sc_fbh;
	vaa.vaa_mmiot = sc->sc_mmiot;
	vaa.vaa_mmioh = sc->sc_mmioh;

	if (cf->cf_attach->ca_match(parent, cf, &vaa) == 0)
		return 0;

	config_attach(parent, cf, &vaa, voyager_print);
	return 1;
}

/*
 * Interrupt disatcher
 */

int
voyager_intr(void *vsc)
{
	struct voyager_softc *sc = (struct voyager_softc *)vsc;
	uint32_t isr, imr, mask, bitno;
	struct intrhand *ih;

	isr = bus_space_read_4(sc->sc_mmiot, sc->sc_mmioh, VOYAGER_ISR);
	imr = bus_space_read_4(sc->sc_mmiot, sc->sc_mmioh, VOYAGER_IMR);

	isr &= imr;
	if (isr == 0)
		return 0;

	for (bitno = 0, mask = 1 << 0; isr != 0; bitno++, mask <<= 1) {
		if ((isr & mask) == 0)
			continue;
		isr ^= mask;
		for (ih = sc->sc_intr[bitno]; ih != NULL; ih = ih->ih_next) {
			if ((*ih->ih_fun)(ih->ih_arg) != 0)
				ih->ih_count.ec_count++;
		}
	}

	return 1;
}

void *
voyager_intr_establish(void *cookie, int irq, int level, int (*fun)(void *),
    void *arg, const char *name)
{
	struct voyager_softc *sc = (struct voyager_softc *)cookie;
	struct intrhand *prevh, *nh;
	uint32_t imr;

#ifdef DIAGNOSTIC
	if (irq < 0 || irq >= nitems(sc->sc_intr))
		return NULL;
#endif

	nh = (struct intrhand *)malloc(sizeof *nh, M_DEVBUF, M_NOWAIT | M_ZERO);
	if (nh == NULL)
		return NULL;

	nh->ih_fun = fun;
	nh->ih_arg = arg;
	nh->ih_level = level;
	nh->ih_irq = irq + BONITO_NINTS;
	evcount_attach(&nh->ih_count, name, &nh->ih_irq);

	if (sc->sc_intr[irq] == NULL)
		sc->sc_intr[irq] = nh;
	else {
		/* insert at tail */
		for (prevh = sc->sc_intr[irq]; prevh->ih_next != NULL;
		    prevh = prevh->ih_next) ;
		prevh->ih_next = nh;
	}

	/* enable interrupt source */
	imr = bus_space_read_4(sc->sc_mmiot, sc->sc_mmioh, VOYAGER_IMR);
	imr |= 1 << irq;
	bus_space_write_4(sc->sc_mmiot, sc->sc_mmioh, VOYAGER_IMR, imr);
	(void)bus_space_read_4(sc->sc_mmiot, sc->sc_mmioh, VOYAGER_IMR);

	return nh;
}

const char *
voyager_intr_string(void *vih)
{
	struct intrhand *ih = (struct intrhand *)vih;
	static char intrstr[1 + 32];

	snprintf(intrstr, sizeof intrstr, "voyager irq %d",
	    ih->ih_irq - BONITO_NINTS);
	return intrstr;
}

/*
 * GPIO support code
 */

int	voyager_gpio_pin_read(void *, int);
void	voyager_gpio_pin_write(void *, int, int);
void	voyager_gpio_pin_ctl(void *, int, int);

static const struct gpio_chipset_tag voyager_gpio_tag = {
	.gp_pin_read = voyager_gpio_pin_read,
	.gp_pin_write = voyager_gpio_pin_write,
	.gp_pin_ctl = voyager_gpio_pin_ctl
};

int
voyager_gpio_pin_read(void *cookie, int pin)
{
	struct voyager_softc *sc = (struct voyager_softc *)cookie;
	bus_addr_t reg;
	int32_t data, mask;

	if (pin >= 32) {
		pin -= 32;
		reg = VOYAGER_GPIO_DATA_HIGH;
	} else {
		reg = VOYAGER_GPIO_DATA_LOW;
	}
	mask = 1 << pin;

	data = bus_space_read_4(sc->sc_mmiot, sc->sc_mmioh, reg);
	return data & mask ? GPIO_PIN_HIGH : GPIO_PIN_LOW;
}

void
voyager_gpio_pin_write(void *cookie, int pin, int val)
{
	struct voyager_softc *sc = (struct voyager_softc *)cookie;
	bus_addr_t reg;
	int32_t data, mask;

	if (pin >= 32) {
		pin -= 32;
		reg = VOYAGER_GPIO_DATA_HIGH;
	} else {
		reg = VOYAGER_GPIO_DATA_LOW;
	}
	mask = 1 << pin;
	data = bus_space_read_4(sc->sc_mmiot, sc->sc_mmioh, reg);
	if (val)
		data |= mask;
	else
		data &= ~mask;
	bus_space_write_4(sc->sc_mmiot, sc->sc_mmioh, reg, data);
	(void)bus_space_read_4(sc->sc_mmiot, sc->sc_mmioh, reg);
}

void
voyager_gpio_pin_ctl(void *cookie, int pin, int flags)
{
	struct voyager_softc *sc = (struct voyager_softc *)cookie;
	bus_addr_t reg;
	int32_t data, mask;

	if (pin >= 32) {
		pin -= 32;
		reg = VOYAGER_GPIO_DIR_HIGH;
	} else {
		reg = VOYAGER_GPIO_DIR_LOW;
	}
	mask = 1 << pin;
	data = bus_space_read_4(sc->sc_mmiot, sc->sc_mmioh, reg);
	if (ISSET(flags, GPIO_PIN_OUTPUT))
		data |= mask;
	else
		data &= ~mask;
	bus_space_write_4(sc->sc_mmiot, sc->sc_mmioh, reg, data);
	(void)bus_space_read_4(sc->sc_mmiot, sc->sc_mmioh, reg);
}

void
voyager_attach_gpio(struct voyager_softc *sc)
{
	struct gpiobus_attach_args gba;
	int pin;
	uint32_t control, value;

	bcopy(&voyager_gpio_tag, &sc->sc_gpio_tag, sizeof voyager_gpio_tag);
	sc->sc_gpio_tag.gp_cookie = sc;

	control = bus_space_read_4(sc->sc_mmiot, sc->sc_mmioh,
	    VOYAGER_GPIOL_CONTROL);
	value = bus_space_read_4(sc->sc_mmiot, sc->sc_mmioh,
	    VOYAGER_GPIO_DATA_LOW);
	for (pin = 0; pin < 32; pin++) {
		sc->sc_gpio_pins[pin].pin_num = pin;
		if ((control & 1) == 0) {
			sc->sc_gpio_pins[pin].pin_caps =
			    GPIO_PIN_INPUT | GPIO_PIN_OUTPUT;
			sc->sc_gpio_pins[pin].pin_state = value & 1;
		} else {
			/* disable control of taken over pins */
			sc->sc_gpio_pins[pin].pin_caps = 0;
			sc->sc_gpio_pins[pin].pin_state = 0;
		}
	}

	control = bus_space_read_4(sc->sc_mmiot, sc->sc_mmioh,
	    VOYAGER_GPIOH_CONTROL);
	value = bus_space_read_4(sc->sc_mmiot, sc->sc_mmioh,
	    VOYAGER_GPIO_DATA_HIGH);
	for (pin = 32 + 0; pin < 32 + 32; pin++) {
		sc->sc_gpio_pins[pin].pin_num = pin;
		if ((control & 1) == 0) {
			sc->sc_gpio_pins[pin].pin_caps =
			    GPIO_PIN_INPUT | GPIO_PIN_OUTPUT;
			sc->sc_gpio_pins[pin].pin_state = value & 1;
		} else {
			/* disable control of taken over pins */
			sc->sc_gpio_pins[pin].pin_caps = 0;
			sc->sc_gpio_pins[pin].pin_state = 0;
		}
	}

	gba.gba_name = "gpio";
	gba.gba_gc = &sc->sc_gpio_tag;
	gba.gba_pins = sc->sc_gpio_pins;
	gba.gba_npins = nitems(sc->sc_gpio_pins);

	config_found(&sc->sc_dev, &gba, voyager_print);
}


code:
/*	$OpenBSD: voyagerreg.h,v 1.3 2010/08/27 12:48:54 miod Exp $	*/

/*
 * Copyright (c) 2010 Miodrag Vallat.
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

/*
 * Silicon Motion SM501/SM502 registers
 */

#define	SM5XX_MMIO_BASE			0x000000
#define	SM5XX_MMIO_SIZE			0x010000

#define	VOYAGER_SYSTEM_CONTROL		0x0000
#define	VSC_DPMS_VSYNC_DISABLE		0x80000000
#define	VSC_DPMS_HSYNC_DISABLE		0x40000000
#define	VSC_COLOR_CONVERSION_BUSY	0x10000000
#define	VSC_FIFO_EMPTY			0x00100000
#define	VSC_2DENGINE_BUSY		0x00080000
#define	VSC_2DENGINE_ABORT		0x00003000	/* not a typo */
#define	VOYAGER_MISC_CONTROL		0x0004
#define	VOYAGER_GPIOL_CONTROL		0x0008
#define	VOYAGER_GPIOH_CONTROL		0x000c
#define	VOYAGER_DRAM_CONTROL		0x0010
#define	VOYAGER_ARB_CONTROL		0x0014

#define	VOYAGER_COMMANDLIST_CONTROL	0x0018
#define	VOYAGER_COMMANDLIST_CONDITION	0x001c
#define	VOYAGER_COMMANDLIST_RETURN	0x0020
#define	VOYAGER_COMMANDLIST_STATUS	0x0024
#define	VCS_2M				0x00100000
#define	VCS_CF				0x00080000
#define	VCS_2C				0x00040000
#define	VCS_DM				0x00020000
#define	VCS_CS				0x00010000
#define	VCS_VF				0x00008000
#define	VCS_VS				0x00004000
#define	VCS_PS				0x00002000
#define	VCS_SC				0x00001000
#define	VCS_SP				0x00000800
#define	VCS_2S				0x00000004
#define	VCS_2F				0x00000002
#define	VCS_2E				0x00000001

#define	VOYAGER_RAW_ISR			0x0028
#define	VOYAGER_RAWINTR_ZV1				6
#define	VOYAGER_RAWINTR_USB_PLUGIN			5
#define	VOYAGER_RAWINTR_ZV0				4
#define	VOYAGER_RAWINTR_CRT_VSYNC			3
#define	VOYAGER_RAWINTR_USB_SLAVE			2
#define	VOYAGER_RAWINTR_PANEL_VSYNC			1
#define	VOYAGER_RAWINTR_COMMAND_INTERPRETER		0
#define	VOYAGER_RAW_ICR			0x0028
#define	VOYAGER_ISR			0x002c
#define	VOYAGER_INTR_USB_PLUGIN				31
#define	VOYAGER_INTR_GPIO54				30
#define	VOYAGER_INTR_GPIO53				29
#define	VOYAGER_INTR_GPIO52				28
#define	VOYAGER_INTR_GPIO51				27
#define	VOYAGER_INTR_GPIO50				26
#define	VOYAGER_INTR_GPIO49				25
#define	VOYAGER_INTR_GPIO48				24
#define	VOYAGER_INTR_I2C				23
#define	VOYAGER_INTR_PWM				22
#define	VOYAGER_INTR_DMA				20
#define	VOYAGER_INTR_PCI				19
#define	VOYAGER_INTR_I2S				18
#define	VOYAGER_INTR_AC97				17
#define	VOYAGER_INTR_USB_SLAVE				16
#define	VOYAGER_INTR_UART1				13
#define	VOYAGER_INTR_UART0				12
#define	VOYAGER_INTR_CRT_VSYNC				11
#define	VOYAGER_INTR_8051				10
#define	VOYAGER_INTR_SSP1				9
#define	VOYAGER_INTR_SSP0				8
#define	VOYAGER_INTR_USB_HOST				6
#define	VOYAGER_INTR_ZV1				4
#define	VOYAGER_INTR_2DENGINE				3
#define	VOYAGER_INTR_ZV0				2
#define	VOYAGER_INTR_PANEL_VSYNC			1
#define	VOYAGER_INTR_COMMAND_INTERPRETER		0
#define	VOYAGER_IMR			0x0030
#define	VOYAGER_DEBUG			0x0034

#define	VOYAGER_PM_CURRENT_GATE		0x0038
#define	VOYAGER_PM_CURRENT_CLOCK	0x003c
#define	VOYAGER_PM_MODE0_GATE		0x0040
#define	VOYAGER_PM_MODE0_CLOCK		0x0044
#define	VOYAGER_PM_MODE1_GATE		0x0048
#define	VOYAGER_PM_MODE1_CLOCK		0x004c
#define	VOYAGER_PM_SLEEP_GATE		0x0050
#define	VOYAGER_PM_CONTROL		0x0054

#define	VOYAGER_MASTER_PCI_BASE		0x0058
#define	VOYAGER_ENDIAN_CONTROL		0x005c
#define	VOYAGER_DEVICE_ID		0x0060
#define	VOYAGER_PLL_COUNT		0x0064
#define	VOYAGER_MISC			0x0068
#define	VOYAGER_SDRAM_CLOCK		0x006c
#define	VOYAGER_NON_CACHE_ADDRESS	0x0070
#define	VOYAGER_PLL_CONTROL		0x0074

/*
 * GPIO
 */

#define	VOYAGER_GPIO_DATA_LOW		0x010000
#define	VOYAGER_GPIO_DATA_HIGH		0x010004
#define	VOYAGER_GPIO_DIR_LOW		0x010008
#define	VOYAGER_GPIO_DIR_HIGH		0x01000c

/*
 * OHCI
 */

#define	VOYAGER_OHCI_BASE		0x040000
#define	VOYAGER_OHCI_SIZE		0x020000

/*
 * Display Controller
 */

#define	SM5XX_DCR_BASE			0x080000
#define	SM5XX_DCR_SIZE			0x010000

#define	DCR_PANEL_DISPLAY_CONTROL	0x0000
#define	PDC_EN				0x08000000
#define	PDC_BIAS			0x04000000
#define	PDC_DATA			0x02000000
#define	PDC_VDD				0x01000000


code:
/*	$OpenBSD: voyagervar.h,v 1.2 2010/02/26 14:53:11 miod Exp $	*/

/*
 * Copyright (c) 2010 Miodrag Vallat.
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

struct voyager_attach_args {
	const char			*vaa_name;

	struct pci_attach_args		*vaa_pa;
	bus_space_tag_t			 vaa_fbt;
	bus_space_handle_t		 vaa_fbh;
	bus_space_tag_t			 vaa_mmiot;
	bus_space_handle_t		 vaa_mmioh;
};

void	*voyager_intr_establish(void *, int, int, int (*)(void *), void *,
	    const char *);
const char *
	 voyager_intr_string(void *);


path: sys/arch/loongson/include/CVS/Entries


path: sys/arch/loongson/include/CVS/Tag


code:
/*	$OpenBSD: _float.h,v 1.1 2012/06/26 16:12:44 deraadt Exp $ */

#include <mips64/_float.h>


code:
/* $OpenBSD: _types.h,v 1.1.1.1 2009/07/31 09:26:25 miod Exp $ */
/* public domain */
#include <mips64/_types.h>


code:
/*	$OpenBSD: apmvar.h,v 1.4 2015/02/07 22:14:43 miod Exp $	*/

/*
 *  Copyright (c) 2001 Alexander Guy
 *  Copyright (c) 1995 John T. Kohl
 *  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.
 *
 */
#ifndef _MACHINE_APMVAR_H_
#define _MACHINE_APMVAR_H_

#include <sys/ioccom.h>

/* Advanced Power Management (v1.0 and v1.1 specification)
 * functions/defines/etc.
 */

/* These definitions make up the heart of the user-land interface
 * to the APM devices.
 */

#define		APM_AC_OFF		0x00
#define		APM_AC_ON		0x01
#define		APM_AC_BACKUP		0x02
#define		APM_AC_UNKNOWN		0xff
#define		APM_BATT_HIGH		0x00
#define		APM_BATT_LOW		0x01
#define		APM_BATT_CRITICAL	0x02
#define		APM_BATT_CHARGING	0x03
#define		APM_BATT_UNKNOWN	0xff
#define		APM_BATT_LIFE_UNKNOWN	0xff

#define		APM_NOEVENT		0x0000
#define		APM_STANDBY_REQ		0x0001
#define		APM_SUSPEND_REQ		0x0002
#define		APM_NORMAL_RESUME	0x0003
#define		APM_CRIT_RESUME		0x0004 /* suspend/resume happened
						  without us */
#define		APM_BATTERY_LOW		0x0005
#define		APM_POWER_CHANGE	0x0006
#define		APM_UPDATE_TIME		0x0007
#define		APM_CRIT_SUSPEND_REQ	0x0008
#define		APM_USER_STANDBY_REQ	0x0009
#define		APM_USER_SUSPEND_REQ	0x000A
#define		APM_SYS_STANDBY_RESUME	0x000B
#define		APM_CAPABILITY_CHANGE	0x000C	/* apm v1.2 */
#define		APM_USER_HIBERNATE_REQ	0x000D
#define		APM_EVENT_MASK		0xffff

#define	APM_EVENT_COMPOSE(t,i)	((((i) & 0x7fff) << 16)|((t) & APM_EVENT_MASK))
#define	APM_EVENT_TYPE(e)	((e) & APM_EVENT_MASK)
#define	APM_EVENT_INDEX(e)	((e) >> 16)

/*
 * LP (Laptop Package)
 *
 * Copyright (C) 1994 by HOSOKAWA Tatsumi <hosokawa@mt.cs.keio.ac.jp>
 *
 * This software may be used, modified, copied, and distributed, in
 * both source and binary form provided that the above copyright and
 * these terms are retained. Under no circumstances is the author
 * responsible for the proper functioning of this software, nor does
 * the author assume any responsibility for damages incurred with its
 * use.
 *
 * Sep., 1994	Implemented on FreeBSD 1.1.5.1R (Toshiba AVS001WD)
 */

#define APM_BATTERY_ABSENT 4

struct apm_power_info {
	u_char battery_state;
	u_char ac_state;
	u_char battery_life;
	u_char spare1;
	u_int minutes_left;		/* estimate */
	u_int spare2[6];
};

struct apm_ctl {
	u_int dev;
	u_int mode;
};

#define	APM_IOC_REJECT	_IOW('A', 0, struct apm_event_info) /* reject request # */
#define	APM_IOC_STANDBY	_IO('A', 1)	/* put system into standby */
#define	APM_IOC_SUSPEND	_IO('A', 2)	/* put system into suspend */
#define	APM_IOC_GETPOWER _IOR('A', 3, struct apm_power_info) /* fetch battery state */
#define	APM_IOC_DEV_CTL	_IOW('A', 5, struct apm_ctl) /* put device into mode */
#define APM_IOC_PRN_CTL _IOW('A', 6, int ) /* driver power status msg */
#define		APM_PRINT_ON	0	/* driver power status displayed */
#define		APM_PRINT_OFF	1	/* driver power status not displayed */
#define		APM_PRINT_PCT	2	/* driver power status only displayed
					   if the percentage changes */
#define	APM_IOC_STANDBY_REQ	_IO('A', 7)	/* request standby */
#define	APM_IOC_SUSPEND_REQ	_IO('A', 8)	/* request suspend */
#define	APM_IOC_HIBERNATE	_IO('A', 9)	/* put system into hibernate */

#ifdef _KERNEL
void apm_setinfohook(int (*)(struct apm_power_info *));
int apm_record_event(u_int, const char *, const char *);
#endif

#endif /* _MACHINE_APMVAR_H_ */


code:
/* $OpenBSD: asm.h,v 1.1.1.1 2009/07/31 09:26:25 miod Exp $ */
/* public domain */
#include <mips64/asm.h>


code:
/* $OpenBSD: atomic.h,v 1.1.1.1 2009/07/31 09:26:25 miod Exp $ */
/* public domain */
#include <mips64/atomic.h>


code:
/*	$OpenBSD: autoconf.h,v 1.11 2014/03/29 23:59:49 miod Exp $ */

/*
 * Copyright (c) 2001-2003 Opsycon AB  (www.opsycon.se / www.opsycon.com)
 *
 * 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.
 *
 * 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.
 *
 */

/*
 * Definitions used by autoconfiguration.
 */

#ifndef _MACHINE_AUTOCONF_H_
#define _MACHINE_AUTOCONF_H_

#include <machine/bus.h>

struct bonito_config;
struct mips_isa_chipset;

/*
 * List of legacy I/O ranges.
 */
struct legacy_io_range {
	bus_addr_t	start;
	bus_size_t	end;	/* inclusive */
};

/*
 * Per platform information.
 */
struct platform {
	int				 system_type;
#define	LOONGSON_2E		0x0000	/* Generic Loongson 2E system */
#define	LOONGSON_YEELOONG	0x0001	/* Lemote Yeeloong */
#define	LOONGSON_GDIUM		0x0002	/* EMTEC Gdium Liberty */
#define	LOONGSON_FULOONG	0x0003	/* Lemote Fuloong */
#define	LOONGSON_LYNLOONG	0x0004	/* Lemote Lynloong */
#define	LOONGSON_EBT700		0x0005	/* eBenton EBT700 */
#define	LOONGSON_3A		0x0066	/* Loongson 2Gq or 3A based system */

	char				*vendor;
	char				*product;

	const struct bonito_config	*bonito_config;
	struct mips_isa_chipset		*isa_chipset;
	const struct legacy_io_range	*legacy_io_ranges;

	void				(*setup)(void);
	void				(*device_register)(struct device *,
					    void *);

	void				(*powerdown)(void);
	void				(*reset)(void);
	int				(*suspend)(void);
	int				(*resume)(void);
};

extern const struct platform *sys_platform;
extern uint loongson_ver;

struct mainbus_attach_args {
	const char	*maa_name;
};

extern struct device *bootdv;
extern char bootdev[];
extern enum devclass bootdev_class;

extern bus_space_tag_t early_mem_t;
extern bus_space_tag_t early_io_t;

#include <mips64/autoconf.h>

#endif /* _MACHINE_AUTOCONF_H_ */


code:
/*	$OpenBSD: bus.h,v 1.6 2014/05/24 21:11:01 miod Exp $	*/

/*
 * Copyright (c) 2003-2004 Opsycon AB Sweden.  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.
 *
 * 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.
 */

#ifndef _MACHINE_BUS_H_
#define _MACHINE_BUS_H_

#ifdef __STDC__
#define CAT(a,b)	a##b
#define CAT3(a,b,c)	a##b##c
#else
#define CAT(a,b)	a/**/b
#define CAT3(a,b,c)	a/**/b/**/c
#endif

/*
 * Bus access types.
 */
struct mips_bus_space;
typedef u_long bus_addr_t;
typedef u_long bus_size_t;
typedef u_long bus_space_handle_t;
typedef struct mips_bus_space *bus_space_tag_t;

struct mips_bus_space {
	bus_addr_t	bus_base;
	void		*bus_private;
	u_int8_t	(*_space_read_1)(bus_space_tag_t , bus_space_handle_t,
			  bus_size_t);
	void		(*_space_write_1)(bus_space_tag_t , bus_space_handle_t,
			  bus_size_t, u_int8_t);
	u_int16_t	(*_space_read_2)(bus_space_tag_t , bus_space_handle_t,
			  bus_size_t);
	void		(*_space_write_2)(bus_space_tag_t , bus_space_handle_t,
			  bus_size_t, u_int16_t);
	u_int32_t	(*_space_read_4)(bus_space_tag_t , bus_space_handle_t,
			  bus_size_t);
	void		(*_space_write_4)(bus_space_tag_t , bus_space_handle_t,
			  bus_size_t, u_int32_t);
	u_int64_t	(*_space_read_8)(bus_space_tag_t , bus_space_handle_t,
			  bus_size_t);
	void		(*_space_write_8)(bus_space_tag_t , bus_space_handle_t,
			  bus_size_t, u_int64_t);
	void		(*_space_read_raw_2)(bus_space_tag_t, bus_space_handle_t,
			  bus_addr_t, u_int8_t *, bus_size_t);
	void		(*_space_write_raw_2)(bus_space_tag_t, bus_space_handle_t,
			  bus_addr_t, const u_int8_t *, bus_size_t);
	void		(*_space_read_raw_4)(bus_space_tag_t, bus_space_handle_t,
			  bus_addr_t, u_int8_t *, bus_size_t);
	void		(*_space_write_raw_4)(bus_space_tag_t, bus_space_handle_t,
			  bus_addr_t, const u_int8_t *, bus_size_t);
	void		(*_space_read_raw_8)(bus_space_tag_t, bus_space_handle_t,
			  bus_addr_t, u_int8_t *, bus_size_t);
	void		(*_space_write_raw_8)(bus_space_tag_t, bus_space_handle_t,
			  bus_addr_t, const u_int8_t *, bus_size_t);
	int		(*_space_map)(bus_space_tag_t , bus_addr_t,
			  bus_size_t, int, bus_space_handle_t *);
	void		(*_space_unmap)(bus_space_tag_t, bus_space_handle_t,
			  bus_size_t);
	int		(*_space_subregion)(bus_space_tag_t, bus_space_handle_t,
			  bus_size_t, bus_size_t, bus_space_handle_t *);
	void *		(*_space_vaddr)(bus_space_tag_t, bus_space_handle_t);
	paddr_t		(*_space_mmap)(bus_space_tag_t, bus_addr_t, off_t,
			    int, int);
};

#define	bus_space_read_1(t, h, o) (*(t)->_space_read_1)((t), (h), (o))
#define	bus_space_read_2(t, h, o) (*(t)->_space_read_2)((t), (h), (o))
#define	bus_space_read_4(t, h, o) (*(t)->_space_read_4)((t), (h), (o))
#define	bus_space_read_8(t, h, o) (*(t)->_space_read_8)((t), (h), (o))

#define	bus_space_write_1(t, h, o, v) (*(t)->_space_write_1)((t), (h), (o), (v))
#define	bus_space_write_2(t, h, o, v) (*(t)->_space_write_2)((t), (h), (o), (v))
#define	bus_space_write_4(t, h, o, v) (*(t)->_space_write_4)((t), (h), (o), (v))
#define	bus_space_write_8(t, h, o, v) (*(t)->_space_write_8)((t), (h), (o), (v))

#define	bus_space_read_raw_multi_2(t, h, a, b, l) \
	(*(t)->_space_read_raw_2)((t), (h), (a), (b), (l))
#define	bus_space_read_raw_multi_4(t, h, a, b, l) \
	(*(t)->_space_read_raw_4)((t), (h), (a), (b), (l))
#define	bus_space_read_raw_multi_8(t, h, a, b, l) \
	(*(t)->_space_read_raw_8)((t), (h), (a), (b), (l))

#define	bus_space_write_raw_multi_2(t, h, a, b, l) \
	(*(t)->_space_write_raw_2)((t), (h), (a), (b), (l))
#define	bus_space_write_raw_multi_4(t, h, a, b, l) \
	(*(t)->_space_write_raw_4)((t), (h), (a), (b), (l))
#define	bus_space_write_raw_multi_8(t, h, a, b, l) \
	(*(t)->_space_write_raw_8)((t), (h), (a), (b), (l))

#define	bus_space_map(t, o, s, c, p) (*(t)->_space_map)((t), (o), (s), (c), (p))
#define	bus_space_unmap(t, h, s) (*(t)->_space_unmap)((t), (h), (s))
#define	bus_space_subregion(t, h, o, s, p) \
    (*(t)->_space_subregion)((t), (h), (o), (s), (p))

#define	BUS_SPACE_MAP_CACHEABLE		0x01
#define	BUS_SPACE_MAP_LINEAR		0x02
#define	BUS_SPACE_MAP_PREFETCHABLE	0x04

#define	bus_space_vaddr(t, h)	(*(t)->_space_vaddr)((t), (h))
#define	bus_space_mmap(t, a, o, p, f) \
	(*(t)->_space_mmap)((t), (a), (o), (p), (f))

/*----------------------------------------------------------------------------*/
#define bus_space_read_multi(n,m)					      \
static __inline void							      \
CAT(bus_space_read_multi_,n)(bus_space_tag_t bst, bus_space_handle_t bsh,     \
     bus_size_t o, CAT3(u_int,m,_t) *x, size_t cnt)			      \
{									      \
	while (cnt--)							      \
		*x++ = CAT(bus_space_read_,n)(bst, bsh, o);		      \
}

bus_space_read_multi(1,8)
bus_space_read_multi(2,16)
bus_space_read_multi(4,32)
bus_space_read_multi(8,64)

/*----------------------------------------------------------------------------*/
#define bus_space_read_region(n,m)					      \
static __inline void							      \
CAT(bus_space_read_region_,n)(bus_space_tag_t bst, bus_space_handle_t bsh,    \
     bus_addr_t ba, CAT3(u_int,m,_t) *x, size_t cnt)			      \
{									      \
	while (cnt--)							      \
		*x++ = CAT(bus_space_read_,n)(bst, bsh, ba++);		      \
}

bus_space_read_region(1,8)
bus_space_read_region(2,16)
bus_space_read_region(4,32)
bus_space_read_region(8,64)

/*----------------------------------------------------------------------------*/
#define bus_space_read_raw_region(n,m)					      \
static __inline void							      \
CAT(bus_space_read_raw_region_,n)(bus_space_tag_t bst,			      \
     bus_space_handle_t bsh,						      \
     bus_addr_t ba, u_int8_t *x, size_t cnt)				      \
{									      \
	cnt >>= ((n) >> 1);						      \
	while (cnt--) {							      \
		CAT(bus_space_read_raw_multi_,n)(bst, bsh, ba, x, (n));	      \
		ba += (n);						      \
		x += (n);						      \
	}								      \
}

bus_space_read_raw_region(2,16)
bus_space_read_raw_region(4,32)
bus_space_read_raw_region(8,64)

/*----------------------------------------------------------------------------*/
#define bus_space_write_multi(n,m)					      \
static __inline void							      \
CAT(bus_space_write_multi_,n)(bus_space_tag_t bst, bus_space_handle_t bsh,    \
     bus_size_t o, const CAT3(u_int,m,_t) *x, size_t cnt)		      \
{									      \
	while (cnt--) {							      \
		CAT(bus_space_write_,n)(bst, bsh, o, *x++);		      \
	}								      \
}

bus_space_write_multi(1,8)
bus_space_write_multi(2,16)
bus_space_write_multi(4,32)
bus_space_write_multi(8,64)

/*----------------------------------------------------------------------------*/
#define bus_space_write_region(n,m)					      \
static __inline void							      \
CAT(bus_space_write_region_,n)(bus_space_tag_t bst, bus_space_handle_t bsh,   \
     bus_addr_t ba, const CAT3(u_int,m,_t) *x, size_t cnt)		      \
{									      \
	while (cnt--) {							      \
		CAT(bus_space_write_,n)(bst, bsh, ba, *x++);		      \
		ba += sizeof(x);					      \
	}								      \
}

bus_space_write_region(1,8)
bus_space_write_region(2,16)
bus_space_write_region(4,32)
bus_space_write_region(8,64)

/*----------------------------------------------------------------------------*/
#define bus_space_write_raw_region(n,m)					      \
static __inline void							      \
CAT(bus_space_write_raw_region_,n)(bus_space_tag_t bst,			      \
     bus_space_handle_t bsh,						      \
     bus_addr_t ba, const u_int8_t *x, size_t cnt)		              \
{									      \
	cnt >>= ((n) >> 1);						      \
	while (cnt--) {							      \
		CAT(bus_space_write_raw_multi_,n)(bst, bsh, ba, x, (n));      \
		ba += (n);						      \
		x += (n);						      \
	}								      \
}

bus_space_write_raw_region(2,16)
bus_space_write_raw_region(4,32)
bus_space_write_raw_region(8,64)

/*----------------------------------------------------------------------------*/
#define bus_space_set_region(n,m)					      \
static __inline void							      \
CAT(bus_space_set_region_,n)(bus_space_tag_t bst, bus_space_handle_t bsh,     \
     bus_addr_t ba, CAT3(u_int,m,_t) x, size_t cnt)			      \
{									      \
	while (cnt--) {							      \
		CAT(bus_space_write_,n)(bst, bsh, ba, x);		      \
		ba += sizeof(x);					      \
	}								      \
}

bus_space_set_region(1,8)
bus_space_set_region(2,16)
bus_space_set_region(4,32)
bus_space_set_region(8,64)

/*----------------------------------------------------------------------------*/
static __inline void
bus_space_copy_1(void *v, bus_space_handle_t h1, bus_size_t o1,
	bus_space_handle_t h2, bus_size_t o2, bus_size_t c)
{
	char *s = (char *)(h1 + o1);
	char *d = (char *)(h2 + o2);

	while (c--)
		*d++ = *s++;
}

static __inline void
bus_space_copy_2(void *v, bus_space_handle_t h1, bus_size_t o1,
	bus_space_handle_t h2, bus_size_t o2, bus_size_t c)
{
	short *s = (short *)(h1 + o1);
	short *d = (short *)(h2 + o2);

	while (c--)
		*d++ = *s++;
}

static __inline void
bus_space_copy_4(void *v, bus_space_handle_t h1, bus_size_t o1,
	bus_space_handle_t h2, bus_size_t o2, bus_size_t c)
{
	int *s = (int *)(h1 + o1);
	int *d = (int *)(h2 + o2);

	while (c--)
		*d++ = *s++;
}

static __inline void
bus_space_copy_8(void *v, bus_space_handle_t h1, bus_size_t o1,
	bus_space_handle_t h2, bus_size_t o2, bus_size_t c)
{
	int64_t *s = (int64_t *)(h1 + o1);
	int64_t *d = (int64_t *)(h2 + o2);

	while (c--)
		*d++ = *s++;
}

int	generic_space_map(bus_space_tag_t, bus_addr_t, bus_size_t, int,
	    bus_space_handle_t *);
void	generic_space_unmap(bus_space_tag_t, bus_space_handle_t, bus_size_t);
int	generic_space_region(bus_space_tag_t, bus_space_handle_t, bus_size_t,
	    bus_size_t, bus_space_handle_t *);
void	*generic_space_vaddr(bus_space_tag_t, bus_space_handle_t);
uint8_t generic_space_read_1(bus_space_tag_t, bus_space_handle_t, bus_size_t);
uint16_t generic_space_read_2(bus_space_tag_t, bus_space_handle_t, bus_size_t);
uint32_t generic_space_read_4(bus_space_tag_t, bus_space_handle_t, bus_size_t);
uint64_t generic_space_read_8(bus_space_tag_t, bus_space_handle_t, bus_size_t);
void	generic_space_read_raw_2(bus_space_tag_t, bus_space_handle_t,
	    bus_addr_t, uint8_t *, bus_size_t);
void	generic_space_write_1(bus_space_tag_t, bus_space_handle_t, bus_size_t,
	    uint8_t);
void	generic_space_write_2(bus_space_tag_t, bus_space_handle_t, bus_size_t,
	    uint16_t);
void	generic_space_write_4(bus_space_tag_t, bus_space_handle_t, bus_size_t,
	    uint32_t);
void	generic_space_write_8(bus_space_tag_t, bus_space_handle_t, bus_size_t,
	    uint64_t);
void	generic_space_write_raw_2(bus_space_tag_t, bus_space_handle_t,
	    bus_addr_t, const uint8_t *, bus_size_t);
void	generic_space_read_raw_4(bus_space_tag_t, bus_space_handle_t,
	    bus_addr_t, uint8_t *, bus_size_t);
void	generic_space_write_raw_4(bus_space_tag_t, bus_space_handle_t,
	    bus_addr_t, const uint8_t *, bus_size_t);
void	generic_space_read_raw_8(bus_space_tag_t, bus_space_handle_t,
	    bus_addr_t, uint8_t *, bus_size_t);
void	generic_space_write_raw_8(bus_space_tag_t, bus_space_handle_t,
	    bus_addr_t, const uint8_t *, bus_size_t);
paddr_t	generic_space_mmap(bus_space_tag_t, bus_addr_t, off_t, int, int);

/*----------------------------------------------------------------------------*/
/*
 * Bus read/write barrier methods.
 *
 *	void bus_space_barrier(bus_space_tag_t tag,
 *	    bus_space_handle_t bsh, bus_size_t offset,
 *	    bus_size_t len, int flags);
 *
 */
static inline void
bus_space_barrier(bus_space_tag_t t, bus_space_handle_t h, bus_size_t offset,
    bus_size_t length, int flags)
{
	__asm__ volatile ("sync" ::: "memory");
}
#define BUS_SPACE_BARRIER_READ  0x01		/* force read barrier */
#define BUS_SPACE_BARRIER_WRITE 0x02		/* force write barrier */

#define	BUS_DMA_WAITOK		0x0000
#define	BUS_DMA_NOWAIT		0x0001
#define	BUS_DMA_ALLOCNOW	0x0002
#define	BUS_DMA_COHERENT	0x0008
#define	BUS_DMA_BUS1		0x0010	/* placeholders for bus functions... */
#define	BUS_DMA_BUS2		0x0020
#define	BUS_DMA_BUS3		0x0040
#define	BUS_DMA_BUS4		0x0080
#define	BUS_DMA_READ		0x0100	/* mapping is device -> memory only */
#define	BUS_DMA_WRITE		0x0200	/* mapping is memory -> device only */
#define	BUS_DMA_STREAMING	0x0400	/* hint: sequential, unidirectional */
#define	BUS_DMA_ZERO		0x0800	/* zero memory in dmamem_alloc */
#define	BUS_DMA_NOCACHE		0x1000

/* Forwards needed by prototypes below. */
struct mbuf;
struct proc;
struct uio;

#define	BUS_DMASYNC_POSTREAD	0x0001
#define BUS_DMASYNC_POSTWRITE	0x0002
#define BUS_DMASYNC_PREREAD	0x0004
#define BUS_DMASYNC_PREWRITE	0x0008

typedef struct machine_bus_dma_tag	*bus_dma_tag_t;
typedef struct machine_bus_dmamap	*bus_dmamap_t;

/*
 *	bus_dma_segment_t
 *
 *	Describes a single contiguous DMA transaction.  Values
 *	are suitable for programming into DMA registers.
 */
struct machine_bus_dma_segment {
	bus_addr_t	ds_addr;	/* DMA address */
	bus_size_t	ds_len;		/* length of transfer */

	paddr_t		_ds_paddr;	/* CPU address */
	vaddr_t		_ds_vaddr;	/* CPU address */
};
typedef struct machine_bus_dma_segment	bus_dma_segment_t;

/*
 *	bus_dma_tag_t
 *
 *	A machine-dependent opaque type describing the implementation of
 *	DMA for a given bus.
 */

struct machine_bus_dma_tag {
	void	*_cookie;		/* cookie used in the guts */

	/*
	 * DMA mapping methods.
	 */
	int	(*_dmamap_create)(bus_dma_tag_t , bus_size_t, int,
		    bus_size_t, bus_size_t, int, bus_dmamap_t *);
	void	(*_dmamap_destroy)(bus_dma_tag_t , bus_dmamap_t);
	int	(*_dmamap_load)(bus_dma_tag_t , bus_dmamap_t, void *,
		    bus_size_t, struct proc *, int);
	int	(*_dmamap_load_mbuf)(bus_dma_tag_t , bus_dmamap_t,
		    struct mbuf *, int);
	int	(*_dmamap_load_uio)(bus_dma_tag_t , bus_dmamap_t,
		    struct uio *, int);
	int	(*_dmamap_load_raw)(bus_dma_tag_t , bus_dmamap_t,
		    bus_dma_segment_t *, int, bus_size_t, int);
	int	(*_dmamap_load_buffer)(bus_dma_tag_t, bus_dmamap_t, void *,
		    bus_size_t, struct proc *, int, paddr_t *, int *, int);
	void	(*_dmamap_unload)(bus_dma_tag_t , bus_dmamap_t);
	void	(*_dmamap_sync)(bus_dma_tag_t , bus_dmamap_t,
		    bus_addr_t, bus_size_t, int);

	/*
	 * DMA memory utility functions.
	 */
	int	(*_dmamem_alloc)(bus_dma_tag_t, bus_size_t, bus_size_t,
		    bus_size_t, bus_dma_segment_t *, int, int *, int);
	void	(*_dmamem_free)(bus_dma_tag_t, bus_dma_segment_t *, int);
	int	(*_dmamem_map)(bus_dma_tag_t, bus_dma_segment_t *,
		    int, size_t, caddr_t *, int);
	void	(*_dmamem_unmap)(bus_dma_tag_t, caddr_t, size_t);
	paddr_t	(*_dmamem_mmap)(bus_dma_tag_t, bus_dma_segment_t *,
		    int, off_t, int, int);

	/*
	 * internal memory address translation information.
	 */
	bus_addr_t (*_pa_to_device)(paddr_t);
	paddr_t	(*_device_to_pa)(bus_addr_t);
	bus_addr_t _dma_mask;
};

#define	bus_dmamap_create(t, s, n, m, b, f, p)			\
	(*(t)->_dmamap_create)((t), (s), (n), (m), (b), (f), (p))
#define	bus_dmamap_destroy(t, p)				\
	(*(t)->_dmamap_destroy)((t), (p))
#define	bus_dmamap_load(t, m, b, s, p, f)			\
	(*(t)->_dmamap_load)((t), (m), (b), (s), (p), (f))
#define	bus_dmamap_load_mbuf(t, m, b, f)			\
	(*(t)->_dmamap_load_mbuf)((t), (m), (b), (f))
#define	bus_dmamap_load_uio(t, m, u, f)				\
	(*(t)->_dmamap_load_uio)((t), (m), (u), (f))
#define	bus_dmamap_load_raw(t, m, sg, n, s, f)			\
	(*(t)->_dmamap_load_raw)((t), (m), (sg), (n), (s), (f))
#define	bus_dmamap_unload(t, p)					\
	(*(t)->_dmamap_unload)((t), (p))
#define	bus_dmamap_sync(t, p, a, l, o)				\
	(void)((t)->_dmamap_sync ?				\
	    (*(t)->_dmamap_sync)((t), (p), (a), (l), (o)) : (void)0)

#define	bus_dmamem_alloc(t, s, a, b, sg, n, r, f)		\
	(*(t)->_dmamem_alloc)((t), (s), (a), (b), (sg), (n), (r), (f))
#define	bus_dmamem_free(t, sg, n)				\
	(*(t)->_dmamem_free)((t), (sg), (n))
#define	bus_dmamem_map(t, sg, n, s, k, f)			\
	(*(t)->_dmamem_map)((t), (sg), (n), (s), (k), (f))
#define	bus_dmamem_unmap(t, k, s)				\
	(*(t)->_dmamem_unmap)((t), (k), (s))
#define	bus_dmamem_mmap(t, sg, n, o, p, f)			\
	(*(t)->_dmamem_mmap)((t), (sg), (n), (o), (p), (f))

int	_dmamap_create(bus_dma_tag_t, bus_size_t, int,
	    bus_size_t, bus_size_t, int, bus_dmamap_t *);
void	_dmamap_destroy(bus_dma_tag_t, bus_dmamap_t);
int	_dmamap_load(bus_dma_tag_t, bus_dmamap_t, void *,
	    bus_size_t, struct proc *, int);
int	_dmamap_load_mbuf(bus_dma_tag_t, bus_dmamap_t, struct mbuf *, int);
int	_dmamap_load_uio(bus_dma_tag_t, bus_dmamap_t, struct uio *, int);
int	_dmamap_load_raw(bus_dma_tag_t, bus_dmamap_t,
	    bus_dma_segment_t *, int, bus_size_t, int);
int	_dmamap_load_buffer(bus_dma_tag_t, bus_dmamap_t, void *,
	    bus_size_t, struct proc *, int, paddr_t *, int *, int);
void	_dmamap_unload(bus_dma_tag_t, bus_dmamap_t);
void	_dmamap_sync(bus_dma_tag_t, bus_dmamap_t, bus_addr_t,
	    bus_size_t, int);

int	_dmamem_alloc(bus_dma_tag_t, bus_size_t, bus_size_t,
	    bus_size_t, bus_dma_segment_t *, int, int *, int);
void	_dmamem_free(bus_dma_tag_t, bus_dma_segment_t *, int);
int	_dmamem_map(bus_dma_tag_t, bus_dma_segment_t *,
	    int, size_t, caddr_t *, int);
void	_dmamem_unmap(bus_dma_tag_t, caddr_t, size_t);
paddr_t	_dmamem_mmap(bus_dma_tag_t, bus_dma_segment_t *, int, off_t, int, int);
int	_dmamem_alloc_range(bus_dma_tag_t, bus_size_t, bus_size_t, bus_size_t,
	    bus_dma_segment_t *, int, int *, int, paddr_t, paddr_t);

/*
 *	bus_dmamap_t
 *
 *	Describes a DMA mapping.
 */
struct machine_bus_dmamap {
	/*
	 * PRIVATE MEMBERS: not for use by machine-independent code.
	 */
	bus_size_t	_dm_size;	/* largest DMA transfer mappable */
	int		_dm_segcnt;	/* number of segs this map can map */
	bus_size_t	_dm_maxsegsz;	/* largest possible segment */
	bus_size_t	_dm_boundary;	/* don't cross this */
	int		_dm_flags;	/* misc. flags */

	void		*_dm_cookie;	/* cookie for bus-specific functions */

	/*
	 * PUBLIC MEMBERS: these are used by machine-independent code.
	 */
	bus_size_t	dm_mapsize;	/* size of the mapping */
	int		dm_nsegs;	/* # valid segments in mapping */
	bus_dma_segment_t dm_segs[1];	/* segments; variable length */
};

#endif /* _MACHINE_BUS_H_ */


code:
/* $OpenBSD: cdefs.h,v 1.2 2013/03/28 17:30:45 martynas Exp $ */
/* public domain */
#include <mips64/cdefs.h>


code:
/*	$OpenBSD: conf.h,v 1.3 2011/07/04 16:52:41 nicm Exp $	*/
/*	$NetBSD: conf.h,v 1.2 1996/05/05 19:28:34 christos Exp $	*/

/*
 * Copyright (c) 1996 Christos Zoulas.  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. All advertising materials mentioning features or use of this software
 *    must display the following acknowledgement:
 *	This product includes software developed by Christos Zoulas.
 * 4. 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 <sys/conf.h>

/* open, close, write, ioctl, kqueue */
#define cdev_apm_init(c,n) { \
        dev_init(c,n,open), dev_init(c,n,close), (dev_type_read((*))) enodev, \
        (dev_type_write((*))) enodev, dev_init(c,n,ioctl), \
	(dev_type_stop((*))) enodev, 0, selfalse, \
	(dev_type_mmap((*))) enodev, 0, 0, dev_init(c,n,kqfilter) }

cdev_decl(apm);


code:
/* $OpenBSD: cpu.h,v 1.4 2014/03/31 20:21:18 miod Exp $ */
/*-
 * Copyright (c) 1992, 1993
 *	The Regents of the University of California.  All rights reserved.
 *
 * This code is derived from software contributed to Berkeley by
 * Ralph Campbell and Rick Macklem.
 *
 * 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. Neither the name of the University nor the names of its contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
 *
 *	Copyright (C) 1989 Digital Equipment Corporation.
 *	Permission to use, copy, modify, and distribute this software and
 *	its documentation for any purpose and without fee is hereby granted,
 *	provided that the above copyright notice appears in all copies.
 *	Digital Equipment Corporation makes no representations about the
 *	suitability of this software for any purpose.  It is provided "as is"
 *	without express or implied warranty.
 *
 *	from: @(#)cpu.h	8.4 (Berkeley) 1/4/94
 */

#ifdef	_KERNEL

#define	Mips_SyncCache(ci)			\
	Loongson2_SyncCache((ci))
#define	Mips_InvalidateICache(ci, va, l)	\
	Loongson2_InvalidateICache((ci), (va), (l))
#define	Mips_InvalidateICachePage(ci, va)	\
	Loongson2_InvalidateICachePage((ci), (va))
#define	Mips_SyncICache(ci)			\
	Loongson2_SyncICache((ci))
#define	Mips_SyncDCachePage(ci, va, pa)		\
	Loongson2_SyncDCachePage((ci), (va), (pa))
#define	Mips_HitSyncDCache(ci, va, l)	\
	Loongson2_HitSyncDCache((ci), (va), (l))
#define	Mips_IOSyncDCache(ci, va, l, h)	\
	Loongson2_IOSyncDCache((ci), (va), (l), (h))
#define	Mips_HitInvalidateDCache(ci, va, l)	\
	Loongson2_HitInvalidateDCache((ci), (va), (l))

#endif	/* _KERNEL */

#include <mips64/cpu.h>


code:
/* $OpenBSD: cpustate.h,v 1.1.1.1 2009/07/31 09:26:25 miod Exp $ */
/* public domain */
#include <mips64/cpustate.h>


code:
/* $OpenBSD: db_machdep.h,v 1.1.1.1 2009/07/31 09:26:25 miod Exp $ */
/* public domain */
#include <mips64/db_machdep.h>


code:
/* $OpenBSD: disklabel.h,v 1.1.1.1 2009/08/04 20:26:39 miod Exp $ */
/* public domain */

/*
 * Standard MBR partition scheme, with the label in the second sector
 * of the OpenBSD partition.
 */

#define	LABELSECTOR	1
#define	LABELOFFSET	0
#define	MAXPARTITIONS	16


code:
/* $OpenBSD: endian.h,v 1.1.1.1 2009/07/31 09:26:25 miod Exp $ */
/* public domain */
#include <mips64/endian.h>


code:
/* $OpenBSD: exec.h,v 1.1.1.1 2009/07/31 09:26:25 miod Exp $ */
/* public domain */
#include <mips64/exec.h>


code:
/*	$OpenBSD: fenv.h,v 1.2 2013/06/01 21:20:54 jasper Exp $	*/
/* public domain */
#include <mips64/fenv.h>


code:
/* $OpenBSD: fpu.h,v 1.1 2010/09/17 00:34:04 miod Exp $ */
/* public domain */
#include <mips64/fpu.h>


code:
/* $OpenBSD: frame.h,v 1.1.1.1 2009/07/31 09:26:25 miod Exp $ */
/* public domain */
#include <mips64/frame.h>


code:
/*	$OpenBSD: hibernate.h,v 1.2 2014/05/31 06:30:16 mlarkin Exp $	*/

/*
 * Copyright (c) 2013 Paul Irofti.
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

#include <machine/hibernate_var.h>

/* Loongson hibernate support structures and functions */

int	get_hibernate_info_md(union hibernate_info *);
void	hibernate_flush(void);
void	hibernate_enter_resume_mapping(vaddr_t, paddr_t, int);
int	hibernate_inflate_skip(union hibernate_info *, paddr_t);
int	hibernate_suspend(void);
void	hibernate_switch_stack_machdep(void);
void	hibernate_resume_machdep(void);
void	hibernate_activate_resume_pt_machdep(void);
void	hibernate_enable_intr_machdep(void);
void	hibernate_disable_intr_machdep(void);


code:
/*	$OpenBSD: hibernate_var.h,v 1.1 2013/06/02 21:46:04 pirofti Exp $	*/

/*
 * Copyright (c) 2013 Paul Irofti.
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

/* Loongson hibernate support definitions */

#define PAGE_MASK_4M ((256 * PAGE_SIZE) - 1)

#define PIGLET_PAGE_MASK ~((paddr_t)PAGE_MASK_4M)

/*
 * Steal hibernate pages right after the first page which is reserved
 * for the exception area.
 * */
#define HIBERNATE_STACK_PAGE	(PAGE_SIZE * 1)
#define HIBERNATE_INFLATE_PAGE	(PAGE_SIZE * 2)
#define HIBERNATE_COPY_PAGE	(PAGE_SIZE * 3)
#define HIBERNATE_HIBALLOC_PAGE	(PAGE_SIZE * 4)

#define HIBERNATE_RESERVED_PAGES	4

/* Use 4MB hibernation chunks */
#define HIBERNATE_CHUNK_SIZE		0x400000

#define HIBERNATE_CHUNK_TABLE_SIZE	0x100000


code:
/* $OpenBSD: ieee.h,v 1.1.1.1 2009/07/31 09:26:25 miod Exp $ */
/* public domain */
#include <mips64/ieee.h>


code:
/* $OpenBSD: ieeefp.h,v 1.1.1.1 2009/07/31 09:26:25 miod Exp $ */
/* public domain */
#include <mips64/ieeefp.h>