code:
/*	$OpenBSD: qecreg.h,v 1.4 2003/06/02 15:54:22 deraadt Exp $	*/

/*
 * Copyright (c) 1998 Theo de Raadt and Jason L. Wright.
 * 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 AUTHORS ``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 AUTHORS 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.
 */

/* QEC registers */
struct qecregs {
	volatile u_int32_t ctrl;		/* control */
	volatile u_int32_t stat;		/* status */
	volatile u_int32_t psize;		/* packet size */
	volatile u_int32_t msize;		/* local-mem size (64K) */
	volatile u_int32_t rsize;		/* receive partition size */
	volatile u_int32_t tsize;		/* transmit partition size */
};

/* qecregs.ctrl: control. */
#define QEC_CTRL_MODEMASK	0xf0000000	/* QEC mode: qe or be */
#define QEC_CTRL_MMODE		0x40000000		/* MACE qec mode */
#define QEC_CTRL_BMODE		0x10000000		/* BE qec mode */
#define QEC_CTRL_EPAR		0x00000020	/* enable parity */
#define QEC_CTRL_ACNTRL		0x00000018	/* sbus arbitration control */
#define QEC_CTRL_B64		0x00000004	/* 64 byte dvma bursts */
#define QEC_CTRL_B32		0x00000002	/* 32 byte dvma bursts */
#define QEC_CTRL_B16		0x00000000	/* 16 byte dvma bursts */
#define QEC_CTRL_RESET		0x00000001	/* reset the qec */

/* qecregs.stat: status. */
#define QEC_STAT_TX		0x00000008	/* bigmac transmit irq */
#define QEC_STAT_RX		0x00000004	/* bigmac receive irq */
#define QEC_STAT_BM		0x00000002	/* bigmac qec irq */
#define QEC_STAT_ER		0x00000001	/* bigmac error irq */

/* qecregs.stat: packet size. */
#define QEC_PSIZE_2048		0x00		/* 2k packet size */
#define QEC_PSIZE_4096		0x01		/* 4k packet size */
#define QEC_PSIZE_6144		0x10		/* 6k packet size */
#define QEC_PSIZE_8192		0x11		/* 8k packet size */


code:
/*	$OpenBSD: qecvar.h,v 1.12 2015/03/29 10:59:47 mpi Exp $	*/

/*
 * Copyright (c) 1998 Theo de Raadt and Jason L. Wright.
 * 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 AUTHORS ``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 AUTHORS 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.
 */

struct qec_softc {
	struct	device	sc_dev;		/* us as a device */
	struct	qecregs	*sc_regs;	/* QEC registers */
	int		sc_node;	/* PROM node ID */
	int		sc_burst;	/* DVMA burst size in effect */
	int		sc_bufsiz;	/* Size of buffer */
	int		sc_pri;		/* interrupt priority */
	int		sc_nchannels;	/* number of channels on board */
	int		sc_nrange;	/* number of ranges */
	struct	rom_range *sc_range;	/* array of ranges */
	void		*sc_paddr;

	/*
	 * For use by children:
	 */
	u_int32_t	sc_msize;	/* qec buffer offset per channel */
	u_int32_t	sc_rsize;	/* qec buffer size for receive */
};

void	qec_reset(struct qec_softc *);
int	qec_put(u_int8_t *, struct mbuf *);
struct mbuf *qec_get(u_int8_t *, int);

license: unknown


code:
/*	$OpenBSD: qereg.h,v 1.7 2003/06/02 18:40:59 jason Exp $	*/

/*
 * Copyright (c) 1998, 2000 Jason L. Wright.
 * 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 AUTHORS ``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 AUTHORS 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.
 */

/*
 * Documentation for MACE chip can be found on AMD's website:
 *      http://www.amd.com/products/npd/techdocs/techdocs.html
 */

/*
 * QE Channel registers
 */
struct qe_cregs {
	volatile u_int32_t ctrl;		/* control */
	volatile u_int32_t stat;		/* status */
	volatile u_int32_t rxds;		/* rx descriptor ring ptr */
	volatile u_int32_t txds;		/* tx descriptor ring ptr */
	volatile u_int32_t rimask;		/* rx interrupt mask */
	volatile u_int32_t timask;		/* tx interrupt mask */
	volatile u_int32_t qmask;		/* qec error interrupt mask */
	volatile u_int32_t mmask;		/* mace error interrupt mask */
	volatile u_int32_t rxwbufptr;		/* local memory rx write ptr */
	volatile u_int32_t rxrbufptr;		/* local memory rx read ptr */
	volatile u_int32_t txwbufptr;		/* local memory tx write ptr */
	volatile u_int32_t txrbufptr;		/* local memory tx read ptr */
	volatile u_int32_t ccnt;		/* collision counter */
	volatile u_int32_t pipg;		/* inter-frame gap */
};

/* qe_cregs.ctrl: control. */
#define	QE_CR_CTRL_RXOFF	0x00000004	/* disable receiver */
#define	QE_CR_CTRL_RESET	0x00000002	/* reset this channel */
#define	QE_CR_CTRL_TWAKEUP	0x00000001	/* tx dma wakeup */

/* qe_cregs.stat: status. */
#define	QE_CR_STAT_EDEFER	0x10000000	/* excessive defers */
#define	QE_CR_STAT_CLOSS	0x08000000	/* loss of carrier */
#define	QE_CR_STAT_ERETRIES	0x04000000	/* >16 retries */
#define	QE_CR_STAT_LCOLL	0x02000000	/* late tx collision */
#define	QE_CR_STAT_FUFLOW	0x01000000	/* fifo underflow */
#define	QE_CR_STAT_JERROR	0x00800000	/* jabber error */
#define	QE_CR_STAT_BERROR	0x00400000	/* babble error */
#define	QE_CR_STAT_TXIRQ	0x00200000	/* tx interrupt */
#define	QE_CR_STAT_TCCOFLOW	0x00100000	/* tx collision cntr expired */
#define	QE_CR_STAT_TXDERROR	0x00080000	/* tx descriptor is bad */
#define	QE_CR_STAT_TXLERR	0x00040000	/* tx late error */
#define	QE_CR_STAT_TXPERR	0x00020000	/* tx parity error */
#define	QE_CR_STAT_TXSERR	0x00010000	/* tx sbus error ack */
#define	QE_CR_STAT_RCCOFLOW	0x00001000	/* rx collision cntr expired */
#define	QE_CR_STAT_RUOFLOW	0x00000800	/* rx runt counter expired */
#define	QE_CR_STAT_MCOFLOW	0x00000400	/* rx missed counter expired */
#define	QE_CR_STAT_RXFOFLOW	0x00000200	/* rx fifo over flow */
#define	QE_CR_STAT_RLCOLL	0x00000100	/* rx late collision */
#define	QE_CR_STAT_FCOFLOW	0x00000080	/* rx frame counter expired */
#define	QE_CR_STAT_CECOFLOW	0x00000040	/* rx crc error cntr expired */
#define	QE_CR_STAT_RXIRQ	0x00000020	/* rx interrupt */
#define	QE_CR_STAT_RXDROP	0x00000010	/* rx dropped packet */
#define	QE_CR_STAT_RXSMALL	0x00000008	/* rx buffer too small */
#define	QE_CR_STAT_RXLERR	0x00000004	/* rx late error */
#define	QE_CR_STAT_RXPERR	0x00000002	/* rx parity error */
#define	QE_CR_STAT_RXSERR	0x00000001	/* rx sbus error ack */

/*
 * Errors: all status bits except for TX/RX IRQ
 */
#define	QE_CR_STAT_ALLERRORS	\
	( QE_CR_STAT_EDEFER   | QE_CR_STAT_CLOSS    | QE_CR_STAT_ERETRIES \
	| QE_CR_STAT_LCOLL    | QE_CR_STAT_FUFLOW   | QE_CR_STAT_JERROR \
	| QE_CR_STAT_BERROR   | QE_CR_STAT_TCCOFLOW | QE_CR_STAT_TXDERROR \
	| QE_CR_STAT_TXLERR   | QE_CR_STAT_TXPERR   | QE_CR_STAT_TXSERR \
	| QE_CR_STAT_RCCOFLOW | QE_CR_STAT_RUOFLOW  | QE_CR_STAT_MCOFLOW \
	| QE_CR_STAT_RXFOFLOW | QE_CR_STAT_RLCOLL   | QE_CR_STAT_FCOFLOW \
	| QE_CR_STAT_CECOFLOW | QE_CR_STAT_RXDROP   | QE_CR_STAT_RXSMALL \
	| QE_CR_STAT_RXLERR   | QE_CR_STAT_RXPERR   | QE_CR_STAT_RXSERR)

/* qe_cregs.qmask: qec error interrupt mask. */
#define	QE_CR_QMASK_COFLOW	0x00100000	/* collision cntr overflow */
#define	QE_CR_QMASK_TXDERROR	0x00080000	/* tx descriptor error */
#define	QE_CR_QMASK_TXLERR	0x00040000	/* tx late error */
#define	QE_CR_QMASK_TXPERR	0x00020000	/* tx parity error */
#define	QE_CR_QMASK_TXSERR	0x00010000	/* tx sbus error ack */
#define	QE_CR_QMASK_RXDROP	0x00000010	/* rx packet dropped */
#define	QE_CR_QMASK_RXSMALL	0x00000008	/* rx buffer too small */
#define	QE_CR_QMASK_RXLERR	0x00000004	/* rx late error */
#define	QE_CR_QMASK_RXPERR	0x00000002	/* rx parity error */
#define	QE_CR_QMASK_RXSERR	0x00000001	/* rx sbus error ack */

/* qe_cregs.mmask: MACE error interrupt mask. */
#define	QE_CR_MMASK_EDEFER	0x10000000	/* excess defer */
#define	QE_CR_MMASK_CLOSS	0x08000000	/* carrier loss */
#define	QE_CR_MMASK_ERETRY	0x04000000	/* excess retry */
#define	QE_CR_MMASK_LCOLL	0x02000000	/* late collision error */
#define	QE_CR_MMASK_UFLOW	0x01000000	/* underflow */
#define	QE_CR_MMASK_JABBER	0x00800000	/* jabber error */
#define	QE_CR_MMASK_BABBLE	0x00400000	/* babble error */
#define	QE_CR_MMASK_OFLOW	0x00000800	/* overflow */
#define	QE_CR_MMASK_RXCOLL	0x00000400	/* rx coll-cntr overflow */
#define	QE_CR_MMASK_RPKT	0x00000200	/* runt pkt overflow */
#define	QE_CR_MMASK_MPKT	0x00000100	/* missed pkt overflow */

/* qe_cregs.pipg: inter-frame gap. */
#define	QE_CR_PIPG_TENAB	0x00000020	/* enable throttle */
#define	QE_CR_PIPG_MMODE	0x00000010	/* manual mode */
#define	QE_CR_PIPG_WMASK	0x0000000f	/* sbus wait mask */

/* MACE registers */
struct qe_mregs {
	volatile u_int8_t rcvfifo;	/*0*/	/* receive fifo */
	volatile u_int8_t xmtfifo;	/*1*/	/* transmit fifo */
	volatile u_int8_t xmtfc;	/*2*/	/* transmit frame control */
	volatile u_int8_t xmtfs;	/*3*/	/* transmit frame status */
	volatile u_int8_t xmtrc;	/*4*/	/* tx retry count */
	volatile u_int8_t rcvfc;	/*5*/	/* receive frame control */
	volatile u_int8_t rcvfs;	/*6*/	/* receive frame status */
	volatile u_int8_t fifofc;	/*7*/	/* fifo frame count */
	volatile u_int8_t ir;		/*8*/	/* interrupt register */
	volatile u_int8_t imr;		/*9*/	/* interrupt mask register */
	volatile u_int8_t pr;		/*10*/	/* poll register */
	volatile u_int8_t biucc;	/*11*/	/* biu config control */
	volatile u_int8_t fifocc;	/*12*/	/* fifo config control */
	volatile u_int8_t maccc;	/*13*/	/* mac config control */
	volatile u_int8_t plscc;	/*14*/	/* pls config control */
	volatile u_int8_t phycc;	/*15*/	/* phy config control */
	volatile u_int8_t chipid1;	/*16*/	/* chipid, low byte */
	volatile u_int8_t chipid2;	/*17*/	/* chipid, high byte */
	volatile u_int8_t iac;		/*18*/	/* internal address config */
	volatile u_int8_t _reserved0;	/*19*/	/* reserved */
	volatile u_int8_t ladrf;	/*20*/	/* logical address filter */
	volatile u_int8_t padr;		/*21*/	/* physical address */
	volatile u_int8_t _reserved1;	/*22*/	/* reserved */
	volatile u_int8_t _reserved2;	/*23*/	/* reserved */
	volatile u_int8_t mpc;		/*24*/	/* missed packet count */
	volatile u_int8_t _reserved3;	/*25*/	/* reserved */
	volatile u_int8_t rntpc;	/*26*/	/* runt packet count */
	volatile u_int8_t rcvcc;	/*27*/	/* receive collision count */
	volatile u_int8_t _reserved4;	/*28*/	/* reserved */
	volatile u_int8_t utr;		/*29*/	/* user test register */
	volatile u_int8_t rtr1;		/*30*/	/* reserved test register 1 */
	volatile u_int8_t rtr2;		/*31*/	/* reserved test register 2 */
};

/* qe_mregs.xmtfc: transmit frame control. */
#define	QE_MR_XMTFC_DRETRY	0x80		/* disable retries */
#define	QE_MR_XMTFC_DXMTFCS	0x08		/* disable tx fcs */
#define	QE_MR_XMTFC_APADXMT	0x01		/* enable auto padding */

/* qe_mregs.xmtfs: transmit frame status. */
#define	QE_MR_XMTFS_XMTSV	0x80		/* tx valid */
#define	QE_MR_XMTFS_UFLO	0x40		/* tx underflow */
#define	QE_MR_XMTFS_LCOL	0x20		/* tx late collision */
#define	QE_MR_XMTFS_MORE	0x10		/* tx > 1 retries */
#define	QE_MR_XMTFS_ONE		0x08		/* tx 1 retry */
#define	QE_MR_XMTFS_DEFER	0x04		/* tx pkt deferred */
#define	QE_MR_XMTFS_LCAR	0x02		/* tx carrier lost */
#define	QE_MR_XMTFS_RTRY	0x01		/* tx retry error */

/* qe_mregs.xmtrc: transmit retry count. */
#define	QE_MR_XMTRC_EXDEF	0x80		/* tx excess defers */
#define	QE_MR_XMTRC_XMTRC	0x0f		/* tx retry count mask */

/* qe_mregs.rcvfc: receive frame control. */
#define	QE_MR_RCVFC_LLRCV	0x08		/* rx low latency */
#define	QE_MR_RCVFC_MR		0x04		/* rx addr match/reject */
#define	QE_MR_RCVFC_ASTRPRCV	0x01		/* rx auto strip */

/* qe_mregs.rcvfs: receive frame status. */
#define	QE_MR_RCVFS_OFLO	0x80		/* rx overflow */
#define	QE_MR_RCVFS_CLSN	0x40		/* rx late collision */
#define	QE_MR_RCVFS_FRAM	0x20		/* rx framing error */
#define	QE_MR_RCVFS_FCS		0x10		/* rx fcs error */
#define	QE_MR_RCVFS_RCVCNT	0x0f		/* rx msg byte count mask */

/* qe_mregs.fifofc: fifo frame count. */
#define	QE_MR_FIFOFC_RCVFC	0xf0		/* rx fifo frame count */
#define	QE_MR_FIFOFC_XMTFC	0x0f		/* tx fifo frame count */

/* qe_mregs.ir: interrupt register. */
#define	QE_MR_IR_JAB		0x80		/* jabber error */
#define	QE_MR_IR_BABL		0x40		/* babble error */
#define	QE_MR_IR_CERR		0x20		/* collision error */
#define	QE_MR_IR_RCVCCO		0x10		/* collision cnt overflow */
#define	QE_MR_IR_RNTPCO		0x08		/* runt pkt cnt overflow */
#define	QE_MR_IR_MPCO		0x04		/* miss pkt cnt overflow */
#define	QE_MR_IR_RCVINT		0x02		/* packet received */
#define	QE_MR_IR_XMTINT		0x01		/* packet transmitted */

/* qe_mregs.imr: interrupt mask register. */
#define	QE_MR_IMR_JABM		0x80		/* jabber errors */
#define	QE_MR_IMR_BABLM		0x40		/* babble errors */
#define	QE_MR_IMR_CERRM		0x20		/* collision errors */
#define	QE_MR_IMR_RCVCCOM	0x10		/* rx collision count oflow */
#define	QE_MR_IMR_RNTPCOM	0x08		/* runt pkt cnt ovrflw */
#define	QE_MR_IMR_MPCOM		0x04		/* miss pkt cnt ovrflw */
#define	QE_MR_IMR_RCVINTM	0x02		/* rx interrupts */
#define	QE_MR_IMR_XMTINTM	0x01		/* tx interrupts */

/* qe_mregs.pr: poll register. */
#define	QE_MR_PR_XMTSV		0x80		/* tx status is valid */
#define	QE_MR_PR_TDTREQ		0x40		/* tx data xfer request */
#define	QE_MR_PR_RDTREQ		0x20		/* rx data xfer request */

/* qe_mregs.biucc: biu config control. */
#define	QE_MR_BIUCC_BSWAP	0x40		/* byte swap */
#define	QE_MR_BIUCC_4TS		0x00		/* 4byte xmit start point */
#define	QE_MR_BIUCC_16TS	0x10		/* 16byte xmit start point */
#define	QE_MR_BIUCC_64TS	0x20		/* 64byte xmit start point */
#define	QE_MR_BIUCC_112TS	0x30		/* 112byte xmit start point */
#define	QE_MR_BIUCC_SWRST	0x01		/* sw-reset mace */

/* qe_mregs.fifocc: fifo config control. */
#define	QE_MR_FIFOCC_TXF8	0x00		/* tx fifo 8 write cycles */
#define	QE_MR_FIFOCC_TXF32	0x80		/* tx fifo 32 write cycles */
#define	QE_MR_FIFOCC_TXF16	0x40		/* tx fifo 16 write cycles */
#define	QE_MR_FIFOCC_RXF64	0x20		/* rx fifo 64 write cycles */
#define	QE_MR_FIFOCC_RXF32	0x10		/* rx fifo 32 write cycles */
#define	QE_MR_FIFOCC_RXF16	0x00		/* rx fifo 16 write cycles */
#define	QE_MR_FIFOCC_TFWU	0x08		/* tx fifo watermark update */
#define	QE_MR_FIFOCC_RFWU	0x04		/* rx fifo watermark update */
#define	QE_MR_FIFOCC_XMTBRST	0x02		/* tx burst enable */
#define	QE_MR_FIFOCC_RCVBRST	0x01		/* rx burst enable */

/* qe_mregs.maccc: mac config control. */
#define	QE_MR_MACCC_PROM	0x80		/* promiscuous mode enable */
#define	QE_MR_MACCC_DXMT2PD	0x40		/* tx 2part deferral enable */
#define	QE_MR_MACCC_EMBA	0x20		/* modified backoff enable */
#define	QE_MR_MACCC_DRCVPA	0x08		/* rx physical addr disable */
#define	QE_MR_MACCC_DRCVBC	0x04		/* rx broadcast disable */
#define	QE_MR_MACCC_ENXMT	0x02		/* enable transmitter */
#define	QE_MR_MACCC_ENRCV	0x01		/* enable receiver */

/* qe_mregs.plscc: pls config control. */
#define	QE_MR_PLSCC_XMTSEL	0x08		/* tx mode select */
#define	QE_MR_PLSCC_PORTMASK	0x06		/* media mask */
#define	QE_MR_PLSCC_GPSI	0x06		/* use gpsi connector */
#define	QE_MR_PLSCC_DAI		0x04		/* use dai connector */
#define	QE_MR_PLSCC_TP		0x02		/* use twistedpair connector */
#define	QE_MR_PLSCC_AUI		0x00		/* use aui connector */
#define	QE_MR_PLSCC_ENPLSIO	0x01		/* pls i/o enable */

/* qe_mregs.phycc: phy config control. */
#define	QE_MR_PHYCC_LNKFL	0x80		/* link fail */
#define	QE_MR_PHYCC_DLNKTST	0x40		/* disable link test logic */
#define	QE_MR_PHYCC_REVPOL	0x20		/* rx polarity */
#define	QE_MR_PHYCC_DAPC	0x10		/* autopolaritycorrect disab */
#define	QE_MR_PHYCC_LRT		0x08		/* select low threshold */
#define	QE_MR_PHYCC_ASEL	0x04		/* connector port auto-sel */
#define	QE_MR_PHYCC_RWAKE	0x02		/* remote wakeup */
#define	QE_MR_PHYCC_AWAKE	0x01		/* auto wakeup */

/* qe_mregs.iac: internal address config. */
#define	QE_MR_IAC_ADDRCHG	0x80		/* start address change */
#define	QE_MR_IAC_PHYADDR	0x04		/* physical address reset */
#define	QE_MR_IAC_LOGADDR	0x02		/* logical address reset */

/* qe_mregs.utr: user test register. */
#define	QE_MR_UTR_RTRE		0x80		/* enable resv test register */
#define	QE_MR_UTR_RTRD		0x40		/* disab resv test register */
#define	QE_MR_UTR_RPA		0x20		/* accept runt packets */
#define	QE_MR_UTR_FCOLL		0x10		/* force collision status */
#define	QE_MR_UTR_RCVSFCSE	0x08		/* enable fcs on rx */
#define	QE_MR_UTR_INTLOOPM	0x06		/* Internal loopback w/mandec */
#define	QE_MR_UTR_INTLOOP	0x04		/* Internal loopback */
#define	QE_MR_UTR_EXTLOOP	0x02		/* external loopback */
#define	QE_MR_UTR_NOLOOP	0x00		/* no loopback */

/*
 * QE receive descriptor
 */
struct qe_rxd {
	volatile u_int32_t rx_flags;		/* rx descriptor flags */
	volatile u_int32_t rx_addr;		/* rx buffer address */
};

#define	QE_RXD_OWN		0x80000000	/* ownership: 1=hw, 0=sw */
#define	QE_RXD_UPDATE		0x10000000	/* being updated? */
#define	QE_RXD_LENGTH		0x000007ff	/* packet length */

/*
 * QE transmit descriptor
 */
struct qe_txd {
	volatile u_int32_t tx_flags;		/* tx descriptor flags */
	volatile u_int32_t tx_addr;		/* tx buffer address */
};

#define	QE_TXD_OWN		0x80000000	/* ownership: 1=hw, 0=sw */
#define	QE_TXD_SOP		0x40000000	/* start of packet marker */
#define	QE_TXD_EOP		0x20000000	/* end of packet marker */
#define	QE_TXD_UPDATE		0x10000000	/* being updated? */
#define	QE_TXD_LENGTH		0x000007ff	/* packet length */

/* Buffer and Ring sizes: fixed ring size */
#define	QE_TX_RING_MAXSIZE	256		/* maximum tx ring size */
#define	QE_RX_RING_MAXSIZE	256		/* maximum rx ring size */
#define	QE_TX_RING_SIZE		16		/* power of 2, <= MAXSIZE */
#define	QE_RX_RING_SIZE		16		/* power of 2, <= MAXSIZE */
#define	QE_PKT_BUF_SZ		2048

#define	QE_TX_RING_MAXMASK	(QE_TX_RING_MAXSIZE-1)
#define	QE_RX_RING_MAXMASK	(QE_RX_RING_MAXSIZE-1)
#define	QE_TX_RING_MASK		(QE_TX_RING_SIZE-1)
#define	QE_RX_RING_MASK		(QE_RX_RING_SIZE-1)

/*
 * QE descriptor rings
 */
struct qe_desc {
	struct qe_rxd qe_rxd[QE_RX_RING_MAXSIZE];
	struct qe_txd qe_txd[QE_TX_RING_MAXSIZE];
};

/*
 * QE packet buffers
 */
struct qe_bufs {
	char	rx_buf[QE_RX_RING_SIZE][QE_PKT_BUF_SZ];
	char	tx_buf[QE_TX_RING_SIZE][QE_PKT_BUF_SZ];
};

#define	MC_POLY_LE	0xedb88320	/* mcast crc, little endian */


code:
/*	$OpenBSD: qevar.h,v 1.6 2006/06/02 20:00:54 miod Exp $	*/

/*
 * Copyright (c) 1998, 2000 Jason L. Wright.
 * 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 AUTHORS ``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 AUTHORS 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.
 */

struct qesoftc {
	struct	device sc_dev;
	struct	intrhand sc_ih;		/* interrupt vectoring */
	struct	arpcom sc_arpcom;	/* ethernet common */

	struct	qec_softc *sc_qec;	/* QEC parent */
	struct	qecregs *sc_qr;		/* QEC registers */
	struct	qe_mregs *sc_mr;	/* MACE registers */
	struct	qe_cregs *sc_cr;	/* Channel registers */

	int	sc_channel;
	u_int	sc_rev;

	int	sc_burst;

	struct	qe_bufs *sc_bufs, *sc_bufs_dva;
	struct	qe_desc *sc_desc, *sc_desc_dva;

	int	sc_no_td, sc_first_td, sc_last_td;
	int	sc_last_rd;
	struct	ifmedia sc_ifmedia;
};


code:
/*	$OpenBSD: qlw_sbus.c,v 1.3 2015/03/30 20:30:22 miod Exp $	*/
/*
 * Copyright (c) 2014 Mark Kettenis
 *
 * 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 <sys/param.h>
#include <sys/device.h>
#include <sys/malloc.h>
#include <sys/systm.h>

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

#include <sparc/dev/sbusvar.h>
#include <sparc/dev/dmareg.h>

#include <scsi/scsi_all.h>
#include <scsi/scsiconf.h>

#include <dev/ic/qlwreg.h>
#include <dev/ic/qlwvar.h>

#ifndef ISP_NOFIRMWARE
#include <dev/microcode/isp/asm_sbus.h>
#endif

struct qlw_sbus_softc {
	struct qlw_softc	qsc_sc;
	struct intrhand		qsc_ih;
	struct rom_reg		qsc_rr;
};

int	qlw_sbus_match(struct device *, void *, void *);
void	qlw_sbus_attach(struct device *, struct device *, void *);

struct cfattach qlw_sbus_ca = {
	sizeof(struct qlw_softc),
	qlw_sbus_match,
	qlw_sbus_attach
};

int
qlw_sbus_match(struct device *parent, void *cf, void *aux)
{
	struct confargs *ca = aux;
	struct romaux *ra = &ca->ca_ra;

	if (strcmp("ptisp", ra->ra_name) == 0 ||
	    strcmp("PTI,ptisp", ra->ra_name) == 0 ||
	    strcmp("SUNW,isp", ra->ra_name) == 0 ||
	    strcmp("QLGC,isp", ra->ra_name) == 0)
		return 2;

	return 0;
}

void
qlw_sbus_attach(struct device *parent, struct device *self, void *aux)
{
	struct confargs *ca = aux;
	struct romaux *ra = &ca->ca_ra;
	struct qlw_sbus_softc *qsc = (void *)self;
	struct qlw_softc *sc = &qsc->qsc_sc;
	u_int32_t sbusburst, burst;
	int freq;

	if (ra->ra_nintr < 1) {
		printf(": no interrupt\n");
		return;
	}

	if (ra->ra_nreg < 1) {
		printf(": no registers\n");
		return;
	}

	if (bus_space_map(&ra->ra_reg[0], 0,
	    ra->ra_reg[0].rr_len, 0, &sc->sc_ioh) != 0) {
		printf(": can't map registers\n");
		return;
	}

	printf(": %s\n", ra->ra_name);

	qsc->qsc_ih.ih_fun = qlw_intr;
	qsc->qsc_ih.ih_arg = sc;
	intr_establish(ra->ra_intr[0].int_pri, &qsc->qsc_ih,
	    IPL_BIO, self->dv_xname);

	/*
	 * Get transfer burst size from PROM
	 */
	sbusburst = ((struct sbus_softc *)parent)->sc_burst;
	if (sbusburst == 0)
		sbusburst = SBUS_BURST_32 - 1; /* 1->16 */

	burst = getpropint(ra->ra_node, "burst-sizes", -1);
	if (burst == -1)
		burst = sbusburst;

	/* Clamp at parent's burst sizes */
	burst &= sbusburst;

	if ((burst & SBUS_BURST_32))
		sc->sc_isp_config = QLW_BURST_ENABLE | QLW_SBUS_FIFO_32;
	else if ((burst & SBUS_BURST_16))
		sc->sc_isp_config = QLW_BURST_ENABLE | QLW_SBUS_FIFO_16;
	else if ((burst & SBUS_BURST_8))
		sc->sc_isp_config = QLW_BURST_ENABLE | QLW_SBUS_BURST_8;

	qsc->qsc_rr = ra->ra_reg[0];
	sc->sc_iot = &qsc->qsc_rr;
	sc->sc_ios = ra->ra_reg[0].rr_len;
	sc->sc_dmat = ca->ca_dmat;

	sc->sc_isp_gen = QLW_GEN_ISP1000;
	sc->sc_isp_type = QLW_ISP1000;
	sc->sc_numbusses = 1;

	freq = getpropint(ra->ra_node, "clock-frequency", 40000000);
	sc->sc_clock = (freq + 500000) / 1000000;

#ifndef ISP_NOFIRMWARE
	/*
	 * Some early versions of the PTI cards don't support loading
	 * a new firmware, so only do this in the Sun or QLogic
	 * branded ones.
	 */
	if (strcmp("SUNW,isp", ra->ra_name) == 0 ||
	    strcmp("QLGC,isp", ra->ra_name) == 0)
		sc->sc_firmware = isp_1000_risc_code;
#endif

	sc->sc_initiator[0] = getpropint(ra->ra_node, "scsi-initiator-id", 6);

	sc->sc_host_cmd_ctrl = QLW_HOST_CMD_CTRL_SBUS;
	sc->sc_mbox_base = QLW_MBOX_BASE_SBUS;

	qlw_attach(sc);
	return;
}


code:
/*	$OpenBSD: rfx.c,v 1.17 2015/03/28 19:07:07 miod Exp $	*/

/*
 * Copyright (c) 2004, Miodrag Vallat.
 * 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.
 *
 */

/*
 * Driver for the Vitec RasterFlex family of frame buffers.
 * It should support RasterFlex-24, RasterFlex-32 and RasterFlex-HR.
 */

#include <sys/param.h>
#include <sys/systm.h>
#include <sys/buf.h>
#include <sys/device.h>
#include <sys/ioctl.h>
#include <sys/malloc.h>
#include <sys/mman.h>
#include <sys/tty.h>
#include <sys/conf.h>

#include <uvm/uvm_extern.h>

#include <machine/autoconf.h>
#include <machine/pmap.h>
#include <machine/cpu.h>
#include <machine/conf.h>

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

#include <dev/ic/bt463reg.h>

/*
 * Configuration structure
 */
struct rfx_config {
	u_int16_t	unknown;
	u_int16_t	version;
	u_int32_t	scanline;
	u_int32_t	maxwidth;	/* unsure */
	u_int32_t	maxheight;	/* unsure */
	u_int32_t	width;
	u_int32_t	height;
};

/*
 * In-memory offsets
 */

#define	RFX_RAMDAC_ADDR		0x00020000
#define	RFX_RAMDAC_SIZE		0x00000004

#define	RFX_CONTROL_ADDR	0x00040000
#define	RFX_CONTROL_SIZE	0x000000e0

#define	RFX_INIT_ADDR		0x00018000
#define	RFX_INIT_OFFSET		0x0000001c
#define	RFX_INIT_SIZE		0x00008000

#define	RFX_VRAM_ADDR		0x00100000

/*
 * Control registers
 */

#define	RFX_VIDCTRL_REG		0x10
#define	RFX_VSYNC_ENABLE	0x00000001
#define	RFX_VIDEO_DISABLE	0x00000002

/*
 * Shadow colormap
 */
struct rfx_cmap {
	u_int8_t	red[256];
	u_int8_t	green[256];
	u_int8_t	blue[256];
};

struct rfx_softc {
	struct	sunfb		 sc_sunfb;
	struct	rom_reg		 sc_phys;
	struct	intrhand	 sc_ih;

	struct rfx_cmap		 sc_cmap;
	volatile u_int8_t	*sc_ramdac;
	volatile u_int32_t	*sc_ctrl;
};

void	rfx_burner(void *, u_int, u_int);
int	rfx_ioctl(void *, u_long, caddr_t, int, struct proc *);
paddr_t	rfx_mmap(void *, off_t, int);

int	rfx_getcmap(struct rfx_cmap *, struct wsdisplay_cmap *);
void	rfx_initialize(struct rfx_softc *, struct rfx_config *);
int	rfx_intr(void *);
void	rfx_loadcmap(struct rfx_softc *, int, int);
int	rfx_putcmap(struct rfx_cmap *, struct wsdisplay_cmap *);
void	rfx_setcolor(void *, u_int, u_int8_t, u_int8_t, u_int8_t);

struct wsdisplay_accessops rfx_accessops = {
	.ioctl = rfx_ioctl,
	.mmap = rfx_mmap,
	.burn_screen = rfx_burner
};

int	rfxmatch(struct device *, void *, void *);
void	rfxattach(struct device *, struct device *, void *);

#if defined(OpenBSD)

struct cfattach rfx_ca = {
	sizeof (struct rfx_softc), rfxmatch, rfxattach
};

struct cfdriver rfx_cd = {
	NULL, "rfx", DV_DULL
};

#else

CFATTACH_DECL(rfx, sizeof (struct rfx_softc), rfxmatch, rfxattach, NULL, NULL);

#endif

/*
 * Match a supported RasterFlex card.
 */
int
rfxmatch(struct device *parent, void *vcf, void *aux)
{
	struct confargs *ca = aux;
	struct romaux *ra = &ca->ca_ra;
	const char *device = ra->ra_name;

	/* skip vendor name (could be CWARE, VITec, ...) */
	while (*device != ',' && *device != '\0')
		device++;
	if (*device == '\0')
		device = ra->ra_name;
	else
		device++;

	if (strncmp(device, "RasterFLEX", strlen("RasterFLEX")) != 0)
		return (0);

	/* RasterVideo and RasterFlex-TV are frame grabbers */
	if (strcmp(device, "RasterFLEX-TV") == 0)
		return (0);

	return (1);
}

/*
 * Attach and initialize a rfx display, as well as a child wsdisplay.
 */
void
rfxattach(struct device *parent, struct device *self, void *args)
{
	struct rfx_softc *sc = (struct rfx_softc *)self;
	struct confargs *ca = args;
	const char *device = ca->ca_ra.ra_name;
	struct rfx_config cf;
	int node, cflen, isconsole;
#if 0
	int pri;
#endif

#if 0
	pri = ca->ca_ra.ra_intr[0].int_pri;
	printf(" pri %d", pri);
#endif

	/* skip vendor name (could be CWARE, VITec, ...) */
	while (*device != ',' && *device != '\0')
		device++;
	if (*device == '\0')
		device = ca->ca_ra.ra_name;
	else
		device++;
	printf(": %s", device);

	if (ca->ca_ra.ra_nreg == 0) {
		printf("\n%s: no SBus registers!\n",
		    self->dv_xname);
		return;
	}

	node = ca->ca_ra.ra_node;
	isconsole = node == fbnode;

	/*
	 * Parse configuration structure
	 */
	cflen = getproplen(node, "configuration");
	if (cflen != sizeof cf) {
		printf(", unknown %d bytes conf. structure", cflen);
		/* fill in default values */
		cf.version = 0;
		cf.scanline = 2048;
		cf.width = 1152;
		cf.height = 900;
	} else {
		getprop(node, "configuration", &cf, cflen);
		printf(", revision %d", cf.version);
	}

	/*
	 * Map registers
	 */
	sc->sc_ramdac = (u_int8_t *)
	    mapiodev(ca->ca_ra.ra_reg, RFX_RAMDAC_ADDR, RFX_RAMDAC_SIZE);
	sc->sc_ctrl = (u_int32_t *)
	    mapiodev(ca->ca_ra.ra_reg, RFX_CONTROL_ADDR, RFX_CONTROL_SIZE);
	sc->sc_phys = ca->ca_ra.ra_reg[0];

#if 0	/* not yet */
	sc->sc_ih.ih_fun = rfx_intr;
	sc->sc_ih.ih_arg = sc;
	intr_establish(pri, &sc->sc_ih, IPL_FB, self->dv_xname);
#endif

	/*
	 * The following is an equivalent for
	 *   fb_setsize(&sc->sc_sunfb, 8, cf.width, cf.height,
	 *     node, ca->ca_bustype);
	 * forcing the correct scan line value. Since the usual frame buffer
	 * properties are missing on this card, no need to go through
	 * fb_setsize()...
	 */
	sc->sc_sunfb.sf_depth = 8;
	sc->sc_sunfb.sf_width = cf.width;
	sc->sc_sunfb.sf_height = cf.height;
	sc->sc_sunfb.sf_linebytes = cf.scanline;
	sc->sc_sunfb.sf_fbsize = cf.height * cf.scanline;

	printf(", %dx%d\n", sc->sc_sunfb.sf_width, sc->sc_sunfb.sf_height);

	sc->sc_sunfb.sf_ro.ri_bits = mapiodev(ca->ca_ra.ra_reg,
	    RFX_VRAM_ADDR, round_page(sc->sc_sunfb.sf_fbsize));
	sc->sc_sunfb.sf_ro.ri_hw = sc;

	/*
	 * If we are not the console, the frame buffer has not been
	 * initialized by the PROM - do this ourselves.
	 */
	if (!isconsole)
		rfx_initialize(sc, &cf);

	fbwscons_init(&sc->sc_sunfb, isconsole);

	bzero(&sc->sc_cmap, sizeof(sc->sc_cmap));
	fbwscons_setcolormap(&sc->sc_sunfb, rfx_setcolor);

	if (isconsole)
		fbwscons_console_init(&sc->sc_sunfb, -1);

	/* enable video */
	rfx_burner(sc, 1, 0);

	fbwscons_attach(&sc->sc_sunfb, &rfx_accessops, isconsole);
}

/*
 * Common wsdisplay operations
 */

int
rfx_ioctl(void *v, u_long cmd, caddr_t data, int flags, struct proc *p)
{
	struct rfx_softc *sc = v;
	struct wsdisplay_cmap *cm;
	struct wsdisplay_fbinfo *wdf;
	int error;

	switch (cmd) {
	case WSDISPLAYIO_GTYPE:
		*(u_int *)data = WSDISPLAY_TYPE_RFLEX;
		break;
	case WSDISPLAYIO_GINFO:
		wdf = (struct wsdisplay_fbinfo *)data;
		wdf->height = sc->sc_sunfb.sf_height;
		wdf->width  = sc->sc_sunfb.sf_width;
		wdf->depth  = sc->sc_sunfb.sf_depth;
		wdf->cmsize = 256;
		break;
	case WSDISPLAYIO_LINEBYTES:
		*(u_int *)data = sc->sc_sunfb.sf_linebytes;
		break;

	case WSDISPLAYIO_GETCMAP:
		cm = (struct wsdisplay_cmap *)data;
		error = rfx_getcmap(&sc->sc_cmap, cm);
		if (error != 0)
			return (error);
		break;
	case WSDISPLAYIO_PUTCMAP:
		cm = (struct wsdisplay_cmap *)data;
		error = rfx_putcmap(&sc->sc_cmap, cm);
		if (error != 0)
			return (error);
		rfx_loadcmap(sc, cm->index, cm->count);
		break;

	case WSDISPLAYIO_SVIDEO:
	case WSDISPLAYIO_GVIDEO:
		break;

	default:
		return (-1);
        }

	return (0);
}

paddr_t
rfx_mmap(void *v, off_t offset, int prot)
{
	struct rfx_softc *sc = v;

	if (offset & PGOFSET)
		return (-1);

	if (offset >= 0 && offset < sc->sc_sunfb.sf_fbsize) {
		return (REG2PHYS(&sc->sc_phys, RFX_VRAM_ADDR + offset) |
		    PMAP_NC);
	}

	return (-1);
}

void
rfx_burner(void *v, u_int on, u_int flags)
{
	struct rfx_softc *sc = v;

	if (on) {
		sc->sc_ctrl[RFX_VIDCTRL_REG] &= ~RFX_VIDEO_DISABLE;
		sc->sc_ctrl[RFX_VIDCTRL_REG] |= RFX_VSYNC_ENABLE;
	} else {
		sc->sc_ctrl[RFX_VIDCTRL_REG] |= RFX_VIDEO_DISABLE;
		if (flags & WSDISPLAY_BURN_VBLANK)
			sc->sc_ctrl[RFX_VIDCTRL_REG] &= ~RFX_VSYNC_ENABLE;
	}
}

/*
 * Colormap helper functions
 */

void
rfx_setcolor(void *v, u_int index, u_int8_t r, u_int8_t g, u_int8_t b)
{
	struct rfx_softc *sc = v;

	sc->sc_cmap.red[index] = r;
	sc->sc_cmap.green[index] = g;
	sc->sc_cmap.blue[index] = b;

	rfx_loadcmap(sc, index, 1);
}

int
rfx_getcmap(struct rfx_cmap *cm, struct wsdisplay_cmap *rcm)
{
	u_int index = rcm->index, count = rcm->count;
	int error;

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

	if ((error = copyout(cm->red + index, rcm->red, count)) != 0)
		return (error);
	if ((error = copyout(cm->green + index, rcm->green, count)) != 0)
		return (error);
	if ((error = copyout(cm->blue + index, rcm->blue, count)) != 0)
		return (error);

	return (0);
}

int
rfx_putcmap(struct rfx_cmap *cm, struct wsdisplay_cmap *rcm)
{
	u_int index = rcm->index, count = rcm->count;
	u_int8_t red[256], green[256], blue[256];
	int error;

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

	if ((error = copyin(rcm->red, red, count)) != 0)
		return (error);
	if ((error = copyin(rcm->green, green, count)) != 0)
		return (error);
	if ((error = copyin(rcm->blue, blue, count)) != 0)
		return (error);

	bcopy(red, cm->red + index, count);
	bcopy(green, cm->green + index, count);
	bcopy(blue, cm->blue + index, count);

	return (0);
}

void
rfx_loadcmap(struct rfx_softc *sc, int start, int ncolors)
{
	u_int8_t *r, *g, *b;

	r = sc->sc_cmap.red + start;
	g = sc->sc_cmap.green + start;
	b = sc->sc_cmap.blue + start;

	start += BT463_IREG_CPALETTE_RAM;
	sc->sc_ramdac[BT463_REG_ADDR_LOW] = start & 0xff;
	sc->sc_ramdac[BT463_REG_ADDR_HIGH] = (start >> 8) & 0xff;

	while (ncolors-- != 0) {
		sc->sc_ramdac[BT463_REG_CMAP_DATA] = *r++;
		sc->sc_ramdac[BT463_REG_CMAP_DATA] = *g++;
		sc->sc_ramdac[BT463_REG_CMAP_DATA] = *b++;
	}
}

/*
 * Initialization code parser
 */

void
rfx_initialize(struct rfx_softc *sc, struct rfx_config *cf)
{
	u_int32_t *data, offset, value;
	size_t cnt;

	/*
	 * Map the initialization data - this is a waste as we won't be
	 * able to reclaim this mapping...
	 */
	data = (u_int32_t *)
	    mapiodev(&sc->sc_phys, RFX_INIT_ADDR, RFX_INIT_SIZE);

	/*
	 * Skip copyright notice
	 */
	data += RFX_INIT_OFFSET / sizeof(u_int32_t);
	cnt = (RFX_INIT_SIZE - RFX_INIT_OFFSET) / sizeof(u_int32_t);
	cnt >>= 1;

	/*
	 * Parse and apply settings
	 */
	while (cnt != 0) {
		offset = *data++;
		value = *data++;

		if (offset == (u_int32_t)-1 && value == (u_int32_t)-1)
			break;

		/* Old PROM are little-endian */
		if (cf->version <= 1) {
			offset = letoh32(offset);
			value = letoh32(offset);
		}

		if (offset & (1U << 31)) {
			offset = (offset & ~(1U << 31)) - RFX_RAMDAC_ADDR;
			if (offset < RFX_RAMDAC_SIZE)
				sc->sc_ramdac[offset] = value >> 24;
		} else {
			offset -= RFX_CONTROL_ADDR;
			if (offset < RFX_CONTROL_SIZE)
				sc->sc_ctrl[offset >> 2] = value;
		}

		cnt--;
	}
}


code:
/*	$OpenBSD: sbus.c,v 1.21 2015/03/30 20:30:22 miod Exp $	*/
/*	$NetBSD: sbus.c,v 1.17 1997/06/01 22:10:39 pk Exp $ */

/*
 * Copyright (c) 1992, 1993
 *	The Regents of the University of California.  All rights reserved.
 *
 * This software was developed by the Computer Systems Engineering group
 * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
 * contributed to Berkeley.
 *
 * All advertising materials mentioning features or use of this software
 * must display the following acknowledgement:
 *	This product includes software developed by the University of
 *	California, Lawrence Berkeley Laboratory.
 *
 * 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.
 *
 *	@(#)sbus.c	8.1 (Berkeley) 6/11/93
 */

/*
 * SBus stuff.
 */

#include <sys/param.h>
#include <sys/malloc.h>
#include <sys/systm.h>
#include <sys/device.h>
#include <uvm/uvm_extern.h>

#include <machine/autoconf.h>

#include <sparc/dev/sbusreg.h>
#include <sparc/dev/sbusvar.h>
#include <sparc/dev/xboxreg.h>
#include <sparc/dev/xboxvar.h>
#include <sparc/dev/dmareg.h>

int sbus_print(void *, const char *);

/* autoconfiguration driver */
void	sbus_attach(struct device *, struct device *, void *);
int	sbus_match(struct device *, void *, void *);
int	sbus_search(struct device *, void *, void *);

struct cfattach sbus_ca = {
	sizeof(struct sbus_softc), sbus_match, sbus_attach
};

struct cfdriver sbus_cd = {
	NULL, "sbus", DV_DULL
};

/*
 * SBus driver attach arguments.
 * We carry a few more information than a mere struct confargs internally,
 * for the sake of sbus_match() and sbus_print().
 */
struct sbus_attach_args {
	struct confargs	sa_ca;
	int		sa_slave_only;
	int		sa_unsupported;
};

static /*const*/ char *sl = "slave-only";

/*
 * Print the location of some sbus-attached device (called just
 * before attaching that device).  If `sbus' is not NULL, the
 * device was found but not configured; print the sbus as well.
 * Return UNCONF (config_find ignores this if the device was configured).
 */
int
sbus_print(void *args, const char *sbus)
{
	struct sbus_attach_args *sa = args;
	char *class;

	if (sbus != NULL) {
		printf("\"%s\" at %s", sa->sa_ca.ca_ra.ra_name, sbus);
		class = getpropstring(sa->sa_ca.ca_ra.ra_node, "device_type");
		if (*class != '\0')
			printf(" class %s", class);
	}
	if (sa->sa_slave_only)
		printf(" %s", sl);
	printf(" slot %d offset 0x%x", sa->sa_ca.ca_slot, sa->sa_ca.ca_offset);

	return sa->sa_unsupported != 0 ? UNSUPP : UNCONF;
}

int
sbus_match(struct device *parent, void *vcf, void *aux)
{
	struct cfdata *cf = vcf;
	struct confargs *ca = aux;
	struct romaux *ra = &ca->ca_ra;

	if (CPU_ISSUN4)
		return (0);

	if (ca->ca_bustype == BUS_XBOX) {
		struct xbox_softc *xsc = (struct xbox_softc *)parent;

		/* Prevent multiple attachments */
		if (xsc->sc_attached == 0) {
			xsc->sc_attached = 1;
			return (1);
		}

		return (0);
	}

	return (strcmp(cf->cf_driver->cd_name, ra->ra_name) == 0);
}

/*
 * Attach an SBus.
 */
void
sbus_attach(struct device *parent, struct device *self, void *aux)
{
	struct sbus_softc *sc = (struct sbus_softc *)self;
	struct confargs *ca = aux;
	struct romaux *ra = &ca->ca_ra;
	int node;
	char *name;
	struct sbus_attach_args saa;
	int rlen;

	/*
	 * XXX there is only one SBus, for now -- do not know how to
	 * address children on others
	 */
	if (sc->sc_dev.dv_unit > 0 && ca->ca_bustype != BUS_XBOX) {
		printf(" unsupported\n");
		return;
	}

	/*
	 * Record clock frequency for synchronous SCSI.
	 * IS THIS THE CORRECT DEFAULT??
	 */
	node = ra->ra_node;
	sc->sc_clockfreq = getpropint(node, "clock-frequency", -1);
	if (sc->sc_clockfreq <= 0)
		sc->sc_clockfreq = getpropint(findroot(), "clock-frequency",
		    25 * 1000 * 1000);
	printf(": %s MHz\n", clockfreq(sc->sc_clockfreq));

	/*
	 * Get the SBus burst transfer size if burst transfers are supported
	 */
	sc->sc_burst = getpropint(node, "burst-sizes", 0);
	sc->sc_burst = sc->sc_burst & ~SBUS_BURST_64;

	if (ca->ca_bustype == BUS_XBOX) {
		struct xbox_softc *xsc = (struct xbox_softc *)parent;

		/* Parent has already done the leg work */
		sc->sc_nrange = xsc->sc_nrange;
		sc->sc_range = xsc->sc_range;
		xsc->sc_attached = 2;

		sc->sc_slave_only = getpropint(node, sl, 0);
	} else {
		/* Check root node for 'slave-only' property */
		sc->sc_slave_only = getpropint(0, sl, 0);

		rlen = getproplen(node, "ranges");
		if (rlen > 0) {
			sc->sc_nrange = rlen / sizeof(struct rom_range);
			sc->sc_range =
			    (struct rom_range *)malloc(rlen, M_DEVBUF, M_NOWAIT);
			if (sc->sc_range == NULL)
				panic("sbus: PROM ranges too large: %d", rlen);
			(void)getprop(node, "ranges", sc->sc_range, rlen);
		}
	}

	if (ca->ca_bustype != BUS_XBOX && ra->ra_bp != NULL &&
	    strcmp(ra->ra_bp->name, "sbus") == 0)
		saa.sa_ca.ca_ra.ra_bp = ra->ra_bp + 1;
	else
		saa.sa_ca.ca_ra.ra_bp = NULL;

	/*
	 * Loop through ROM children, fixing any relative addresses
	 * and then configuring each device.
	 */
	for (node = firstchild(node); node; node = nextsibling(node)) {
		name = getpropstring(node, "name");
#ifdef SUN4E
		if (CPU_ISSUN4E && strcmp(name, "vm") == 0)
			continue;
#endif
		if (!romprop(&saa.sa_ca.ca_ra, name, node))
			continue;

		saa.sa_ca.ca_bustype = BUS_SBUS;
		saa.sa_ca.ca_dmat = ca->ca_dmat;
		saa.sa_unsupported = sbus_translate(self, &saa.sa_ca) != 0;
		saa.sa_slave_only =
		    sc->sc_slave_only & (1 << saa.sa_ca.ca_slot);

		config_found_sm(&sc->sc_dev, (void *)&saa, sbus_print,
		    sbus_search);
	}
}

int
sbus_search(struct device *parent, void *vcf, void *args)
{
	struct cfdata *cf = vcf;
	struct sbus_attach_args *saa = args;

	if (saa->sa_unsupported != 0)
		return 0;

	return (cf->cf_attach->ca_match)(parent, cf, &saa->sa_ca);
}

int
sbus_translate(struct device *dev, struct confargs *ca)
{
	struct sbus_softc *sc = (struct sbus_softc *)dev;
	int base, slot;
	int i;

	if (sc->sc_nrange == 0) {
		/* Old-style SBus configuration */
		base = (int)ca->ca_ra.ra_paddr;
		if (SBUS_ABS(base)) {
			ca->ca_slot = SBUS_ABS_TO_SLOT(base);
			ca->ca_offset = SBUS_ABS_TO_OFFSET(base);
		} else {
			if (!CPU_ISSUN4C && !CPU_ISSUN4E) {
				printf("%s: relative sbus addressing not supported\n",
				    dev->dv_xname);
				return ENXIO;
			}
			ca->ca_slot = slot = ca->ca_ra.ra_iospace;
			ca->ca_offset = base;

			/* Fix all register banks */
			for (i = 0; i < ca->ca_ra.ra_nreg; i++) {
				base = (int)ca->ca_ra.ra_reg[i].rr_paddr;
				if ((base & ~SBUS_PAGE_MASK) != 0)
					return ENXIO;
				ca->ca_ra.ra_reg[i].rr_paddr =
					(void *)SBUS_ADDR(slot, base);
				ca->ca_ra.ra_reg[i].rr_iospace = PMAP_OBIO;
			}
		}
	} else {
		ca->ca_slot = ca->ca_ra.ra_iospace;
		ca->ca_offset = (int)ca->ca_ra.ra_paddr;

		/* Translate into parent address spaces */
		for (i = 0; i < ca->ca_ra.ra_nreg; i++) {
			int j, cspace = ca->ca_ra.ra_reg[i].rr_iospace;

			for (j = 0; j < sc->sc_nrange; j++) {
				if (sc->sc_range[j].cspace == cspace) {
					ca->ca_ra.ra_reg[i].rr_paddr +=
						sc->sc_range[j].poffset;
					ca->ca_ra.ra_reg[i].rr_iospace =
						sc->sc_range[j].pspace;
					break;
				}
			}
		}
	}

	return 0;
}

/*
 * Returns true if this sbus slot is capable of dma
 */
int
sbus_testdma(struct sbus_softc *sc, struct confargs *ca)
{
        struct romaux *ra = &ca->ca_ra;

	if (sc->sc_slave_only & (1 << ca->ca_slot)) {
		printf("%s: dma card found in non-dma sbus slot %d"
			": not supported\n", ra->ra_name, ca->ca_slot);
		return (0);
	}

	return (1);
}


code:
/*	$OpenBSD: sbusreg.h,v 1.6 2010/07/10 19:32:24 miod Exp $	*/
/*	$NetBSD: sbusreg.h,v 1.3 1997/09/14 19:17:25 pk Exp $ */

/*
 * Copyright (c) 1992, 1993
 *	The Regents of the University of California.  All rights reserved.
 *
 * This software was developed by the Computer Systems Engineering group
 * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
 * contributed to Berkeley.
 *
 * All advertising materials mentioning features or use of this software
 * must display the following acknowledgement:
 *	This product includes software developed by the University of
 *	California, Lawrence Berkeley Laboratory.
 *
 * 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.
 *
 *	@(#)sbusreg.h	8.1 (Berkeley) 6/11/93
 */

/*
 * Sun-4c S-bus definitions.  (Should be made generic!)
 *
 * SBus slot 0 is not a separate slot; it talks to the onboard I/O devices.
 * It is, however, addressed just like any `real' SBus.
 *
 * SBus device addresses are obtained from the FORTH PROMs.  They come
 * in `absolute' and `relative' address flavors, so we have to handle both.
 * Relative addresses do *not* include the slot number.
 */
#define	SBUS_PAGE_SHIFT		(13 + PAGE_SHIFT)
#define	SBUS_BASE		(0 - (4 << SBUS_PAGE_SHIFT))
#define	SBUS_PAGE_MASK		((1 << SBUS_PAGE_SHIFT) - 1)
#define	SBUS_ADDR(slot, off)	(SBUS_BASE + ((slot) << SBUS_PAGE_SHIFT) + (off))
#define	SBUS_ABS(a)		((unsigned)(a) >= SBUS_BASE)
#define	SBUS_ABS_TO_SLOT(a)	(((a) - SBUS_BASE) >> SBUS_PAGE_SHIFT)
#define	SBUS_ABS_TO_OFFSET(a)	(((a) - SBUS_BASE) & SBUS_PAGE_MASK)

struct sbusreg {
	u_int32_t	sbus_afsr;	/* M-to-S Asynchronous Fault Status */
	u_int32_t	sbus_afar;	/* M-to-S Asynchronous Fault Address */
	u_int32_t	sbus_arbiter;	/* Arbiter Enable  */
	u_int32_t	sbus_reserved1;

#define NSBUSCFG	20
	/* Actual number dependent on machine model */
	u_int32_t	sbus_sbuscfg[NSBUSCFG];	/* SBus configuration control */
};


code:
/*	$OpenBSD: sbusvar.h,v 1.11 2015/03/30 20:30:22 miod Exp $	*/
/*	$NetBSD: sbusvar.h,v 1.4 1996/04/22 02:35:05 abrown Exp $ */

/*
 * Copyright (c) 1992, 1993
 *	The Regents of the University of California.  All rights reserved.
 *
 * This software was developed by the Computer Systems Engineering group
 * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
 * contributed to Berkeley.
 *
 * All advertising materials mentioning features or use of this software
 * must display the following acknowledgement:
 *	This product includes software developed by the University of
 *	California, Lawrence Berkeley Laboratory.
 *
 * 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.
 *
 *	@(#)sbusvar.h	8.1 (Berkeley) 6/11/93
 */

/*
 * SBus variables.
 */

/* variables per SBus */
struct sbus_softc {
	struct	device	sc_dev;		/* base device */
	int		sc_clockfreq;	/* clock frequency (in Hz) */
	struct	rom_range *sc_range;
	int		sc_nrange;
	int		sc_burst;	/* burst transfer sizes supported */
	int		sc_slave_only;
};

int	sbus_translate(struct device *, struct confargs *);
int	sbus_testdma(struct sbus_softc *, struct confargs *);


code:
/*	$OpenBSD: scf.c,v 1.10 2006/03/15 20:03:06 miod Exp $	*/

/*
 * Copyright (c) 1999 Jason L. Wright (jason@thought.net)
 * All rights reserved.
 *
 * This software was developed by Jason L. Wright under contract with
 * RTMX Incorporated (http://www.rtmx.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.
 */

/*
 * Driver for the flash memory and sysconfig registers found on Force CPU-5V
 * boards.
 */

#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/errno.h>
#include <sys/ioctl.h>
#include <sys/mbuf.h>
#include <sys/socket.h>
#include <sys/syslog.h>
#include <sys/device.h>
#include <sys/malloc.h>
#include <sys/timeout.h>

#include <machine/autoconf.h>
#include <sparc/cpu.h>
#include <sparc/sparc/cpuvar.h>
#include <machine/scfio.h>
#include <sparc/dev/scfreg.h>

int	scfmatch(struct device *, void *, void *);
void	scfattach(struct device *, struct device *, void *);

int	scfopen(dev_t, int, int, struct proc *);
int	scfclose(dev_t, int, int, struct proc *);
int	scfioctl(dev_t, u_long, caddr_t, int, struct proc *);

struct scf_softc {
	struct	device sc_dv;			/* base device */
	struct	scf_regs *sc_regs;	/* our registers */
	int	sc_open;
	int	sc_tick;
	struct	timeout sc_blink_tmo;	/* for scfblink() */
};

struct cfattach scf_ca = {
	sizeof (struct scf_softc), scfmatch, scfattach
};

struct cfdriver scf_cd = {
	NULL, "scf", DV_DULL
};

extern int sparc_led_blink;

static const u_int8_t scf_pattern[] = {
	SSLDCR_A|SSLDCR_B|SSLDCR_C|SSLDCR_D|SSLDCR_E|SSLDCR_F,
	SSLDCR_B|SSLDCR_C,
	SSLDCR_A|SSLDCR_B|SSLDCR_D|SSLDCR_E|SSLDCR_G,
	SSLDCR_A|SSLDCR_B|SSLDCR_C|SSLDCR_D|SSLDCR_G,
	SSLDCR_B|SSLDCR_C|SSLDCR_F|SSLDCR_G,
	SSLDCR_A|SSLDCR_C|SSLDCR_D|SSLDCR_F|SSLDCR_G,
	SSLDCR_A|SSLDCR_C|SSLDCR_D|SSLDCR_E|SSLDCR_F|SSLDCR_G,
	SSLDCR_A|SSLDCR_B|SSLDCR_C,
	SSLDCR_A|SSLDCR_B|SSLDCR_C|SSLDCR_D|SSLDCR_E|SSLDCR_F|SSLDCR_G,
	SSLDCR_A|SSLDCR_B|SSLDCR_C|SSLDCR_D|SSLDCR_F|SSLDCR_G,
	SSLDCR_A|SSLDCR_B|SSLDCR_C|SSLDCR_E|SSLDCR_F|SSLDCR_G,
	SSLDCR_C|SSLDCR_D|SSLDCR_E|SSLDCR_F|SSLDCR_G,
	SSLDCR_A|SSLDCR_D|SSLDCR_E|SSLDCR_F,
	SSLDCR_B|SSLDCR_C|SSLDCR_D|SSLDCR_E|SSLDCR_G,
	SSLDCR_A|SSLDCR_D|SSLDCR_E|SSLDCR_F|SSLDCR_G,
	SSLDCR_A|SSLDCR_E|SSLDCR_F|SSLDCR_G,
};

int
scfmatch(parent, vcf, aux)
	struct device *parent;
	void *vcf, *aux;
{
	struct confargs *ca = aux;
	register struct romaux *ra = &ca->ca_ra;

	if (strcmp("sysconfig", ra->ra_name))
		return (0);

	return (1);
}

void
scfattach(parent, self, aux)
	struct device *parent, *self;
	void *aux;
{
	struct confargs *ca = aux;
	struct scf_softc *sc = (struct scf_softc *)self;
	char *s;

	/* map registers */
	if (ca->ca_ra.ra_nreg != 1) {
		printf(": expected 1 register, got %d\n", ca->ca_ra.ra_nreg);
		return;
	}

	sc->sc_regs = mapiodev(&(ca->ca_ra.ra_reg[0]), 0,
			ca->ca_ra.ra_reg[0].rr_len);

	s = getpropstring(ca->ca_ra.ra_node, "model");
	printf(": model %s\n", s);

	sc->sc_regs->led1 &= ~LED_MASK;
	sc->sc_regs->led2 &= ~LED_MASK;
	sc->sc_regs->ssldcr = 0;

	timeout_set(&sc->sc_blink_tmo, scfblink, 0);

	if (sparc_led_blink)
		scfblink(0);
}

int
scfopen(dev, flags, mode, p)
	dev_t dev;
	int flags;
	int mode;
	struct proc *p;
{
	struct scf_softc *sc;
	int card = 0;

	if (card >= scf_cd.cd_ndevs)
		return (ENXIO);
	sc = scf_cd.cd_devs[card];
	if (sc == NULL)
		return (ENXIO);
	if (sc->sc_open)
		return (EBUSY);

	sc->sc_open = 1;
	return (0);
}

int
scfclose(dev, flags, mode, p)
	dev_t dev;
	int flags;
	int mode;
	struct proc *p;
{
	struct scf_softc *sc;
	int card = 0;

	sc = scf_cd.cd_devs[card];
	sc->sc_open = 0;
	return (0);
}

int
scfioctl(dev, cmd, data, flags, p)
	dev_t dev;
	u_long cmd;
	caddr_t data;
	int flags;
	struct proc *p;
{
	struct scf_softc *sc = scf_cd.cd_devs[0];
	u_int8_t *ptr = (u_int8_t *)data, c;
	int error = 0;

	switch (cmd) {
	case SCFIOCSLED1:
		sc->sc_regs->led1 = LED_MASK | (*ptr);
		break;
	case SCFIOCGLED1:
		*ptr = sc->sc_regs->led1 & (LED_COLOR_MASK | LED_BLINK_MASK);
		break;
	case SCFIOCSLED2:
		sc->sc_regs->led2 = LED_MASK | (*ptr);
		break;
	case SCFIOCGLED2:
		*ptr = sc->sc_regs->led2 & (LED_COLOR_MASK | LED_BLINK_MASK);
		break;
	case SCFIOCSLED7:
		sc->sc_regs->ssldcr = *ptr;
		break;
	case SCFIOCGLED7:
		*ptr = sc->sc_regs->ssldcr;
		break;
	case SCFIOCGROT:
		*ptr = sc->sc_regs->rssr;
		break;
	case SCFIOCSFMCTRL:
		if ((*ptr) & SCF_FMCTRL_SELROM)
			sc->sc_regs->fmpcr1 |= FMPCR1_SELROM;
		else
			sc->sc_regs->fmpcr1 &= ~FMPCR1_SELROM;

		if ((*ptr) & SCF_FMCTRL_SELBOOT)
			sc->sc_regs->fmpcr2 |= FMPCR2_SELBOOT;
		else
			sc->sc_regs->fmpcr2 &= ~FMPCR2_SELBOOT;

		if ((*ptr) & SCF_FMCTRL_WRITEV)
			sc->sc_regs->fmpvcr |= FMPVCR_VPP;
		else
			sc->sc_regs->fmpvcr &= ~FMPVCR_VPP;

		c = ((*ptr) & SCF_FMCTRL_SELADDR) >> 3;
		sc->sc_regs->fmpcr1 =
		    (sc->sc_regs->fmpcr1 & ~FMPCR1_SELADDR) | (c << 1);

		break;
	case SCFIOCGFMCTRL:
		c = (sc->sc_regs->fmpcr1 & FMPCR1_SELADDR) << 2;
		if (sc->sc_regs->fmpcr1 & FMPCR1_SELROM)
			c |= SCF_FMCTRL_SELROM;
		if (sc->sc_regs->fmpcr2 & FMPCR2_SELBOOT)
			c |= SCF_FMCTRL_SELBOOT;
		if (sc->sc_regs->fmpvcr & FMPVCR_VPP)
			c |= SCF_FMCTRL_WRITEV;
		*ptr = c;
		break;
	default:
		error = ENOTTY;
	}

	return (error);
}

void
scfblink(v)
        void *v;
{
	struct scf_softc *sc;
	int s, avg, hi = 0;

	if (scf_cd.cd_ndevs == 0)
		return;

	sc = scf_cd.cd_devs[0];
	if (sc == NULL)
		return;

	if (sparc_led_blink == 0) {
		sc->sc_regs->led1 &= ~LED_MASK;
		sc->sc_regs->led2 &= ~LED_MASK;
		sc->sc_regs->ssldcr = 0;
		return;
	}

	avg = averunnable.ldavg[0] >> FSHIFT;
	while (avg > 15) {
		hi = 1;
		avg >>= 4;
	}

	s = splhigh();
	if (sc->sc_tick & 1) {
		sc->sc_regs->led1 &= ~LED_MASK;
		sc->sc_regs->led2 |= LED_COLOR_GREEN;
	}
	else {
		sc->sc_regs->led1 |= LED_COLOR_YELLOW;
		sc->sc_regs->led2 &= ~LED_MASK;
	}
	sc->sc_regs->ssldcr = scf_pattern[avg] | (hi ? SSLDCR_P : 0);
	splx(s);

	sc->sc_tick++;

	s = ((averunnable.ldavg[0] + FSCALE) * hz) >> (FSHIFT + 1);
	timeout_add(&sc->sc_blink_tmo, s);
}


code:
/*	$OpenBSD: scfreg.h,v 1.2 2003/06/02 18:40:59 jason Exp $	*/

/*
 * Copyright (c) 1999 Jason L. Wright (jason@thought.net)
 * All rights reserved.
 *
 * This software was developed by Jason L. Wright under contract with
 * RTMX Incorporated (http://www.rtmx.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.
 */

struct scf_regs {
	volatile u_int8_t	led1;		/* user led 1 control */
	volatile u_int8_t	led2;		/* user led 2 control */
	volatile u_int8_t	fmpcr1;		/* flash prog control 1 */
	volatile u_int8_t	rssr;		/* rotary switch status */
	volatile u_int8_t	_reserved0[4];	/* unused */
	volatile u_int8_t	brscr;		/* boot ROM size ctrl */
	volatile u_int8_t	fmpcr2;		/* flash prog control reg 2 */
	volatile u_int8_t	fmpvcr;		/* flash prog voltage ctrl */
	volatile u_int8_t	ssldcr;		/* 7-segment led ctrl */
	volatile u_int8_t	fmb0;		/* FMB chan 0 data discard */
	volatile u_int8_t	fmb1;		/* FMB chan 1 data discard */
	volatile u_int8_t	_reserved1[1];	/* unused */
	volatile u_int8_t	lcaid;		/* LCA identification */
};

/* led1/led2: user led 1/led 2 control */
#define	LED_MASK		0x0f
#define	LED_COLOR_MASK		0x03	/* color mask */
#define	LED_COLOR_OFF		0x00	/* led is off */
#define	LED_COLOR_GREEN		0x01	/* led is green */
#define	LED_COLOR_RED		0x02	/* led is red */
#define	LED_COLOR_YELLOW	0x03	/* led is yellow */
#define	LED_BLINK_MASK		0x0c	/* blink mask */
#define	LED_BLINK_NONE		0x00	/* led does not blink */
#define	LED_BLINK_HALF		0x04	/* led blinks at 0.5hz */
#define	LED_BLINK_ONE		0x08	/* led blinks at 1.0hz */
#define	LED_BLINK_TWO		0x0c	/* led blinks at 2.0hz */

/* fmpcr1: flash memory programming control register 1 */
#define	FMPCR1_MASK		0xf0	/* must be or'd with this on write */
#define	FMPCR1_SELADDR		0x0e	/* address select */
#define	FMPCR1_SELROM		0x01	/* 0=first,1=second flash memory */

/* rssr: rotary switch status register */
#define	RSSR_MASK		0x0f	/* value of user rotary switch */

/* brscr: boot ROM size control register */
/* ??? */

/* fmpcr2: flash memory programming control register 2 */
#define	FMPCR2_MASK		0xfe	/* must be or'd with this on write */
#define	FMPCR2_SELBOOT		0x01	/* 0=USER,1=BOOT flash memory */

/* fmpvcr: flash memory programming voltage control register */
#define	FMPVCR_MASK		0xfe	/* must be or'd with this on write */
#define	FMPVCR_VPP		0x01	/* 1=prog voltage on, 0 = off */

/* fmb0/fmb1: FMB channel 0/1 data discard status register */
#define	FMB_MSBVALID	0x01		/* (ro) whether to discard FMB data */

/* ssldcr: seven segment LED display control register */
/*
 * Layout:
 *          AAA
 *         FF BB
 *	    GGG
 *	   EE CC
 *	    DDD  P
 */
#define	SSLDCR_A	0x01
#define	SSLDCR_B	0x02
#define	SSLDCR_C	0x04
#define	SSLDCR_D	0x08
#define	SSLDCR_E	0x10
#define	SSLDCR_F	0x20
#define	SSLDCR_G	0x40
#define	SSLDCR_P	0x80