code:
/*-
 * Copyright (c) 2001 Michael Smith
 * 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 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 AUTHOR 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.
 *
 *	$FreeBSD: release/9.0.0/sys/dev/ciss/cissvar.h 204648 2010-03-03 17:58:41Z mav $
 */

/*
 * CISS adapter driver datastructures
 */

typedef STAILQ_HEAD(, ciss_request)	cr_qhead_t;

/************************************************************************
 * Tunable parameters
 */

/*
 * There is no guaranteed upper bound on the number of concurrent
 * commands an adapter may claim to support.  Cap it at a reasonable
 * value.
 */
#define CISS_MAX_REQUESTS	1024

/*
 * Maximum number of logical drives we support.
 */
#define CISS_MAX_LOGICAL	15

/*
 * Maximum number of physical devices we support.
 */
#define CISS_MAX_PHYSICAL	1024

/*
 * Interrupt reduction can be controlled by tuning the interrupt
 * coalesce delay and count paramters.  The delay (in microseconds)
 * defers delivery of interrupts to increase the chance of there being
 * more than one completed command ready when the interrupt is
 * delivered.  The count expedites the delivery of the interrupt when
 * the given number of commands are ready.
 *
 * If the delay is set to 0, interrupts are delivered immediately.
 */
#define CISS_INTERRUPT_COALESCE_DELAY	0
#define CISS_INTERRUPT_COALESCE_COUNT	16

/*
 * Heartbeat routine timeout in seconds.  Note that since event
 * handling is performed on a callback basis, we don't need this to
 * run very often.
 */
#define CISS_HEARTBEAT_RATE		10

/************************************************************************
 * Compatibility with older versions of FreeBSD
 */
#if __FreeBSD_version < 440001
#warning testing old-FreeBSD compat
typedef struct proc	d_thread_t;
#endif

/************************************************************************
 * Driver version.  Only really significant to the ACU interface.
 */
#define CISS_DRIVER_VERSION	20011201

/************************************************************************
 * Driver data structures
 */

/*
 * Each command issued to the adapter is managed by a request
 * structure.
 */
struct ciss_request
{
    STAILQ_ENTRY(ciss_request)	cr_link;
    int				cr_onq;		/* which queue we are on */

    struct ciss_softc		*cr_sc;		/* controller softc */
    void			*cr_data;	/* data buffer */
    u_int32_t			cr_length;	/* data length */
    bus_dmamap_t		cr_datamap;	/* DMA map for data */
    struct ciss_command		*cr_cc;
    uint32_t			cr_ccphys;
    int				cr_tag;
    int				cr_flags;
#define CISS_REQ_MAPPED		(1<<0)		/* data mapped */
#define CISS_REQ_SLEEP		(1<<1)		/* submitter sleeping */
#define CISS_REQ_POLL		(1<<2)		/* submitter polling */
#define CISS_REQ_DATAOUT	(1<<3)		/* data host->adapter */
#define CISS_REQ_DATAIN		(1<<4)		/* data adapter->host */
#define CISS_REQ_BUSY		(1<<5)		/* controller has req */

    void			(* cr_complete)(struct ciss_request *);
    void			*cr_private;
    int				cr_sg_tag;
#define CISS_SG_MAX		((CISS_SG_FETCH_MAX << 1) | 0x1)
#define CISS_SG_1		((CISS_SG_FETCH_1 << 1) | 0x01)
#define CISS_SG_2		((CISS_SG_FETCH_2 << 1) | 0x01)
#define CISS_SG_4		((CISS_SG_FETCH_4 << 1) | 0x01)
#define CISS_SG_8		((CISS_SG_FETCH_8 << 1) | 0x01)
#define CISS_SG_16		((CISS_SG_FETCH_16 << 1) | 0x01)
#define CISS_SG_32		((CISS_SG_FETCH_32 << 1) | 0x01)
#define CISS_SG_NONE		((CISS_SG_FETCH_NONE << 1) | 0x01)
};

/*
 * The adapter command structure is defined with a zero-length
 * scatter/gather list size.  In practise, we want space for a
 * scatter-gather list, and we also want to avoid having commands
 * cross page boundaries.
 *
 * The size of the ciss_command is 52 bytes.  65 s/g elements are reserved
 * to allow a max i/o size of 256k.  This gives a total command size of
 * 1120 bytes, including the 32 byte alignment padding.  Modern controllers
 * seem to saturate nicely at this value.
 */

#define CISS_MAX_SG_ELEMENTS	65
#define CISS_COMMAND_ALIGN	32
#define CISS_COMMAND_SG_LENGTH	(sizeof(struct ciss_sg_entry) * CISS_MAX_SG_ELEMENTS)
#define CISS_COMMAND_ALLOC_SIZE		(roundup2(sizeof(struct ciss_command) + CISS_COMMAND_SG_LENGTH, CISS_COMMAND_ALIGN))

/*
 * Per-logical-drive data.
 */
struct ciss_ldrive
{
    union ciss_device_address	cl_address;
    union ciss_device_address	*cl_controller;
    int				cl_status;
#define CISS_LD_NONEXISTENT	0
#define CISS_LD_ONLINE		1
#define CISS_LD_OFFLINE		2

    int				cl_update;

    struct ciss_bmic_id_ldrive	*cl_ldrive;
    struct ciss_bmic_id_lstatus	*cl_lstatus;
    struct ciss_ldrive_geometry	cl_geometry;

    char			cl_name[16];		/* device name */
};

/*
 * Per-physical-drive data
 */
struct ciss_pdrive
{
    union ciss_device_address	cp_address;
    int				cp_online;
};

#define CISS_PHYSICAL_SHIFT	5
#define CISS_PHYSICAL_BASE	(1 << CISS_PHYSICAL_SHIFT)
#define CISS_MAX_PHYSTGT	256

#define CISS_IS_PHYSICAL(bus)	(bus >= CISS_PHYSICAL_BASE)
#define CISS_CAM_TO_PBUS(bus)	(bus - CISS_PHYSICAL_BASE)

/*
 * Per-adapter data
 */
struct ciss_softc
{
    /* bus connections */
    device_t			ciss_dev;		/* bus attachment */
    struct cdev *ciss_dev_t;		/* control device */

    struct resource		*ciss_regs_resource;	/* register interface window */
    int				ciss_regs_rid;		/* resource ID */
    bus_space_handle_t		ciss_regs_bhandle;	/* bus space handle */
    bus_space_tag_t		ciss_regs_btag;		/* bus space tag */

    struct resource		*ciss_cfg_resource;	/* config struct interface window */
    int				ciss_cfg_rid;		/* resource ID */
    struct ciss_config_table	*ciss_cfg;		/* config table in adapter memory */
    struct ciss_perf_config	*ciss_perf;		/* config table for the performant */
    struct ciss_bmic_id_table	*ciss_id;		/* ID table in host memory */
    u_int32_t			ciss_heartbeat;		/* last heartbeat value */
    int				ciss_heart_attack;	/* number of times we have seen this value */

    int				ciss_msi;
    struct resource		*ciss_irq_resource;	/* interrupt */
    int				ciss_irq_rid[CISS_MSI_COUNT];		/* resource ID */
    void			*ciss_intr;		/* interrupt handle */

    bus_dma_tag_t		ciss_parent_dmat;	/* parent DMA tag */
    bus_dma_tag_t		ciss_buffer_dmat;	/* data buffer/command DMA tag */

    u_int32_t			ciss_interrupt_mask;	/* controller interrupt mask bits */

    uint64_t			*ciss_reply;
    int				ciss_cycle;
    int				ciss_rqidx;
    bus_dma_tag_t		ciss_reply_dmat;
    bus_dmamap_t		ciss_reply_map;
    uint32_t			ciss_reply_phys;

    int				ciss_max_requests;
    struct ciss_request		ciss_request[CISS_MAX_REQUESTS];	/* requests */
    void			*ciss_command;		/* command structures */
    bus_dma_tag_t		ciss_command_dmat;	/* command DMA tag */
    bus_dmamap_t		ciss_command_map;	/* command DMA map */
    u_int32_t			ciss_command_phys;	/* command array base address */
    cr_qhead_t			ciss_free;		/* requests available for reuse */
    cr_qhead_t			ciss_notify;		/* requests which are defered for processing */
    struct proc			*ciss_notify_thread;

    struct callout		ciss_periodic;		/* periodic event handling */
    struct ciss_request		*ciss_periodic_notify;	/* notify callback request */

    struct mtx			ciss_mtx;
    struct ciss_ldrive		**ciss_logical;
    struct ciss_pdrive		**ciss_physical;
    union ciss_device_address	*ciss_controllers;	/* controller address */
    int				ciss_max_bus_number;	/* maximum bus number */
    int				ciss_max_logical_bus;
    int				ciss_max_physical_bus;

    struct cam_devq		*ciss_cam_devq;
    struct cam_sim		**ciss_cam_sim;

    int				ciss_soft_reset;

    int				ciss_flags;
#define CISS_FLAG_NOTIFY_OK	(1<<0)		/* notify command running OK */
#define CISS_FLAG_CONTROL_OPEN	(1<<1)		/* control device is open */
#define CISS_FLAG_ABORTING	(1<<2)		/* driver is going away */
#define CISS_FLAG_RUNNING	(1<<3)		/* driver is running (interrupts usable) */
#define CISS_FLAG_BUSY		(1<<4)		/* no free commands */

#define CISS_FLAG_FAKE_SYNCH	(1<<16)		/* needs SYNCHRONISE_CACHE faked */
#define CISS_FLAG_BMIC_ABORT	(1<<17)		/* use BMIC command to abort Notify on Event */
#define CISS_FLAG_THREAD_SHUT	(1<<20)		/* shutdown the kthread */

    struct ciss_qstat		ciss_qstat[CISSQ_COUNT];	/* queue statistics */
};

/************************************************************************
 * Debugging/diagnostic output.
 */

/*
 * Debugging levels:
 *  0 - quiet, only emit warnings
 *  1 - talkative, log major events, but nothing on the I/O path
 *  2 - noisy, log events on the I/O path
 *  3 - extremely noisy, log items in loops
 */
#ifdef CISS_DEBUG
# define debug(level, fmt, args...)							\
	do {										\
	    if (level <= CISS_DEBUG) printf("%s: " fmt "\n", __func__ , ##args);	\
	} while(0)
# define debug_called(level)						\
	do {								\
	    if (level <= CISS_DEBUG) printf("%s: called\n", __func__);	\
	} while(0)
# define debug_struct(s)		printf("  SIZE %s: %zu\n", #s, sizeof(struct s))
# define debug_union(s)			printf("  SIZE %s: %zu\n", #s, sizeof(union s))
# define debug_type(s)			printf("  SIZE %s: %zu\n", #s, sizeof(s))
# define debug_field(s, f)		printf("  OFFSET %s.%s: %d\n", #s, #f, ((int)&(((struct s *)0)->f)))
# define debug_const(c)			printf("  CONST %s %jd/0x%jx\n", #c, (intmax_t)c, (intmax_t)c);
#else
# define debug(level, fmt, args...)
# define debug_called(level)
# define debug_struct(s)
# define debug_union(s)
# define debug_type(s)
# define debug_field(s, f)
# define debug_const(c)
#endif

#define ciss_printf(sc, fmt, args...)	device_printf(sc->ciss_dev, fmt , ##args)

/************************************************************************
 * Queue primitives
 */

#define CISSQ_ADD(sc, qname)					\
	do {							\
	    struct ciss_qstat *qs = &(sc)->ciss_qstat[qname];	\
								\
	    qs->q_length++;					\
	    if (qs->q_length > qs->q_max)			\
		qs->q_max = qs->q_length;			\
	} while(0)

#define CISSQ_REMOVE(sc, qname)    (sc)->ciss_qstat[qname].q_length--
#define CISSQ_INIT(sc, qname)			\
	do {					\
	    sc->ciss_qstat[qname].q_length = 0;	\
	    sc->ciss_qstat[qname].q_max = 0;	\
	} while(0)

#define CISSQ_REQUEST_QUEUE(name, index)				\
static __inline void							\
ciss_initq_ ## name (struct ciss_softc *sc)				\
{									\
    STAILQ_INIT(&sc->ciss_ ## name);					\
    CISSQ_INIT(sc, index);						\
}									\
static __inline void							\
ciss_enqueue_ ## name (struct ciss_request *cr)				\
{									\
									\
    STAILQ_INSERT_TAIL(&cr->cr_sc->ciss_ ## name, cr, cr_link);		\
    CISSQ_ADD(cr->cr_sc, index);					\
    cr->cr_onq = index;							\
}									\
static __inline void							\
ciss_requeue_ ## name (struct ciss_request *cr)				\
{									\
									\
    STAILQ_INSERT_HEAD(&cr->cr_sc->ciss_ ## name, cr, cr_link);		\
    CISSQ_ADD(cr->cr_sc, index);					\
    cr->cr_onq = index;							\
}									\
static __inline struct ciss_request *					\
ciss_dequeue_ ## name (struct ciss_softc *sc)				\
{									\
    struct ciss_request	*cr;						\
									\
    if ((cr = STAILQ_FIRST(&sc->ciss_ ## name)) != NULL) {		\
	STAILQ_REMOVE_HEAD(&sc->ciss_ ## name, cr_link);		\
	CISSQ_REMOVE(sc, index);					\
	cr->cr_onq = -1;						\
    }									\
    return(cr);								\
}									\
struct hack

CISSQ_REQUEST_QUEUE(free, CISSQ_FREE);
CISSQ_REQUEST_QUEUE(notify, CISSQ_NOTIFY);

static __inline void
ciss_enqueue_complete(struct ciss_request *ac, cr_qhead_t *head)
{

    STAILQ_INSERT_TAIL(head, ac, cr_link);
}

static __inline struct ciss_request *
ciss_dequeue_complete(struct ciss_softc *sc, cr_qhead_t *head)
{
    struct ciss_request  *ac;

    if ((ac = STAILQ_FIRST(head)) != NULL)
        STAILQ_REMOVE_HEAD(head, cr_link);
    return(ac);
}

/********************************************************************************
 * space-fill a character string
 */
static __inline void
padstr(char *targ, const char *src, int len)
{
    while (len-- > 0) {
	if (*src != 0) {
	    *targ++ = *src++;
	} else {
	    *targ++ = ' ';
	}
    }
}

#define ciss_report_request(a, b, c)	\
	_ciss_report_request(a, b, c, __FUNCTION__)


code:
/*-
 * Copyright (c) 2003 Hidetoshi Shimokawa
 * Copyright (c) 1998-2002 Katsushi Kobayashi and Hidetoshi Shimokawa
 * 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 acknowledgement as bellow:
 *
 *    This product includes software developed by K. Kobayashi and H. Shimokawa
 *
 * 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.
 *
 * $FreeBSD: release/9.0.0/sys/dev/firewire/firewire.h 188726 2009-02-17 19:37:04Z sbruno $
 *
 */

#ifndef _FIREWIRE_H
#define _FIREWIRE_H 1

#define	DEV_DEF  0
#define	DEV_DV   2

struct fw_isochreq {
	unsigned char	ch:6,
			tag:2;
};

struct fw_isobufreq {
	struct fw_bufspec {
		unsigned int nchunk;
		unsigned int npacket;
		unsigned int psize;
	} tx, rx;
};

struct fw_addr {
	uint32_t hi;
	uint32_t lo;
};

struct fw_asybindreq {
	struct fw_addr start;
	unsigned long len;
};

struct fw_reg_req_t {
	uint32_t addr;
	uint32_t data;
};

#define MAXREC(x)	(2 << (x))
#define FWPMAX_S400 (2048 + 20)	/* MAXREC plus space for control data */
#define FWMAXQUEUE 128

#define	FWLOCALBUS	0xffc0

#define FWTCODE_WREQQ	0
#define FWTCODE_WREQB	1
#define FWTCODE_WRES	2
#define FWTCODE_RREQQ	4
#define FWTCODE_RREQB	5
#define FWTCODE_RRESQ	6
#define FWTCODE_RRESB	7
#define FWTCODE_CYCS	8
#define FWTCODE_LREQ	9
#define FWTCODE_STREAM	0xa
#define FWTCODE_LRES	0xb
#define FWTCODE_PHY	0xe

#define	FWRETRY_1	0
#define	FWRETRY_X	1
#define	FWRETRY_A	2
#define	FWRETRY_B	3

#define FWRCODE_COMPLETE	0
#define FWRCODE_ER_CONFL	4
#define FWRCODE_ER_DATA		5
#define FWRCODE_ER_TYPE		6
#define FWRCODE_ER_ADDR		7

/*
 * Defined 1394a-2000
 * Table 5B-1
 */
#define FWSPD_S100	0
#define FWSPD_S200	1
#define FWSPD_S400	2
#define FWSPD_S800	3
#define FWSPD_S1600	4
#define FWSPD_S3200	5

#define	FWP_TL_VALID (1 << 7)

struct fw_isohdr {
	uint32_t hdr[1];
};

struct fw_asyhdr {
	uint32_t hdr[4];
};

#if BYTE_ORDER == BIG_ENDIAN
#define BIT4x2(x,y)	 uint8_t  x:4, y:4
#define BIT16x2(x,y)	uint32_t x:16, y:16
#else
#define BIT4x2(x,y)	 uint8_t  y:4, x:4
#define BIT16x2(x,y)	uint32_t y:16, x:16
#endif

#if BYTE_ORDER == BIG_ENDIAN
#define COMMON_HDR(a,b,c,d)	uint32_t a:16,b:8,c:4,d:4
#define COMMON_RES(a,b,c,d)	uint32_t a:16,b:4,c:4,d:8
#else
#define COMMON_HDR(a,b,c,d)	uint32_t d:4,c:4,b:8,a:16
#define COMMON_RES(a,b,c,d)	uint32_t d:8,c:4,b:4,a:16
#endif

struct fw_pkt {
	union {
		uint32_t ld[0];
		struct {
			COMMON_HDR(, , tcode, );
		} common;
		struct {
			COMMON_HDR(len, chtag, tcode, sy);
			uint32_t payload[0];
		} stream;
		struct {
			COMMON_HDR(dst, tlrt, tcode, pri);
			BIT16x2(src, );
		} hdr;
		struct {
			COMMON_HDR(dst, tlrt, tcode, pri);
			BIT16x2(src, dest_hi);
			uint32_t dest_lo;
		} rreqq;
		struct {
			COMMON_HDR(dst, tlrt, tcode, pri);
			COMMON_RES(src, rtcode, , );
			uint32_t :32;
		} wres;
		struct {
			COMMON_HDR(dst, tlrt, tcode, pri);
			BIT16x2(src, dest_hi);
			uint32_t dest_lo;
			BIT16x2(len, extcode);
		} rreqb;
		struct {
			COMMON_HDR(dst, tlrt, tcode, pri);
			BIT16x2(src, dest_hi);
			uint32_t dest_lo;
			uint32_t data;
		} wreqq;
		struct {
			COMMON_HDR(dst, tlrt, tcode, pri);
			BIT16x2(src, dest_hi);
			uint32_t dest_lo;
			uint32_t data;
		} cyc;
		struct {
			COMMON_HDR(dst, tlrt, tcode, pri);
			COMMON_RES(src, rtcode, , );
			uint32_t :32;
			uint32_t data;
		} rresq;
		struct {
			COMMON_HDR(dst, tlrt, tcode, pri);
			BIT16x2(src, dest_hi);
			uint32_t dest_lo;
			BIT16x2(len, extcode);
			uint32_t payload[0];
		} wreqb;
		struct {
			COMMON_HDR(dst, tlrt, tcode, pri);
			BIT16x2(src, dest_hi);
			uint32_t dest_lo;
			BIT16x2(len, extcode);
			uint32_t payload[0];
		} lreq;
		struct {
			COMMON_HDR(dst, tlrt, tcode, pri);
			COMMON_RES(src, rtcode, , );
			uint32_t :32;
			BIT16x2(len, extcode);
			uint32_t payload[0];
		} rresb;
		struct {
			COMMON_HDR(dst, tlrt, tcode, pri);
			COMMON_RES(src, rtcode, , );
			uint32_t :32;
			BIT16x2(len, extcode);
			uint32_t payload[0];
		} lres;
	} mode;
};

/*
 * Response code (rtcode)
 */
/* The node has successfully completed the command. */
#define	RESP_CMP		0
/* A resource conflict was detected. The request may be retried. */
#define	RESP_CONFLICT_ERROR	4
/* Hardware error, data is unavailable. */
#define	RESP_DATA_ERROR		5
/* A field in the request packet header was set to an unsupported or incorrect
 * value, or an invalid transaction was attempted (e.g., a write to a read-only
 * address). */
#define	RESP_TYPE_ERROR		6
/* The destination offset field in the request was set to an address not
 * accessible in the destination node. */
#define	RESP_ADDRESS_ERROR	7

/*
 * Extended transaction code (extcode)
 */
#define EXTCODE_MASK_SWAP	1
#define EXTCODE_CMP_SWAP	2
#define EXTCODE_FETCH_ADD	3
#define EXTCODE_LITTLE_ADD	4
#define EXTCODE_BOUNDED_ADD	5
#define EXTCODE_WRAP_ADD	6

struct fw_eui64 {
	uint32_t hi, lo;
};
#define FW_EUI64_BYTE(eui, x) \
	((((x)<4)?				\
		((eui)->hi >> (8*(3-(x)))): 	\
		((eui)->lo >> (8*(7-(x))))	\
	) & 0xff)
#define FW_EUI64_EQUAL(x, y) \
	((x).hi == (y).hi && (x).lo == (y).lo)

struct fw_asyreq {
	struct fw_asyreq_t{
		unsigned char sped;
		unsigned int type;
#define FWASREQNODE	0
#define FWASREQEUI	1
#define FWASRESTL	2
#define FWASREQSTREAM	3
		unsigned short len;
		union {
			struct fw_eui64 eui;
		}dst;
	}req;
	struct fw_pkt pkt;
	uint32_t data[512];
};

struct fw_devinfo {
	struct fw_eui64 eui;
	uint16_t dst;
	uint16_t status;
};

#define FW_MAX_DEVLST 70
struct fw_devlstreq {
	uint16_t n;
	uint16_t info_len;
	struct fw_devinfo dev[FW_MAX_DEVLST];
};

/*
 * Defined in IEEE 1394a-2000
 * 4.3.4.1
 */
#define FW_SELF_ID_PORT_CONNECTED_TO_CHILD 3
#define FW_SELF_ID_PORT_CONNECTED_TO_PARENT 2
#define FW_SELF_ID_PORT_NOT_CONNECTED 1
#define FW_SELF_ID_PORT_NOT_EXISTS 0

#define FW_SELF_ID_PAGE0 0
#define FW_SELF_ID_PAGE1 1

#if BYTE_ORDER == BIG_ENDIAN
union fw_self_id {
	struct {
		uint32_t  id:2,
			  phy_id:6,
			  sequel:1,
			  link_active:1,
			  gap_count:6,
			  phy_speed:2,
			  reserved:2,
			  contender:1,
			  power_class:3,
			  port0:2,
			  port1:2,
			  port2:2,
			  initiated_reset:1,
			  more_packets:1;
	} p0;
	struct {
		uint32_t
			  id:2,
			  phy_id:6,
			  sequel:1,
			  sequence_num:3,
			  reserved2:2,
			  port3:2,
			  port4:2,
			  port5:2,
			  port6:2,
			  port7:2,
			  port8:2,
			  port9:2,
			  port10:2,
			  reserved1:1,
			  more_packets:1;
	} p1;
	struct {
		uint32_t
			  id:2,
			  phy_id:6,
			  sequel:1,
			  sequence_num:3,
			  :2,
			  port11:2,
			  port12:2,
			  port13:2,
			  port14:2,
			  port15:2,
			  :8;
	} p2;
};
#else
union fw_self_id {
	struct {
		uint32_t  more_packets:1,
			  initiated_reset:1,
			  port2:2,
			  port1:2,
			  port0:2,
			  power_class:3,
			  contender:1,
			  reserved:2,
			  phy_speed:2,
			  gap_count:6,
			  link_active:1,
			  sequel:1,
			  phy_id:6,
			  id:2;
	} p0;
	struct {
		uint32_t  more_packets:1,
			  reserved1:1,
			  port10:2,
			  port9:2,
			  port8:2,
			  port7:2,
			  port6:2,
			  port5:2,
			  port4:2,
			  port3:2,
			  reserved2:2,
			  sequence_num:3,
			  sequel:1,
			  phy_id:6,
			  id:2;
	} p1;
	struct {
		uint32_t
			  reserved3:8,
			  port15:2,
			  port14:2,
			  port13:2,
			  port12:2,
			  port11:2,
			  reserved4:2,
			  sequence_num:3,
			  sequel:1,
			  phy_id:6,
			  id:2;
	} p2;
};
#endif

struct fw_topology_map {
	uint32_t crc:16,
		 crc_len:16;
	uint32_t generation;
	uint32_t self_id_count:16,
		 node_count:16;
	union fw_self_id self_id[4*64];
};

struct fw_speed_map {
	uint32_t crc:16,
		 crc_len:16;
	uint32_t generation;
	uint8_t  speed[64][64];
};

struct fw_crom_buf {
	struct fw_eui64 eui;
	uint32_t len;
	void *ptr;
};

/*
 * FireWire specific system requests.
 */
#define	FW_SSTBUF	_IOWR('S', 86, struct fw_isobufreq)
#define	FW_GSTBUF	_IOWR('S', 87, struct fw_isobufreq)
#define	FW_SRSTREAM	_IOWR('S', 88, struct fw_isochreq)
#define	FW_GRSTREAM	_IOWR('S', 89, struct fw_isochreq)
#define	FW_STSTREAM	_IOWR('S', 90, struct fw_isochreq)
#define	FW_GTSTREAM	_IOWR('S', 91, struct fw_isochreq)

#define	FW_ASYREQ	_IOWR('S', 92, struct fw_asyreq)
#define FW_IBUSRST	_IOR('S', 1, unsigned int)
#define FW_GDEVLST	_IOWR('S', 2, struct fw_devlstreq)
#define	FW_SBINDADDR	_IOWR('S', 3, struct fw_asybindreq)
#define	FW_CBINDADDR	_IOWR('S', 4, struct fw_asybindreq)
#define	FW_GTPMAP	_IOR('S', 5, struct fw_topology_map)
#define	FW_GCROM	_IOWR('S', 7, struct fw_crom_buf)

#define	FW_SDEUI64	_IOW('S', 20, struct fw_eui64)
#define	FW_GDEUI64	_IOR('S', 21, struct fw_eui64)

#define FWOHCI_RDREG	_IOWR('S', 80, struct fw_reg_req_t)
#define FWOHCI_WRREG	_IOWR('S', 81, struct fw_reg_req_t)
#define FWOHCI_RDPHYREG	_IOWR('S', 82, struct fw_reg_req_t)
#define FWOHCI_WRPHYREG	_IOWR('S', 83, struct fw_reg_req_t)

#define DUMPDMA		_IOWR('S', 82, uint32_t)

#ifdef _KERNEL

#define FWMAXNDMA 0x100 /* 8 bits DMA channel id. in device No. */

#if defined(__DragonFly__) || __FreeBSD_version < 500000
#define dev2unit(x)	((minor(x) & 0xff) | (minor(x) >> 8))
#define unit2minor(x)	(((x) & 0xff) | (((x) << 8) & ~0xffff))
#endif

#define MAKEMINOR(f, u, s)	\
	((f) | (((u) & 0xff) << 8) | (s & 0xff))
#define DEV2UNIT(x)	((dev2unit(x) & 0xff00) >> 8)
#define DEV2SUB(x)	(dev2unit(x) & 0xff)

#define FWMEM_FLAG	0x10000
#define DEV_FWMEM(x)	(dev2unit(x) & FWMEM_FLAG)
#endif
#endif

repo_name: veiledmerc/mira

license: mit


code:
/*-
 * Copyright (c) 1998-2002 Katsushi Kobayashi and Hidetoshi Shimokawa
 * 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 acknowledgement as bellow:
 *
 *    This product includes software developed by K. Kobayashi and H. Shimokawa
 *
 * 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.
 *
 * $FreeBSD: release/9.0.0/sys/dev/firewire/firewire_phy.h 139749 2005-01-06 01:43:34Z imp $
 *
 */

#define	FW_PHY_PHYSID_REG		0x00
#define	FW_PHY_PHYSID			(63<<2)
#define	FW_PHY_ROOT_REG			0x00
#define	FW_PHY_ROOT			(1<<1)
#define	FW_PHY_CPS_REG			0x00
#define	FW_PHY_CPS			(1<<0)

#define	FW_PHY_RHB_REG			0x01
#define	FW_PHY_RHB			(1<<7)
#define	FW_PHY_IBR_REG			0x01
#define	FW_PHY_IBR			(1<<6)
#define	FW_PHY_ISBR_REG			0x05
#define	FW_PHY_ISBR			(1<<6)
#define	FW_PHY_GC_REG			0x01

#define	FW_PHY_SPD_REG			0x02
#define	FW_PHY_SPD			(3<<6)
#define	FW_PHY_REV_REG			0x02
#define	FW_PHY_REV			(3<<4)
#define	FW_PHY_NP_REG			0x02
#define	FW_PHY_NP			(15<<0)

#define	FW_PHY_P1_REG			0x03
#define	FW_PHY_P2_REG			0x04
#define	FW_PHY_P3_REG			0x05

#define	FW_PHY_P_ASTAT			(3<<6)
#define	FW_PHY_P_BSTAT			(3<<4)
#define	FW_PHY_P_CH			(1<<3)
#define	FW_PHY_P_CON			(1<<2)

#define FW_PHY_LOOPINT_REG		0x06
#define FW_PHY_LOOPINT			(1<<7)
#define FW_PHY_CPSINT_REG		0x06
#define FW_PHY_CPSNT			(1<<6)
/*
#define FW_PHY_CPS_REG			0x06
#define FW_PHY_CPS			(1<<5)
*/
#define FW_PHY_IR_REG			0x06
#define FW_PHY_IR			(1<<4)
#define FW_PHY_C_REG			0x06
#define FW_PHY_C			(1<<0)

#define FW_PHY_ESPD_REG			0x03
#define	FW_PHY_ESPD			(7<<5)

#define FW_PHY_EDEL_REG			0x03
#define FW_PHY_EDEL			15<<0


code:
/*-
 * Copyright (c) 2003 Hidetoshi Shimokawa
 * Copyright (c) 1998-2002 Katsushi Kobayashi and Hidetoshi Shimokawa
 * 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 acknowledgement as bellow:
 *
 *    This product includes software developed by K. Kobayashi and H. Shimokawa
 *
 * 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.
 *
 * $FreeBSD: release/9.0.0/sys/dev/firewire/firewirereg.h 171513 2007-07-20 03:42:57Z simokawa $
 *
 */

#ifdef __DragonFly__
typedef	d_thread_t fw_proc;
#include <sys/select.h>
#elif __FreeBSD_version >= 500000
typedef	struct thread fw_proc;
#include <sys/selinfo.h>
#else
typedef	struct proc fw_proc;
#include <sys/select.h>
#endif

#include <sys/uio.h>
#include <sys/mutex.h>
#include <sys/taskqueue.h>

#define	splfw splimp

STAILQ_HEAD(fw_xferlist, fw_xfer);

struct fw_device{
	uint16_t dst;
	struct fw_eui64 eui;
	uint8_t speed;
	uint8_t maxrec;
	uint8_t nport;
	uint8_t power;
#define CSRROMOFF 0x400
#define CSRROMSIZE 0x400
	int rommax;	/* offset from 0xffff f000 0000 */
	uint32_t csrrom[CSRROMSIZE/4];
	int rcnt;
	struct firewire_comm *fc;
	uint32_t status;
#define FWDEVINIT	1
#define FWDEVATTACHED	2
#define FWDEVINVAL	3
	STAILQ_ENTRY(fw_device) link;
};

struct firewire_softc {
#if defined(__FreeBSD__) && __FreeBSD_version >= 500000
	struct cdev *dev;
#endif
	struct firewire_comm *fc;
};

#define FW_MAX_DMACH 0x20
#define FW_MAX_DEVCH FW_MAX_DMACH
#define FW_XFERTIMEOUT 1

struct firewire_dev_comm {
	device_t dev;
	struct firewire_comm *fc;
	void (*post_busreset) (void *);
	void (*post_explore) (void *);
};

struct tcode_info {
	u_char hdr_len;	/* IEEE1394 header length */
	u_char flag;
#define FWTI_REQ	(1 << 0)
#define FWTI_RES	(1 << 1)
#define FWTI_TLABEL	(1 << 2)
#define FWTI_BLOCK_STR	(1 << 3)
#define FWTI_BLOCK_ASY	(1 << 4)
	u_char valid_res;
};

struct firewire_comm{
	device_t dev;
	device_t bdev;
	uint16_t busid:10,
		  nodeid:6;
	u_int mode;
	u_int nport;
	u_int speed;
	u_int maxrec;
	u_int irm;
	u_int max_node;
	u_int max_hop;
#define FWPHYASYST (1 << 0)
	uint32_t status;
#define	FWBUSDETACH	(-2)
#define	FWBUSNOTREADY	(-1)
#define	FWBUSRESET	0
#define	FWBUSINIT	1
#define	FWBUSCYMELECT	2
#define	FWBUSMGRELECT	3
#define	FWBUSMGRDONE	4
#define	FWBUSEXPLORE	5
#define	FWBUSPHYCONF	6
#define	FWBUSEXPDONE	7
#define	FWBUSCOMPLETION	10
	int nisodma;
	struct fw_eui64 eui;
	struct fw_xferq
		*arq, *atq, *ars, *ats, *it[FW_MAX_DMACH],*ir[FW_MAX_DMACH];
	struct fw_xferlist tlabels[0x40];
	u_char last_tlabel[0x40];
	struct mtx tlabel_lock;
	STAILQ_HEAD(, fw_bind) binds;
	STAILQ_HEAD(, fw_device) devices;
	u_int  sid_cnt;
#define CSRSIZE 0x4000
	uint32_t csr_arc[CSRSIZE/4];
#define CROMSIZE 0x400
	uint32_t *config_rom;
	struct crom_src_buf *crom_src_buf;
	struct crom_src *crom_src;
	struct crom_chunk *crom_root;
	struct fw_topology_map *topology_map;
	struct fw_speed_map *speed_map;
	struct callout busprobe_callout;
	struct callout bmr_callout;
	struct callout timeout_callout;
	struct task task_timeout;
	uint32_t (*cyctimer) (struct  firewire_comm *);
	void (*ibr) (struct firewire_comm *);
	uint32_t (*set_bmr) (struct firewire_comm *, uint32_t);
	int (*ioctl) (struct cdev *, u_long, caddr_t, int, fw_proc *);
	int (*irx_enable) (struct firewire_comm *, int);
	int (*irx_disable) (struct firewire_comm *, int);
	int (*itx_enable) (struct firewire_comm *, int);
	int (*itx_disable) (struct firewire_comm *, int);
	void (*timeout) (void *);
	void (*poll) (struct firewire_comm *, int, int);
	void (*set_intr) (struct firewire_comm *, int);
	void (*irx_post) (struct firewire_comm *, uint32_t *);
	void (*itx_post) (struct firewire_comm *, uint32_t *);
	struct tcode_info *tcode;
	bus_dma_tag_t dmat;
	struct mtx mtx;
	struct mtx wait_lock;
	struct taskqueue *taskqueue;
	struct proc *probe_thread;
};
#define CSRARC(sc, offset) ((sc)->csr_arc[(offset)/4])

#define FW_GMTX(fc)		(&(fc)->mtx)
#define FW_GLOCK(fc)		mtx_lock(FW_GMTX(fc))
#define FW_GUNLOCK(fc)		mtx_unlock(FW_GMTX(fc))
#define FW_GLOCK_ASSERT(fc)	mtx_assert(FW_GMTX(fc), MA_OWNED)

struct fw_xferq {
	int flag;
#define FWXFERQ_CHTAGMASK 0xff
#define FWXFERQ_RUNNING (1 << 8)
#define FWXFERQ_STREAM (1 << 9)

#define FWXFERQ_BULK (1 << 11)
#define FWXFERQ_MODEMASK (7 << 10)

#define FWXFERQ_EXTBUF (1 << 13)
#define FWXFERQ_OPEN (1 << 14)

#define FWXFERQ_HANDLER (1 << 16)
#define FWXFERQ_WAKEUP (1 << 17)
	void (*start) (struct firewire_comm*);
	int dmach;
	struct fw_xferlist q;
	u_int queued;
	u_int maxq;
	u_int psize;
	struct fwdma_alloc_multi *buf;
	u_int bnchunk;
	u_int bnpacket;
	struct fw_bulkxfer *bulkxfer;
	STAILQ_HEAD(, fw_bulkxfer) stvalid;
	STAILQ_HEAD(, fw_bulkxfer) stfree;
	STAILQ_HEAD(, fw_bulkxfer) stdma;
	struct fw_bulkxfer *stproc;
	struct selinfo rsel;
	caddr_t sc;
	void (*hand) (struct fw_xferq *);
};

struct fw_bulkxfer{
	int poffset;
	struct mbuf *mbuf;
	STAILQ_ENTRY(fw_bulkxfer) link;
	caddr_t start;
	caddr_t end;
	int resp;
};

struct fw_bind{
	u_int64_t start;
	u_int64_t end;
	struct fw_xferlist xferlist;
	STAILQ_ENTRY(fw_bind) fclist;
	STAILQ_ENTRY(fw_bind) chlist;
	void *sc;
};

struct fw_xfer{
	caddr_t sc;
	struct firewire_comm *fc;
	struct fw_xferq *q;
	struct timeval tv;
	int8_t resp;
#define FWXF_INIT	0x00
#define FWXF_INQ	0x01
#define FWXF_START	0x02
#define FWXF_SENT	0x04
#define FWXF_SENTERR	0x08
#define FWXF_BUSY	0x10
#define FWXF_RCVD	0x20

#define FWXF_WAKE	0x80
	uint8_t flag;
	int8_t tl;
	void (*hand) (struct fw_xfer *);
	struct {
		struct fw_pkt hdr;
		uint32_t *payload;
		uint16_t pay_len;
		uint8_t spd;
	} send, recv;
	struct mbuf *mbuf;
	STAILQ_ENTRY(fw_xfer) link;
	STAILQ_ENTRY(fw_xfer) tlabel;
	struct malloc_type *malloc;
};

struct fw_rcv_buf {
	struct firewire_comm *fc;
	struct fw_xfer *xfer;
	struct iovec *vec;
	u_int nvec;
	uint8_t spd;
};

void fw_sidrcv (struct firewire_comm *, uint32_t *, u_int);
void fw_rcv (struct fw_rcv_buf *);
void fw_xfer_unload ( struct fw_xfer*);
void fw_xfer_free_buf ( struct fw_xfer*);
void fw_xfer_free ( struct fw_xfer*);
struct fw_xfer *fw_xfer_alloc (struct malloc_type *);
struct fw_xfer *fw_xfer_alloc_buf (struct malloc_type *, int, int);
void fw_init (struct firewire_comm *);
int fw_tbuf_update (struct firewire_comm *, int, int);
int fw_rbuf_update (struct firewire_comm *, int, int);
int fw_bindadd (struct firewire_comm *, struct fw_bind *);
int fw_bindremove (struct firewire_comm *, struct fw_bind *);
int fw_xferlist_add (struct fw_xferlist *, struct malloc_type *, int, int, int,
    struct firewire_comm *, void *, void (*)(struct fw_xfer *));
void fw_xferlist_remove (struct fw_xferlist *);
int fw_asyreq (struct firewire_comm *, int, struct fw_xfer*);
void fw_busreset (struct firewire_comm *, uint32_t);
uint16_t fw_crc16 (uint32_t *, uint32_t);
void fw_xfer_timeout (void *);
void fw_xfer_done (struct fw_xfer *);
void fw_xferwake (struct fw_xfer *);
int fw_xferwait (struct fw_xfer *);
void fw_asy_callback_free (struct fw_xfer *);
struct fw_device *fw_noderesolve_nodeid (struct firewire_comm *, int);
struct fw_device *fw_noderesolve_eui64 (struct firewire_comm *, struct fw_eui64 *);
struct fw_bind *fw_bindlookup (struct firewire_comm *, uint16_t, uint32_t);
void fw_drain_txq (struct firewire_comm *);
int fwdev_makedev (struct firewire_softc *);
int fwdev_destroydev (struct firewire_softc *);
void fwdev_clone (void *, struct ucred *, char *, int, struct cdev **);
int fw_open_isodma(struct firewire_comm *, int);

extern int firewire_debug;
extern devclass_t firewire_devclass;
extern int firewire_phydma_enable;

#ifdef __DragonFly__
#define		FWPRI		PCATCH
#else
#define		FWPRI		((PZERO+8)|PCATCH)
#endif

#if defined(__DragonFly__) || __FreeBSD_version < 500000
#define CALLOUT_INIT(x) callout_init(x)
#else
#define CALLOUT_INIT(x) callout_init(x, 1 /* mpsafe */)
#endif

#if defined(__DragonFly__) || __FreeBSD_version < 500000
/* compatibility shim for 4.X */
#define bio buf
#define bio_bcount b_bcount
#define bio_cmd b_flags
#define bio_count b_count
#define bio_data b_data
#define bio_dev b_dev
#define bio_error b_error
#define bio_flags b_flags
#define bio_offset b_offset
#define bio_resid b_resid
#define BIO_ERROR B_ERROR
#define BIO_READ B_READ
#define BIO_WRITE B_WRITE
#define MIN(a,b) (((a)<(b))?(a):(b))
#define MAX(a,b) (((a)>(b))?(a):(b))
#endif

MALLOC_DECLARE(M_FW);
MALLOC_DECLARE(M_FWXFER);


code:
/*-
 * Copyright (C) 2003
 * 	Hidetoshi Shimokawa. 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 Hidetoshi Shimokawa.
 *
 * 4. Neither the name of the author 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.
 *
 * $FreeBSD: release/9.0.0/sys/dev/firewire/fwdma.h 139749 2005-01-06 01:43:34Z imp $
 */

struct fwdma_alloc {
	bus_dma_tag_t	dma_tag;
	bus_dmamap_t	dma_map;
	void *		v_addr;
	bus_addr_t	bus_addr;
};

struct fwdma_seg {
	bus_dmamap_t	dma_map;
	void *		v_addr;
	bus_addr_t	bus_addr;
};

struct fwdma_alloc_multi {
	bus_size_t	ssize;
	bus_size_t	esize;
	int		nseg;
	bus_dma_tag_t	dma_tag;
	struct fwdma_seg seg[0];
};

static __inline void *
fwdma_v_addr(struct fwdma_alloc_multi *am, int index)
{
	bus_size_t ssize = am->ssize;
	int offset = am->esize * index;

	return ((caddr_t)am->seg[offset / ssize].v_addr + (offset % ssize));
}

static __inline bus_addr_t
fwdma_bus_addr(struct fwdma_alloc_multi *am, int index)
{
	bus_size_t ssize = am->ssize;
	int offset = am->esize * index;

	return (am->seg[offset / ssize].bus_addr + (offset % ssize));
}

static __inline void
fwdma_sync(struct fwdma_alloc *dma, bus_dmasync_op_t op)
{
	bus_dmamap_sync(dma->dma_tag, dma->dma_map, op);
}

static __inline void
fwdma_sync_multiseg(struct fwdma_alloc_multi *am,
			int start, int end, bus_dmasync_op_t op)
{
	struct fwdma_seg *seg, *eseg;

	seg = &am->seg[am->esize * start / am->ssize];
	eseg = &am->seg[am->esize * end / am->ssize];
	for (; seg <= eseg; seg ++)
		bus_dmamap_sync(am->dma_tag, seg->dma_map, op);
}

static __inline void
fwdma_sync_multiseg_all(struct fwdma_alloc_multi *am, bus_dmasync_op_t op)
{
	struct fwdma_seg *seg;
	int i;

	seg = &am->seg[0];
	for (i = 0; i < am->nseg; i++, seg++)
		bus_dmamap_sync(am->dma_tag, seg->dma_map, op);
}

void *fwdma_malloc(struct firewire_comm *, int, bus_size_t, struct fwdma_alloc *, int);
void fwdma_free(struct firewire_comm *, struct fwdma_alloc *);
void *fwdma_malloc_size(bus_dma_tag_t, bus_dmamap_t *, bus_size_t, bus_addr_t *, int);
void fwdma_free_size(bus_dma_tag_t, bus_dmamap_t, void *, bus_size_t);
struct fwdma_alloc_multi *fwdma_malloc_multiseg(struct firewire_comm *,
	int, int, int, int);
void fwdma_free_multiseg(struct fwdma_alloc_multi *);


code:
/*-
 * Copyright (C) 2002-2003
 * 	Hidetoshi Shimokawa. 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 Hidetoshi Shimokawa.
 *
 * 4. Neither the name of the author 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.
 *
 * $FreeBSD: release/9.0.0/sys/dev/firewire/fwmem.h 139749 2005-01-06 01:43:34Z imp $
 */

struct fw_xfer *fwmem_read_quad(struct fw_device *, caddr_t, uint8_t,
	uint16_t, uint32_t, void *, void (*)(struct fw_xfer *));
struct fw_xfer *fwmem_write_quad(struct fw_device *, caddr_t, uint8_t,
	uint16_t, uint32_t, void *, void (*)(struct fw_xfer *));
struct fw_xfer *fwmem_read_block(struct fw_device *, caddr_t, uint8_t,
	uint16_t, uint32_t, int, void *, void (*)(struct fw_xfer *));
struct fw_xfer *fwmem_write_block(struct fw_device *, caddr_t, uint8_t,
	uint16_t, uint32_t, int, void *, void (*)(struct fw_xfer *));

d_open_t	fwmem_open;
d_close_t	fwmem_close;
d_ioctl_t	fwmem_ioctl;
d_read_t	fwmem_read;
d_write_t	fwmem_write;
d_poll_t	fwmem_poll;
d_mmap_t	fwmem_mmap;
d_strategy_t	fwmem_strategy;


code:
/*-
 * Copyright (c) 2003 Hidetoshi Shimokawa
 * Copyright (c) 1998-2002 Katsushi Kobayashi and Hidetoshi Shimokawa
 * 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 acknowledgement as bellow:
 *
 *    This product includes software developed by K. Kobayashi and H. Shimokawa
 *
 * 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.
 *
 * $FreeBSD: release/9.0.0/sys/dev/firewire/fwohcireg.h 188508 2009-02-12 03:05:42Z sbruno $
 *
 */
#define		PCI_CBMEM		PCIR_BAR(0)

#define		FW_VENDORID_NATSEMI	0x100B
#define		FW_VENDORID_NEC		0x1033
#define		FW_VENDORID_SIS		0x1039
#define		FW_VENDORID_TI		0x104c
#define		FW_VENDORID_SONY	0x104d
#define		FW_VENDORID_VIA		0x1106
#define		FW_VENDORID_RICOH	0x1180
#define		FW_VENDORID_APPLE	0x106b
#define		FW_VENDORID_LUCENT	0x11c1
#define		FW_VENDORID_INTEL	0x8086
#define		FW_VENDORID_ADAPTEC	0x9004
#define		FW_VENDORID_SUN		0x108e

#define		FW_DEVICE_CS4210	(0x000f << 16)
#define		FW_DEVICE_UPD861	(0x0063 << 16)
#define		FW_DEVICE_UPD871	(0x00ce << 16)
#define		FW_DEVICE_UPD72870	(0x00cd << 16)
#define		FW_DEVICE_UPD72873	(0x00e7 << 16)
#define		FW_DEVICE_UPD72874	(0x00f2 << 16)
#define		FW_DEVICE_TITSB22	(0x8009 << 16)
#define		FW_DEVICE_TITSB23	(0x8019 << 16)
#define		FW_DEVICE_TITSB26	(0x8020 << 16)
#define		FW_DEVICE_TITSB43	(0x8021 << 16)
#define		FW_DEVICE_TITSB43A	(0x8023 << 16)
#define		FW_DEVICE_TITSB43AB23	(0x8024 << 16)
#define		FW_DEVICE_TITSB82AA2	(0x8025 << 16)
#define		FW_DEVICE_TITSB43AB21	(0x8026 << 16)
#define		FW_DEVICE_TIPCI4410A	(0x8017 << 16)
#define		FW_DEVICE_TIPCI4450	(0x8011 << 16)
#define		FW_DEVICE_TIPCI4451	(0x8027 << 16)
#define		FW_DEVICE_CXD1947	(0x8009 << 16)
#define		FW_DEVICE_CXD3222	(0x8039 << 16)
#define		FW_DEVICE_VT6306	(0x3044 << 16)
#define		FW_DEVICE_R5C551	(0x0551 << 16)
#define		FW_DEVICE_R5C552	(0x0552 << 16)
#define		FW_DEVICE_PANGEA	(0x0030 << 16)
#define		FW_DEVICE_UNINORTH	(0x0031 << 16)
#define		FW_DEVICE_AIC5800	(0x5800 << 16)
#define		FW_DEVICE_FW322		(0x5811 << 16)
#define		FW_DEVICE_7007		(0x7007 << 16)
#define		FW_DEVICE_82372FB	(0x7605 << 16)
#define		FW_DEVICE_PCIO2FW	(0x1102 << 16)

#define PCI_INTERFACE_OHCI	0x10

#define FW_OHCI_BASE_REG	0x10

#define		OHCI_DMA_ITCH		0x20
#define		OHCI_DMA_IRCH		0x20

#define		OHCI_MAX_DMA_CH		(0x4 + OHCI_DMA_ITCH + OHCI_DMA_IRCH)

typedef uint32_t 	fwohcireg_t;

/* for PCI */
#if BYTE_ORDER == BIG_ENDIAN
#define FWOHCI_DMA_WRITE(x, y)	((x) = htole32(y))
#define FWOHCI_DMA_READ(x)	le32toh(x)
#define FWOHCI_DMA_SET(x, y)	((x) |= htole32(y))
#define FWOHCI_DMA_CLEAR(x, y)	((x) &= htole32(~(y)))
#else
#define FWOHCI_DMA_WRITE(x, y)	((x) = (y))
#define FWOHCI_DMA_READ(x)	(x)
#define FWOHCI_DMA_SET(x, y)	((x) |= (y))
#define FWOHCI_DMA_CLEAR(x, y)	((x) &= ~(y))
#endif

struct fwohcidb {
	union {
		struct {
			uint32_t cmd;
			uint32_t addr;
			uint32_t depend;
			uint32_t res;
		} desc;
		uint32_t immed[4];
	} db;
#define OHCI_STATUS_SHIFT	16
#define OHCI_COUNT_MASK		0xffff
#define OHCI_OUTPUT_MORE	(0 << 28)
#define OHCI_OUTPUT_LAST	(1 << 28)
#define OHCI_INPUT_MORE		(2 << 28)
#define OHCI_INPUT_LAST		(3 << 28)
#define OHCI_STORE_QUAD		(4 << 28)
#define OHCI_LOAD_QUAD		(5 << 28)
#define OHCI_NOP		(6 << 28)
#define OHCI_STOP		(7 << 28)
#define OHCI_STORE		(8 << 28)
#define OHCI_CMD_MASK		(0xf << 28)

#define	OHCI_UPDATE		(1 << 27)

#define OHCI_KEY_ST0		(0 << 24)
#define OHCI_KEY_ST1		(1 << 24)
#define OHCI_KEY_ST2		(2 << 24)
#define OHCI_KEY_ST3		(3 << 24)
#define OHCI_KEY_REGS		(5 << 24)
#define OHCI_KEY_SYS		(6 << 24)
#define OHCI_KEY_DEVICE		(7 << 24)
#define OHCI_KEY_MASK		(7 << 24)

#define OHCI_INTERRUPT_NEVER	(0 << 20)
#define OHCI_INTERRUPT_TRUE	(1 << 20)
#define OHCI_INTERRUPT_FALSE	(2 << 20)
#define OHCI_INTERRUPT_ALWAYS	(3 << 20)

#define OHCI_BRANCH_NEVER	(0 << 18)
#define OHCI_BRANCH_TRUE	(1 << 18)
#define OHCI_BRANCH_FALSE	(2 << 18)
#define OHCI_BRANCH_ALWAYS	(3 << 18)
#define OHCI_BRANCH_MASK	(3 << 18)

#define OHCI_WAIT_NEVER		(0 << 16)
#define OHCI_WAIT_TRUE		(1 << 16)
#define OHCI_WAIT_FALSE		(2 << 16)
#define OHCI_WAIT_ALWAYS	(3 << 16)
};

#define OHCI_SPD_S100 0x4
#define OHCI_SPD_S200 0x1
#define OHCI_SPD_S400 0x2

#define FWOHCIEV_NOSTAT 0
#define FWOHCIEV_LONGP 2
#define FWOHCIEV_MISSACK 3
#define FWOHCIEV_UNDRRUN 4
#define FWOHCIEV_OVRRUN 5
#define FWOHCIEV_DESCERR 6
#define FWOHCIEV_DTRDERR 7
#define FWOHCIEV_DTWRERR 8
#define FWOHCIEV_BUSRST 9
#define FWOHCIEV_TIMEOUT 0xa
#define FWOHCIEV_TCODERR 0xb
#define FWOHCIEV_UNKNOWN 0xe
#define FWOHCIEV_FLUSHED 0xf
#define FWOHCIEV_ACKCOMPL 0x11
#define FWOHCIEV_ACKPEND 0x12
#define FWOHCIEV_ACKBSX 0x14
#define FWOHCIEV_ACKBSA 0x15
#define FWOHCIEV_ACKBSB 0x16
#define FWOHCIEV_ACKTARD 0x1b
#define FWOHCIEV_ACKDERR 0x1d
#define FWOHCIEV_ACKTERR 0x1e

#define FWOHCIEV_MASK 0x1f

struct ohci_dma{
	fwohcireg_t	cntl;

#define	OHCI_CNTL_CYCMATCH_S	(0x1 << 31)

#define	OHCI_CNTL_BUFFIL	(0x1 << 31)
#define	OHCI_CNTL_ISOHDR	(0x1 << 30)
#define	OHCI_CNTL_CYCMATCH_R	(0x1 << 29)
#define	OHCI_CNTL_MULTICH	(0x1 << 28)

#define	OHCI_CNTL_DMA_RUN	(0x1 << 15)
#define	OHCI_CNTL_DMA_WAKE	(0x1 << 12)
#define	OHCI_CNTL_DMA_DEAD	(0x1 << 11)
#define	OHCI_CNTL_DMA_ACTIVE	(0x1 << 10)
#define	OHCI_CNTL_DMA_BT	(0x1 << 8)
#define	OHCI_CNTL_DMA_BAD	(0x1 << 7)
#define	OHCI_CNTL_DMA_STAT	(0xff)

	fwohcireg_t	cntl_clr;
	fwohcireg_t	dummy0;
	fwohcireg_t	cmd;
	fwohcireg_t	match;
	fwohcireg_t	dummy1;
	fwohcireg_t	dummy2;
	fwohcireg_t	dummy3;
};

struct ohci_itdma{
	fwohcireg_t	cntl;
	fwohcireg_t	cntl_clr;
	fwohcireg_t	dummy0;
	fwohcireg_t	cmd;
};

struct ohci_registers {
	fwohcireg_t	ver;		/* Version No. 0x0 */
	fwohcireg_t	guid;		/* GUID_ROM No. 0x4 */
	fwohcireg_t	retry;		/* AT retries 0x8 */
#define FWOHCI_RETRY	0x8
	fwohcireg_t	csr_data;	/* CSR data   0xc */
	fwohcireg_t	csr_cmp;	/* CSR compare 0x10 */
	fwohcireg_t	csr_cntl;	/* CSR compare 0x14 */
	fwohcireg_t	rom_hdr;	/* config ROM ptr. 0x18 */
	fwohcireg_t	bus_id;		/* BUS_ID 0x1c */
	fwohcireg_t	bus_opt;	/* BUS option 0x20 */
#define	FWOHCIGUID_H	0x24
#define	FWOHCIGUID_L	0x28
	fwohcireg_t	guid_hi;	/* GUID hi 0x24 */
	fwohcireg_t	guid_lo;	/* GUID lo 0x28 */
	fwohcireg_t	dummy0[2];	/* dummy 0x2c-0x30 */
	fwohcireg_t	config_rom;	/* config ROM map 0x34 */
	fwohcireg_t	post_wr_lo;	/* post write addr lo 0x38 */
	fwohcireg_t	post_wr_hi;	/* post write addr hi 0x3c */
	fwohcireg_t	vender;		/* vender ID 0x40 */
	fwohcireg_t	dummy1[3];	/* dummy 0x44-0x4c */
	fwohcireg_t	hcc_cntl_set;	/* HCC control set 0x50 */
	fwohcireg_t	hcc_cntl_clr;	/* HCC control clr 0x54 */
#define	OHCI_HCC_BIBIV	(1 << 31)	/* BIBimage Valid */
#define	OHCI_HCC_BIGEND	(1 << 30)	/* noByteSwapData */
#define	OHCI_HCC_PRPHY	(1 << 23)	/* programPhyEnable */
#define	OHCI_HCC_PHYEN	(1 << 22)	/* aPhyEnhanceEnable */
#define	OHCI_HCC_LPS	(1 << 19)	/* LPS */
#define	OHCI_HCC_POSTWR	(1 << 18)	/* postedWriteEnable */
#define	OHCI_HCC_LINKEN	(1 << 17)	/* linkEnable */
#define	OHCI_HCC_RESET	(1 << 16)	/* softReset */
	fwohcireg_t	dummy2[2];	/* dummy 0x58-0x5c */
	fwohcireg_t	dummy3[1];	/* dummy 0x60 */
	fwohcireg_t	sid_buf;	/* self id buffer 0x64 */
	fwohcireg_t	sid_cnt;	/* self id count 0x68 */
	fwohcireg_t	dummy4[1];	/* dummy 0x6c */
	fwohcireg_t	ir_mask_hi_set;	/* ir mask hi set 0x70 */
	fwohcireg_t	ir_mask_hi_clr;	/* ir mask hi set 0x74 */
	fwohcireg_t	ir_mask_lo_set;	/* ir mask hi set 0x78 */
	fwohcireg_t	ir_mask_lo_clr;	/* ir mask hi set 0x7c */
#define	FWOHCI_INTSTAT		0x80
#define	FWOHCI_INTSTATCLR	0x84
#define	FWOHCI_INTMASK		0x88
#define	FWOHCI_INTMASKCLR	0x8c
	fwohcireg_t	int_stat;   /*       0x80 */
	fwohcireg_t	int_clear;  /*       0x84 */
	fwohcireg_t	int_mask;   /*       0x88 */
	fwohcireg_t	int_mask_clear;   /*       0x8c */
	fwohcireg_t	it_int_stat;   /*       0x90 */
	fwohcireg_t	it_int_clear;  /*       0x94 */
	fwohcireg_t	it_int_mask;   /*       0x98 */
	fwohcireg_t	it_mask_clear;   /*       0x9c */
	fwohcireg_t	ir_int_stat;   /*       0xa0 */
	fwohcireg_t	ir_int_clear;  /*       0xa4 */
	fwohcireg_t	ir_int_mask;   /*       0xa8 */
	fwohcireg_t	ir_mask_clear;   /*       0xac */
	fwohcireg_t	dummy5[11];	/* dummy 0xb0-d8 */
	fwohcireg_t	fairness;   /* fairness control      0xdc */
	fwohcireg_t	link_cntl;		/* Chip control 0xe0*/
	fwohcireg_t	link_cntl_clr;	/* Chip control clear 0xe4*/
#define FWOHCI_NODEID	0xe8
	fwohcireg_t	node;		/* Node ID 0xe8 */
#define	OHCI_NODE_VALID	(1 << 31)
#define	OHCI_NODE_ROOT	(1 << 30)

#define	OHCI_ASYSRCBUS	1

	fwohcireg_t	phy_access;	/* PHY cntl 0xec */
#define	PHYDEV_RDDONE		(1<<31)
#define	PHYDEV_RDCMD		(1<<15)
#define	PHYDEV_WRCMD		(1<<14)
#define	PHYDEV_REGADDR		8
#define	PHYDEV_WRDATA		0
#define	PHYDEV_RDADDR		24
#define	PHYDEV_RDDATA		16

	fwohcireg_t	cycle_timer;	/* Cycle Timer 0xf0 */
	fwohcireg_t	dummy6[3];	/* dummy 0xf4-fc */
	fwohcireg_t	areq_hi;	/* Async req. filter hi 0x100 */
	fwohcireg_t	areq_hi_clr;	/* Async req. filter hi 0x104 */
	fwohcireg_t	areq_lo;	/* Async req. filter lo 0x108 */
	fwohcireg_t	areq_lo_clr;	/* Async req. filter lo 0x10c */
	fwohcireg_t	preq_hi;	/* Async req. filter hi 0x110 */
	fwohcireg_t	preq_hi_clr;	/* Async req. filter hi 0x114 */
	fwohcireg_t	preq_lo;	/* Async req. filter lo 0x118 */
	fwohcireg_t	preq_lo_clr;	/* Async req. filter lo 0x11c */

	fwohcireg_t	pys_upper;	/* Physical Upper bound 0x120 */

	fwohcireg_t	dummy7[23];	/* dummy 0x124-0x17c */

	/*       0x180, 0x184, 0x188, 0x18c */
	/*       0x190, 0x194, 0x198, 0x19c */
	/*       0x1a0, 0x1a4, 0x1a8, 0x1ac */
	/*       0x1b0, 0x1b4, 0x1b8, 0x1bc */
	/*       0x1c0, 0x1c4, 0x1c8, 0x1cc */
	/*       0x1d0, 0x1d4, 0x1d8, 0x1dc */
	/*       0x1e0, 0x1e4, 0x1e8, 0x1ec */
	/*       0x1f0, 0x1f4, 0x1f8, 0x1fc */
	struct ohci_dma dma_ch[0x4];

	/*       0x200, 0x204, 0x208, 0x20c */
	/*       0x210, 0x204, 0x208, 0x20c */
	struct ohci_itdma dma_itch[0x20];

	/*       0x400, 0x404, 0x408, 0x40c */
	/*       0x410, 0x404, 0x408, 0x40c */
	struct ohci_dma dma_irch[0x20];
};

struct fwohcidb_tr{
	STAILQ_ENTRY(fwohcidb_tr) link;
	struct fw_xfer *xfer;
	struct fwohcidb *db;
	bus_dmamap_t dma_map;
	caddr_t buf;
	bus_addr_t bus_addr;
	int dbcnt;
};

/*
 * OHCI info structure.
 */
struct fwohci_txpkthdr{
	union{
		uint32_t ld[4];
		struct {
#if BYTE_ORDER == BIG_ENDIAN
			uint32_t spd:16, /* XXX include reserved field */
				 :8,
				 tcode:4,
				 :4;
#else
			uint32_t :4,
				 tcode:4,
				 :8,
				 spd:16; /* XXX include reserved fields */
#endif
		}common;
		struct {
#if BYTE_ORDER == BIG_ENDIAN
			uint32_t :8,
				 srcbus:1,
				 :4,
				 spd:3,
				 tlrt:8,
				 tcode:4,
				 :4;
#else
			uint32_t :4,
				 tcode:4,
				 tlrt:8,
				 spd:3,
				 :4,
				 srcbus:1,
				 :8;
#endif
			BIT16x2(dst, );
		}asycomm;
		struct {
#if BYTE_ORDER == BIG_ENDIAN
			uint32_t :13,
			         spd:3,
				 chtag:8,
				 tcode:4,
				 sy:4;
#else
			uint32_t sy:4,
				 tcode:4,
				 chtag:8,
			         spd:3,
				 :13;
#endif
			BIT16x2(len, );
		}stream;
	}mode;
};
struct fwohci_trailer{
#if BYTE_ORDER == BIG_ENDIAN
	uint32_t stat:16,
		  time:16;
#else
	uint32_t time:16,
		  stat:16;
#endif
};

#define	OHCI_CNTL_CYCSRC	(0x1 << 22)
#define	OHCI_CNTL_CYCMTR	(0x1 << 21)
#define	OHCI_CNTL_CYCTIMER	(0x1 << 20)
#define	OHCI_CNTL_PHYPKT	(0x1 << 10)
#define	OHCI_CNTL_SID		(0x1 << 9)

/*
 * defined in OHCI 1.1
 * chapter 6.1
 */
#define OHCI_INT_DMA_ATRQ	(0x1 << 0)
#define OHCI_INT_DMA_ATRS	(0x1 << 1)
#define OHCI_INT_DMA_ARRQ	(0x1 << 2)
#define OHCI_INT_DMA_ARRS	(0x1 << 3)
#define OHCI_INT_DMA_PRRQ	(0x1 << 4)
#define OHCI_INT_DMA_PRRS	(0x1 << 5)
#define OHCI_INT_DMA_IT 	(0x1 << 6)
#define OHCI_INT_DMA_IR 	(0x1 << 7)
#define OHCI_INT_PW_ERR 	(0x1 << 8)
#define OHCI_INT_LR_ERR 	(0x1 << 9)
#define OHCI_INT_PHY_SID	(0x1 << 16)
#define OHCI_INT_PHY_BUS_R	(0x1 << 17)
#define OHCI_INT_REG_FAIL	(0x1 << 18)
#define OHCI_INT_PHY_INT	(0x1 << 19)
#define OHCI_INT_CYC_START	(0x1 << 20)
#define OHCI_INT_CYC_64SECOND	(0x1 << 21)
#define OHCI_INT_CYC_LOST	(0x1 << 22)
#define OHCI_INT_CYC_ERR	(0x1 << 23)
#define OHCI_INT_ERR		(0x1 << 24)
#define OHCI_INT_CYC_LONG	(0x1 << 25)
#define OHCI_INT_PHY_REG	(0x1 << 26)
#define OHCI_INT_EN		(0x1 << 31)

#define IP_CHANNELS             0x0234
#define FWOHCI_MAXREC		2048

#define	OHCI_ISORA		0x02
#define	OHCI_ISORB		0x04

#define FWOHCITCODE_PHY		0xe


code:
/*-
 * Copyright (c) 2003 Hidetoshi SHimokawa
 * Copyright (c) 1998-2002 Katsushi Kobayashi and Hidetoshi SHimokawa
 * 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 acknowledgement as bellow:
 *
 *    This product includes software developed by K. Kobayashi and H. Shimokawa
 *
 * 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.
 *
 * $FreeBSD: release/9.0.0/sys/dev/firewire/fwohcivar.h 188079 2009-02-03 17:13:37Z sbruno $
 *
 */

#include <sys/taskqueue.h>

typedef struct fwohci_softc {
	struct firewire_comm fc;
	bus_space_tag_t bst;
	bus_space_handle_t bsh;
	void *ih;
#if defined(__DragonFly__) || __FreeBSD_version < 500000
	void *ih_cam;
	void *ih_bio;
#endif
	struct resource *bsr;
	struct resource *irq_res;
	struct fwohci_dbch{
		u_int ndb;
		u_int ndesc;
		STAILQ_HEAD(, fwohcidb_tr) db_trq;
		struct fwohcidb_tr *top, *bottom, *pdb_tr;
		struct fw_xferq xferq;
		int flags;
#define	FWOHCI_DBCH_INIT	(1<<0)
#define	FWOHCI_DBCH_FULL	(1<<1)
		/* used only in receive context */
		int buf_offset;	/* signed */
#define FWOHCI_DBCH_MAX_PAGES	32
		/* Context programs buffer */
		struct fwdma_alloc_multi *am;
		bus_dma_tag_t dmat;
	} arrq, arrs, atrq, atrs, it[OHCI_DMA_ITCH], ir[OHCI_DMA_IRCH];
	u_int maxrec;
	uint32_t *sid_buf;
	struct fwdma_alloc sid_dma;
	struct fwdma_alloc crom_dma;
	struct fwdma_alloc dummy_dma;
	uint32_t intmask, irstat, itstat;
	uint32_t intstat;
	struct task fwohci_task_busreset;
	struct task fwohci_task_sid;
	struct task fwohci_task_dma;
	int cycle_lost;
} fwohci_softc_t;

void fwohci_intr (void *arg);
int fwohci_init (struct fwohci_softc *, device_t);
void fwohci_poll (struct firewire_comm *, int, int);
void fwohci_reset (struct fwohci_softc *, device_t);
int fwohci_detach (struct fwohci_softc *, device_t);
int fwohci_resume (struct fwohci_softc *, device_t);
int fwohci_stop (struct fwohci_softc *, device_t dev);


code:
/*-
 * Copyright (C) 2003
 * 	Hidetoshi Shimokawa. 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 Hidetoshi Shimokawa.
 *
 * 4. Neither the name of the author 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.
 *
 * $FreeBSD: release/9.0.0/sys/dev/firewire/fwphyreg.h 188508 2009-02-12 03:05:42Z sbruno $
 */

/*
 * IEEE 1394a
 * Figure 5B - 1
 */
struct phyreg_base {
#if BYTE_ORDER == BIG_ENDIAN
	uint8_t	phy_id:6,
		r:1,
		cps:1;
	uint8_t	rhb:1,
		ibr:1,
		gap_count:6;
	uint8_t	extended:3,
		num_ports:5;
	uint8_t	phy_speed:3,
		:1,
		delay:4;
	uint8_t	lctrl:1,
		c:1,
		jitter:3,
		pwr_class:3;
	uint8_t	wdie:1,
		isbr:1,
		ctoi:1,
		cpsi:1,
		stoi:1,
		pei:1,
		eaa:1,
		emc:1;
	uint8_t	legacy_spd:3,
		blink:1,
		bridge:2,
		:2;
	uint8_t	page_select:3,
		:1,
		port_select:4;
#else
	uint8_t	cps:1,
		r:1,
		phy_id:6;
	uint8_t	gap_count:6,
		ibr:1,
		rhb:1;
	uint8_t	num_ports:5,
		extended:3;
	uint8_t	delay:4,
		:1,
		phy_speed:3;
	uint8_t	pwr_class:3,
		jitter:3,
		c:1,
		lctrl:1;
	uint8_t	emc:1,
		eaa:1,
		pei:1,
		stoi:1,
		cpsi:1,
		ctoi:1,
		isbr:1,
		wdie:1;
	uint8_t	:2,
		bridge:2,
		blink:1,
		legacy_spd:3;
	uint8_t	port_select:4,
		:1,
		page_select:3;
#endif
};

/*
 * IEEE 1394a
 * Figure 5B - 2
 */
struct phyreg_page0 {
#if BYTE_ORDER == BIG_ENDIAN
	uint8_t	astat:2,
		bstat:2,
		ch:1,
		con:1,
		rxok:1,
		dis:1;
	uint8_t	negotiated_speed:3,
		pie:1,
		fault:1,
		stanby_fault:1,
		disscrm:1,
		b_only:1;
	uint8_t	dc_connected:1,
		max_port_speed:3,
		lpp:1,
		cable_speed:3;
	uint8_t	connection_unreliable:1,
		:3,
		beta_mode:1,
		:3;
	uint8_t	port_error;
	uint8_t	:5,
		loop_disable:1,
		in_standby:1,
		hard_disable:1;
	uint8_t	:8;
	uint8_t	:8;
#else
	uint8_t	dis:1,
		rxok:1,
		con:1,
		ch:1,
		bstat:2,
		astat:2;
	uint8_t	b_only:1,
		disscrm:1,
		stanby_fault:1,
		fault:1,
		pie:1,
		negotiated_speed:3;
	uint8_t	cable_speed:3,
		lpp:1,
		max_port_speed:3,
		dc_connected:1;
	uint8_t	:3,
		beta_mode:1,
		:3,
		connection_unreliable:1;
	uint8_t	port_error;
	uint8_t	hard_disable:1,
		in_standby:1,
		loop_disable:1,
		:5;
	uint8_t	:8;
	uint8_t	:8;
#endif
};

/*
 * IEEE 1394a
 * Figure 5B - 3
 */
struct phyreg_page1 {
	uint8_t	compliance;
	uint8_t	:8;
	uint8_t	vendor_id[3];
	uint8_t	product_id[3];
};


code:
/*-
 * Copyright (c) 2003 Hidetoshi Shimokawa
 * Copyright (c) 1998-2002 Katsushi Kobayashi and Hidetoshi Shimokawa
 * 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 acknowledgement as bellow:
 *
 *    This product includes software developed by K. Kobayashi and H. Shimokawa
 *
 * 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.
 *
 * $FreeBSD: release/9.0.0/sys/dev/firewire/iec13213.h 139749 2005-01-06 01:43:34Z imp $
 *
 */

#define	STATE_CLEAR	0x0000
#define	STATE_SET	0x0004
#define	NODE_IDS	0x0008
#define	RESET_START	0x000c
#define	SPLIT_TIMEOUT_HI	0x0018
#define	SPLIT_TIMEOUT_LO	0x001c
#define	CYCLE_TIME	0x0200
#define	BUS_TIME	0x0204
#define	BUSY_TIMEOUT	0x0210
#define	PRIORITY_BUDGET 0x0218
#define	BUS_MGR_ID	0x021c
#define	BANDWIDTH_AV	0x0220
#define	CHANNELS_AV_HI	0x0224
#define	CHANNELS_AV_LO	0x0228
#define	IP_CHANNELS	0x0234

#define	CONF_ROM	0x0400

#define	TOPO_MAP	0x1000
#define	SPED_MAP	0x2000

#define CSRTYPE_SHIFT	6
#define CSRTYPE_MASK	(3 << CSRTYPE_SHIFT)
#define CSRTYPE_I	(0 << CSRTYPE_SHIFT) /* Immediate */
#define CSRTYPE_C	(1 << CSRTYPE_SHIFT) /* CSR offset */
#define CSRTYPE_L	(2 << CSRTYPE_SHIFT) /* Leaf */
#define CSRTYPE_D	(3 << CSRTYPE_SHIFT) /* Directory */

/*
 * CSR keys
 * 00 - 2F: defined by CSR architecture standards.
 * 30 - 37: defined by BUS starndards
 * 38 - 3F: defined by Vendor/Specifier
 */
#define CSRKEY_MASK	0x3f
#define CSRKEY_DESC	0x01 /* Descriptor */
#define CSRKEY_BDINFO	0x02 /* Bus_Dependent_Info */
#define CSRKEY_VENDOR	0x03 /* Vendor */
#define CSRKEY_HW	0x04 /* Hardware_Version */
#define CSRKEY_MODULE	0x07 /* Module */
#define CSRKEY_NCAP	0x0c /* Node_Capabilities */
#define CSRKEY_EUI64	0x0d /* EUI_64 */
#define CSRKEY_UNIT	0x11 /* Unit */
#define CSRKEY_SPEC	0x12 /* Specifier_ID */
#define CSRKEY_VER	0x13 /* Version */
#define CSRKEY_DINFO	0x14 /* Dependent_Info */
#define CSRKEY_ULOC	0x15 /* Unit_Location */
#define CSRKEY_MODEL	0x17 /* Model */
#define CSRKEY_INST	0x18 /* Instance */
#define CSRKEY_KEYW	0x19 /* Keyword */
#define CSRKEY_FEAT	0x1a /* Feature */
#define CSRKEY_EROM	0x1b /* Extended_ROM */
#define CSRKEY_EKSID	0x1c /* Extended_Key_Specifier_ID */
#define CSRKEY_EKEY	0x1d /* Extended_Key */
#define CSRKEY_EDATA	0x1e /* Extended_Data */
#define CSRKEY_MDESC	0x1f /* Modifiable_Descriptor */
#define CSRKEY_DID	0x20 /* Directory_ID */
#define CSRKEY_REV	0x21 /* Revision */

#define CSRKEY_FIRM_VER	0x3c /* Firmware version */
#define CSRKEY_UNIT_CH	0x3a /* Unit characteristics */
#define CSRKEY_COM_SPEC	0x38 /* Command set revision */
#define CSRKEY_COM_SET	0x39 /* Command set */

#define CROM_UDIR	(CSRTYPE_D | CSRKEY_UNIT)  /* 0x81 Unit directory */
#define CROM_TEXTLEAF	(CSRTYPE_L | CSRKEY_DESC)  /* 0x81 Text leaf */
#define CROM_LUN	(CSRTYPE_I | CSRKEY_DINFO) /* 0x14 Logical unit num. */
#define CROM_MGM	(CSRTYPE_C | CSRKEY_DINFO) /* 0x54 Management agent */

#define CSRVAL_VENDOR_PRIVATE	0xacde48
#define CSRVAL_1394TA	0x00a02d
#define CSRVAL_ANSIT10	0x00609e
#define CSRVAL_IETF	0x00005e

#define CSR_PROTAVC	0x010001
#define CSR_PROTCAL	0x010002
#define CSR_PROTEHS	0x010004
#define CSR_PROTHAVI	0x010008
#define CSR_PROTCAM104	0x000100
#define CSR_PROTCAM120	0x000101
#define CSR_PROTCAM130	0x000102
#define CSR_PROTDPP	0x0a6be2
#define CSR_PROTIICP	0x4b661f

#define CSRVAL_T10SBP2	0x010483
#define CSRVAL_SCSI	0x0104d8

struct csrreg {
#if BYTE_ORDER == BIG_ENDIAN
	uint32_t key:8,
		 val:24;
#else
	uint32_t val:24,
		 key:8;
#endif
};
struct csrhdr {
#if BYTE_ORDER == BIG_ENDIAN
	uint32_t info_len:8,
		 crc_len:8,
		 crc:16;
#else
	uint32_t crc:16,
		 crc_len:8,
		 info_len:8;
#endif
};
struct csrdirectory {
	BIT16x2(crc_len, crc);
	struct csrreg entry[0];
};
struct csrtext {
	BIT16x2(crc_len, crc);
#if BYTE_ORDER == BIG_ENDIAN
	uint32_t spec_type:8,
		 spec_id:24;
#else
	uint32_t spec_id:24,
		 spec_type:8;
#endif
	uint32_t lang_id;
	uint32_t text[0];
};

struct bus_info {
#define	CSR_BUS_NAME_IEEE1394	0x31333934
	uint32_t bus_name;
#if BYTE_ORDER == BIG_ENDIAN
	uint32_t irmc:1,		/* iso. resource manager capable */
		 cmc:1,			/* cycle master capable */
		 isc:1,			/* iso. operation support */
		 bmc:1,			/* bus manager capable */
		 pmc:1,			/* power manager capable */
		 :3,
		 cyc_clk_acc:8,		/* 0 <= ppm <= 100 */
		 max_rec:4,		/* (2 << max_rec) bytes */
		 :2,
		 max_rom:2,
		 generation:4,
		 :1,
		 link_spd:3;
#else
	uint32_t link_spd:3,
		 :1,
		 generation:4,
		 max_rom:2,
		 :2,
		 max_rec:4,		/* (2 << max_rec) bytes */
		 cyc_clk_acc:8,		/* 0 <= ppm <= 100 */
		 :3,
		 pmc:1,			/* power manager capable */
		 bmc:1,			/* bus manager capable */
		 isc:1,			/* iso. operation support */
		 cmc:1,			/* cycle master capable */
		 irmc:1;		/* iso. resource manager capable */
#endif
	struct fw_eui64 eui64;
};
/* max_rom */
#define MAXROM_4	0
#define MAXROM_64	1
#define MAXROM_1024	2

#define CROM_MAX_DEPTH	10
struct crom_ptr {
	struct csrdirectory *dir;
	int index;
};

struct crom_context {
	int depth;
	struct crom_ptr stack[CROM_MAX_DEPTH];
};

void crom_init_context(struct crom_context *, uint32_t *);
struct csrreg *crom_get(struct crom_context *);
void crom_next(struct crom_context *);
void crom_parse_text(struct crom_context *, char *, int);
uint16_t crom_crc(uint32_t *r, int);
struct csrreg *crom_search_key(struct crom_context *, uint8_t);
int crom_has_specver(uint32_t *, uint32_t, uint32_t);

#if !defined(_KERNEL) && !defined(_BOOT)
char *crom_desc(struct crom_context *, char *, int);
#endif

/* For CROM build */
#if defined(_KERNEL) || defined(_BOOT) || defined(TEST)
#define CROM_MAX_CHUNK_LEN 20
struct crom_src {
	struct csrhdr hdr;
	struct bus_info businfo;
	STAILQ_HEAD(, crom_chunk) chunk_list;
};

struct crom_chunk {
	STAILQ_ENTRY(crom_chunk) link;
	struct crom_chunk *ref_chunk;
	int ref_index;
	int offset;
	struct {
		BIT16x2(crc_len, crc);
		uint32_t buf[CROM_MAX_CHUNK_LEN];
	} data;
};

extern int crom_add_quad(struct crom_chunk *, uint32_t);
extern int crom_add_entry(struct crom_chunk *, int, int);
extern int crom_add_chunk(struct crom_src *src, struct crom_chunk *,
					struct crom_chunk *, int);
extern int crom_add_simple_text(struct crom_src *src, struct crom_chunk *,
					struct crom_chunk *, char *);
extern int crom_load(struct crom_src *, uint32_t *, int);
#endif


code:
/*-
 * Copyright (c) 2003 Hidetoshi Shimokawa
 * Copyright (c) 1998-2002 Katsushi Kobayashi and Hidetoshi Shimokawa
 * 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 acknowledgement as bellow:
 *
 *    This product includes software developed by K. Kobayashi and H. Shimokawa
 *
 * 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.
 *
 * $FreeBSD: release/9.0.0/sys/dev/firewire/iec68113.h 139749 2005-01-06 01:43:34Z imp $
 *
 */

#define		DV_BROADCAST_ON (1<<30)
#define		oMPR		0x900
#define		oPCR		0x904
#define		iMPR		0x980
#define		iPCR		0x984

struct ciphdr {
#if BYTE_ORDER == BIG_ENDIAN
	uint8_t eoh0:1,		/* 0 */
		form0:1,	/* 0 */
		src:6;
#else
	uint8_t src:6,
		form0:1,	/* 0 */
		eoh0:1;		/* 0 */
#endif
	uint8_t len;
#if BYTE_ORDER == BIG_ENDIAN
	uint8_t fn:2,
		qpc:3,
		sph:1,
		:2;
#else
	uint8_t :2,
		sph:1,
		qpc:3,
		fn:2;
#endif
	uint8_t dbc;
#if BYTE_ORDER == BIG_ENDIAN
	uint8_t eoh1:1,		/* 1 */
		form1:1,	/* 0 */
		fmt:6;
#else
	uint8_t fmt:6,
		form1:1,	/* 0 */
		eoh1:1;		/* 1 */
#endif
#define CIP_FMT_DVCR	0
#define CIP_FMT_MPEG	(1<<5)
	union {
		struct {
#if BYTE_ORDER == BIG_ENDIAN
			uint8_t fs:1,		/* 50/60 field system
								NTSC/PAL */
				stype:5,
				:2;
#else
			uint8_t :2,
				stype:5,
		  		fs:1;		/* 50/60 field system
								NTSC/PAL */
#endif
#define	CIP_STYPE_SD	0
#define	CIP_STYPE_SDL	1
#define	CIP_STYPE_HD	2
	  		uint16_t cyc:16;	/* take care of byte order! */
		} __attribute__ ((packed)) dv;
		uint8_t bytes[3];
	} fdf;

};
struct dvdbc{
#if BYTE_ORDER == BIG_ENDIAN
	uint8_t sct:3,		/* Section type */
		:1,		/* Reserved */
		arb:4;		/* Arbitrary bit */
#else
	uint8_t arb:4,		/* Arbitrary bit */
		:1,		/* Reserved */
		sct:3;		/* Section type */
#endif
#define	DV_SCT_HEADER	0
#define	DV_SCT_SUBCODE	1
#define	DV_SCT_VAUX	2
#define	DV_SCT_AUDIO	3
#define	DV_SCT_VIDEO	4
#if BYTE_ORDER == BIG_ENDIAN
	uint8_t dseq:4,		/* DIF sequence number */
		fsc:1,		/* ID of a DIF block in each channel */
		:3;
#else
	uint8_t :3,
		fsc:1,		/* ID of a DIF block in each channel */
		dseq:4;		/* DIF sequence number */
#endif
	uint8_t dbn;		/* DIF block number */
	uint8_t payload[77];
#define	DV_DSF_12	0x80	/* PAL: payload[0] in Header DIF */
};


code:
/*-
 * Copyright (c) 2002-2003
 * 	Hidetoshi Shimokawa. 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 Hidetoshi Shimokawa.
 *
 * 4. Neither the name of the author 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.
 *
 * $FreeBSD: release/9.0.0/sys/dev/firewire/if_fwevar.h 170374 2007-06-06 14:31:36Z simokawa $
 */

#ifndef _NET_IF_FWEVAR_H_
#define _NET_IF_FWEVAR_H_

struct fwe_softc {
	/* XXX this must be the first for fd.post_explore() */
	struct firewire_dev_comm fd;
	short stream_ch;
	short dma_ch;
	struct fw_pkt pkt_hdr;
	STAILQ_HEAD(, fw_xfer) xferlist;
	struct fwe_eth_softc {
		struct ifnet *ifp;
		struct fwe_softc *fwe;
	} eth_softc;
	struct mtx mtx;
};
#define FWE_LOCK(fwe)	mtx_lock(&(fwe)->mtx)
#define FWE_UNLOCK(fwe)	mtx_unlock(&(fwe)->mtx)
#endif /* !_NET_IF_FWEVAR_H_ */


code:
/*-
 * Copyright (c) 2004
 *	Doug Rabson
 * Copyright (c) 2002-2003
 * 	Hidetoshi Shimokawa. 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 Hidetoshi Shimokawa.
 *
 * 4. Neither the name of the author 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.
 *
 * $FreeBSD: release/9.0.0/sys/dev/firewire/if_fwipvar.h 170374 2007-06-06 14:31:36Z simokawa $
 */

#ifndef _NET_IF_FWIPVAR_H_
#define _NET_IF_FWIPVAR_H_

struct fwip_softc {
	/* XXX this must be first for fd.post_explore() */
	struct firewire_dev_comm fd;
	short dma_ch;
	struct fw_bind fwb;
	struct fw_eui64 last_dest;
	struct fw_pkt last_hdr;
	struct task start_send;
	STAILQ_HEAD(, fw_xfer) xferlist;
	struct crom_chunk unit4;	/* unit directory for IPv4 */
	struct crom_chunk spec4;	/* specifier description IPv4 */
	struct crom_chunk ver4;		/* version description IPv4 */
	struct crom_chunk unit6;	/* unit directory for IPv6 */
	struct crom_chunk spec6;	/* specifier description IPv6 */
	struct crom_chunk ver6;		/* version description IPv6 */
	struct fwip_eth_softc {
		struct ifnet *fwip_ifp;
		struct fwip_softc *fwip;
	} fw_softc;
	struct mtx mtx;
};
#define FWIP_LOCK(fwip)   mtx_lock(&(fwip)->mtx)
#define FWIP_UNLOCK(fwip) mtx_unlock(&(fwip)->mtx)
#endif /* !_NET_IF_FWIPVAR_H_ */


code:
/*-
 * Copyright (c) 2003 Hidetoshi Shimokawa
 * Copyright (c) 1998-2002 Katsushi Kobayashi and Hidetoshi Shimokawa
 * 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 acknowledgement as bellow:
 *
 *    This product includes software developed by K. Kobayashi and H. Shimokawa
 *
 * 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.
 *
 * $FreeBSD: release/9.0.0/sys/dev/firewire/sbp.h 190792 2009-04-07 02:33:46Z sbruno $
 *
 */

#define ORB_NOTIFY	(1 << 31)
#define	ORB_FMT_STD	(0 << 29)
#define	ORB_FMT_VED	(2 << 29)
#define	ORB_FMT_NOP	(3 << 29)
#define	ORB_FMT_MSK	(3 << 29)
#define	ORB_EXV		(1 << 28)
/* */
#define	ORB_CMD_IN	(1 << 27)
/* */
#define	ORB_CMD_SPD(x)	((x) << 24)
#define	ORB_CMD_MAXP(x)	((x) << 20)
#define	ORB_RCN_TMO(x)	((x) << 20)
#define	ORB_CMD_PTBL	(1 << 19)
#define	ORB_CMD_PSZ(x)	((x) << 16)

#define	ORB_FUN_LGI	(0 << 16)
#define	ORB_FUN_QLG	(1 << 16)
#define	ORB_FUN_RCN	(3 << 16)
#define	ORB_FUN_LGO	(7 << 16)
#define	ORB_FUN_ATA	(0xb << 16)
#define	ORB_FUN_ATS	(0xc << 16)
#define	ORB_FUN_LUR	(0xe << 16)
#define	ORB_FUN_RST	(0xf << 16)
#define	ORB_FUN_MSK	(0xf << 16)
#define	ORB_FUN_RUNQUEUE 0xffff

#define ORB_RES_CMPL 0
#define ORB_RES_FAIL 1
#define ORB_RES_ILLE 2
#define ORB_RES_VEND 3

#define SBP_DEBUG(x)	if (debug > x) {
#define END_DEBUG	}

struct ind_ptr {
	uint32_t hi,lo;
};

#define SBP_RECV_LEN 32

struct sbp_login_res{
	uint16_t	len;
	uint16_t	id;
	uint16_t	res0;
	uint16_t	cmd_hi;
	uint32_t	cmd_lo;
	uint16_t	res1;
	uint16_t	recon_hold;
};

struct sbp_status{
#if BYTE_ORDER == BIG_ENDIAN
	uint8_t		src:2,
			resp:2,
			dead:1,
			len:3;
#else
	uint8_t		len:3,
			dead:1,
			resp:2,
			src:2;
#endif
	uint8_t		status;
	uint16_t	orb_hi;
	uint32_t	orb_lo;
	uint32_t	data[6];
};
/* src */
#define SRC_NEXT_EXISTS	0
#define SRC_NO_NEXT	1
#define SRC_UNSOL	2

/* resp */
#define SBP_REQ_CMP	0	/* request complete */
#define SBP_TRANS_FAIL	1	/* transport failure */
#define SBP_ILLE_REQ	2	/* illegal request */
#define SBP_VEND_DEP	3	/* vendor dependent */

/* status (resp == 0) */
/*   0: No additional Information to report */
/*   1: Request Type not supported */
/*   2: Speed not supported */
/*   3: Page size not supported */
/*   4: Access denied */
#define STATUS_ACCESS_DENY	4
#define STATUS_LUR		5
/*   6: Maximum payload too small */
/*   7: Reserved for future standardization */
/*   8: Resource unavailabe */
#define STATUS_RES_UNAVAIL	8
/*   9: Function Rejected */
/*  10: Login ID not recognized */
/*  11: Dummy ORB completed */
/*  12: Request aborted */
/* 255: Unspecified error */

/* status (resp == 1) */
/* Referenced object */
#define OBJ_ORB		(0 << 6)	/* 0: ORB */
#define OBJ_DATA	(1 << 6)	/* 1: Data buffer */
#define OBJ_PT		(2 << 6)	/* 2: Page table */
#define OBJ_UNSPEC	(3 << 6)	/* 3: Unable to specify */
/* Serial bus error */
/* 0: Missing acknowledge */
/* 1: Reserved; not to be used */
/* 2: Time-out error */
#define SBE_TIMEOUT 2
/* 3: Reserved; not to be used */
/* 4: Busy retry limit exceeded: ack_busy_X */
/* 5: Busy retry limit exceeded: ack_busy_A */
/* 6: Busy retry limit exceeded: ack_busy_B */
/* 7-A: Reserved for future standardization */
/* B: Tardy retry limit exceeded */
/* C: Confilict error */
/* D: Data error */
/* E: Type error */
/* F: Address error */

struct sbp_cmd_status{
#define SBP_SFMT_CURR 0
#define SBP_SFMT_DEFER 1
#if BYTE_ORDER == BIG_ENDIAN
	uint8_t		sfmt:2,
			status:6;
	uint8_t		valid:1,
			mark:1,
			eom:1,
			ill_len:1,
			s_key:4;
#else
	uint8_t		status:6,
			sfmt:2;
	uint8_t		s_key:4,
			ill_len:1,
			eom:1,
			mark:1,
			valid:1;
#endif
	uint8_t		s_code;
	uint8_t		s_qlfr;
	uint32_t	info;
	uint32_t	cdb;
	uint8_t		fru;
	uint8_t		s_keydep[3];
	uint32_t	vend[2];
};

#define ORB_FUN_NAMES \
	/* 0 */ "LOGIN", \
	/* 1 */ "QUERY LOGINS", \
	/* 2 */ "Reserved", \
	/* 3 */ "RECONNECT", \
	/* 4 */ "SET PASSWORD", \
	/* 5 */ "Reserved", \
	/* 6 */ "Reserved", \
	/* 7 */ "LOGOUT", \
	/* 8 */ "Reserved", \
	/* 9 */ "Reserved", \
	/* A */ "Reserved", \
	/* B */ "ABORT TASK", \
	/* C */ "ABORT TASK SET", \
	/* D */ "Reserved", \
	/* E */ "LOGICAL UNIT RESET", \
	/* F */ "TARGET RESET"


code:
/*-
 * Copyright (c) 2005, Joseph Koshy
 * 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 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 AUTHOR 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.
 *
 * $FreeBSD: release/9.0.0/sys/dev/hwpmc/hwpmc_amd.h 184802 2008-11-09 17:37:54Z jkoshy $
 */

/* Machine dependent interfaces */

#ifndef _DEV_HWPMC_AMD_H_
#define	_DEV_HWPMC_AMD_H_ 1

/* AMD K7 and K8 PMCs */

#define	AMD_PMC_EVSEL_0		0xC0010000
#define	AMD_PMC_EVSEL_1		0xC0010001
#define	AMD_PMC_EVSEL_2		0xC0010002
#define	AMD_PMC_EVSEL_3		0xC0010003

#define	AMD_PMC_PERFCTR_0	0xC0010004
#define	AMD_PMC_PERFCTR_1	0xC0010005
#define	AMD_PMC_PERFCTR_2	0xC0010006
#define	AMD_PMC_PERFCTR_3	0xC0010007

#define	AMD_NPMCS		4

#define	AMD_PMC_COUNTERMASK	0xFF000000
#define	AMD_PMC_TO_COUNTER(x)	(((x) << 24) & AMD_PMC_COUNTERMASK)
#define	AMD_PMC_INVERT		(1 << 23)
#define	AMD_PMC_ENABLE		(1 << 22)
#define	AMD_PMC_INT		(1 << 20)
#define	AMD_PMC_PC		(1 << 19)
#define	AMD_PMC_EDGE		(1 << 18)
#define	AMD_PMC_OS		(1 << 17)
#define	AMD_PMC_USR		(1 << 16)

#define	AMD_PMC_UNITMASK_M	0x10
#define	AMD_PMC_UNITMASK_O	0x08
#define	AMD_PMC_UNITMASK_E	0x04
#define	AMD_PMC_UNITMASK_S	0x02
#define	AMD_PMC_UNITMASK_I	0x01
#define	AMD_PMC_UNITMASK_MOESI	0x1F

#define	AMD_PMC_UNITMASK	0xFF00
#define	AMD_PMC_EVENTMASK 	0x00FF

#define	AMD_PMC_TO_UNITMASK(x)	(((x) << 8) & AMD_PMC_UNITMASK)
#define	AMD_PMC_TO_EVENTMASK(x)	((x) & 0xFF)
#define	AMD_VALID_BITS		(AMD_PMC_COUNTERMASK | AMD_PMC_INVERT |	\
	AMD_PMC_ENABLE | AMD_PMC_INT | AMD_PMC_PC | AMD_PMC_EDGE | 	\
	AMD_PMC_OS | AMD_PMC_USR | AMD_PMC_UNITMASK | AMD_PMC_EVENTMASK)

#define AMD_PMC_CAPS		(PMC_CAP_INTERRUPT | PMC_CAP_USER | 	\
	PMC_CAP_SYSTEM | PMC_CAP_EDGE | PMC_CAP_THRESHOLD | 		\
	PMC_CAP_READ | PMC_CAP_WRITE | PMC_CAP_INVERT | PMC_CAP_QUALIFIER)

#define AMD_PMC_IS_STOPPED(evsel) ((rdmsr((evsel)) & AMD_PMC_ENABLE) == 0)
#define AMD_PMC_HAS_OVERFLOWED(pmc) ((rdpmc(pmc) & (1ULL << 47)) == 0)

#define	AMD_RELOAD_COUNT_TO_PERFCTR_VALUE(V)	(-(V))
#define	AMD_PERFCTR_VALUE_TO_RELOAD_COUNT(P)	(-(P))

struct pmc_md_amd_op_pmcallocate {
	uint32_t	pm_amd_config;
};

#ifdef _KERNEL

/* MD extension for 'struct pmc' */
struct pmc_md_amd_pmc {
	uint32_t	pm_amd_evsel;
};

#endif /* _KERNEL */
#endif /* _DEV_HWPMC_AMD_H_ */


code:
/*-
 * Copyright (c) 2008 Joseph Koshy
 * 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 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 AUTHOR 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.
 *
 * $FreeBSD: release/9.0.0/sys/dev/hwpmc/hwpmc_core.h 210621 2010-07-29 17:52:23Z gnn $
 */

#ifndef _DEV_HWPMC_CORE_H_
#define	_DEV_HWPMC_CORE_H_ 1

/*
 * Fixed-function PMCs.
 */
struct pmc_md_iaf_op_pmcallocate {
	uint16_t	pm_iaf_flags;	/* additional flags */
};

#define	IAF_OS		0x1
#define	IAF_USR		0x2
#define	IAF_ANY		0x4
#define	IAF_PMI		0x8

/*
 * Programmable PMCs.
 */
struct pmc_md_iap_op_pmcallocate {
	uint32_t	pm_iap_config;
	uint32_t	pm_iap_rsp;
};

#define	IAP_EVSEL(C)	((C) & 0xFF)
#define	IAP_UMASK(C)	((C) & 0xFF00)
#define	IAP_USR		(1 << 16)
#define	IAP_OS		(1 << 17)
#define	IAP_EDGE	(1 << 18)
#define	IAP_INT		(1 << 20)
#define	IAP_ANY		(1 << 21)
#define	IAP_EN		(1 << 22)
#define	IAP_INV		(1 << 23)
#define	IAP_CMASK(C)	(((C) & 0xFF) << 24)

#define	IA_OFFCORE_RSP_MASK	0xF7FF

#ifdef	_KERNEL

/*
 * Fixed-function counters.
 */

#define	IAF_MASK				0xF

#define	IAF_COUNTER_MASK			0x0000ffffffffffff
#define	IAF_CTR0				0x309
#define	IAF_CTR1				0x30A
#define	IAF_CTR2				0x30B

/*
 * The IAF_CTRL MSR is laid out in the following way.
 *
 * Bit Position    Use
 * 63 - 12         Reserved (do not touch)
 * 11              Ctr 2 PMI
 * 10              Reserved (do not touch)
 * 9-8             Ctr 2 Enable
 * 7               Ctr 1 PMI
 * 6               Reserved (do not touch)
 * 5-4             Ctr 1 Enable
 * 3               Ctr 0 PMI
 * 2               Reserved (do not touch)
 * 1-0             Ctr 0 Enable (3: All Levels, 2: User, 1: OS, 0: Disable)
 */

#define	IAF_OFFSET				32
#define	IAF_CTRL				0x38D
#define	IAF_CTRL_MASK				0x0000000000000bbb

/*
 * Programmable counters.
 */

#define	IAP_PMC0				0x0C1

/*
 * IAP_EVSEL(n) is laid out in the following way.
 *
 * Bit Position    Use
 * 63-31           Reserved (do not touch)
 * 31-24           Counter Mask
 * 23              Invert
 * 22              Enable
 * 21              Reserved (do not touch)
 * 20              APIC Interrupt Enable
 * 19              Pin Control
 * 18              Edge Detect
 * 17              OS
 * 16              User
 * 15-8            Unit Mask
 * 7-0             Event Select
 */

#define	IAP_EVSEL_MASK				0x00000000ffdfffff
#define	IAP_EVSEL0				0x186

/*
 * Simplified programming interface in Intel Performance Architecture
 * v2 and later.
 */

#define	IA_GLOBAL_STATUS			0x38E
#define	IA_GLOBAL_CTRL				0x38F

/*
 * IA_GLOBAL_CTRL is layed out in the following way.
 *
 * Bit Position    Use
 * 63-35           Reserved (do not touch)
 * 34              IAF Counter 2 Enable
 * 33              IAF Counter 1 Enable
 * 32              IAF Counter 0 Enable
 * 31-0            Depends on programmable counters
 */

/* The mask is only for the fixed porttion of the register. */
#define	IAF_GLOBAL_CTRL_MASK			0x0000000700000000

/* The mask is only for the programmable porttion of the register. */
#define IAP_GLOBAL_CTRL_MASK			0x00000000ffffffff

/* The mask is for both the fixed and programmable porttions of the register. */
#define IA_GLOBAL_CTRL_MASK			0x00000007ffffffff

#define	IA_GLOBAL_OVF_CTRL			0x390

#define	IA_GLOBAL_STATUS_FLAG_CONDCHG		(1ULL << 63)
#define	IA_GLOBAL_STATUS_FLAG_OVFBUF		(1ULL << 62)

/*
 * Offcore response configuration.
 */
#define	IA_OFFCORE_RSP0				0x1A6
#define	IA_OFFCORE_RSP1				0x1A7

struct pmc_md_iaf_pmc {
	uint64_t	pm_iaf_ctrl;
};

struct pmc_md_iap_pmc {
	uint32_t	pm_iap_evsel;
	uint32_t	pm_iap_rsp;
};

/*
 * Prototypes.
 */

int	pmc_core_initialize(struct pmc_mdep *_md, int _maxcpu);
void	pmc_core_finalize(struct pmc_mdep *_md);

void	pmc_core_mark_started(int _cpu, int _pmc);

int	pmc_iaf_initialize(struct pmc_mdep *_md, int _maxcpu, int _npmc, int _width);
void	pmc_iaf_finalize(struct pmc_mdep *_md);

int	pmc_iap_initialize(struct pmc_mdep *_md, int _maxcpu, int _npmc, int _width,
	    int _flags);
void	pmc_iap_finalize(struct pmc_mdep *_md);

#endif	/* _KERNEL */
#endif	/* _DEV_HWPMC_CORE_H */


code:
/*-
 * Copyright (c) 2010 George V. Neville-Neil <gnn@freebsd.org>
 * 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 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 AUTHOR 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.
 *
 * $FreeBSD: release/9.0.0/sys/dev/hwpmc/hwpmc_mips24k.h 204635 2010-03-03 15:05:58Z gnn $
 */

#ifndef _DEV_HWPMC_MIPS24K_H_
#define _DEV_HWPMC_MIPS24K_H_

#define	MIPS24K_PMC_CAPS	(PMC_CAP_INTERRUPT | PMC_CAP_USER |     \
				 PMC_CAP_SYSTEM | PMC_CAP_EDGE |	\
				 PMC_CAP_THRESHOLD | PMC_CAP_READ |	\
				 PMC_CAP_WRITE | PMC_CAP_INVERT |	\
				 PMC_CAP_QUALIFIER)

#define MIPS24K_PMC_USER_ENABLE           0x08 /* Count in USER mode */
#define MIPS24K_PMC_SUPER_ENABLE          0x04 /* Count in SUPERVISOR mode */
#define MIPS24K_PMC_KERNEL_ENABLE         0x02 /* Count in KERNEL mode */
#define MIPS24K_PMC_ENABLE (MIPS24K_PMC_USER_ENABLE |	   \
			    MIPS24K_PMC_SUPER_ENABLE |	   \
			    MIPS24K_PMC_KERNEL_ENABLE)

#define	MIPS24K_RELOAD_COUNT_TO_PERFCTR_VALUE(R)	(-(R))
#define	MIPS24K_PERFCTR_VALUE_TO_RELOAD_COUNT(P)	(-(P))

#define MIPS24K_PMC_SELECT 0x4 /* Which bit position the event starts at. */
#define MIPS24K_PMC_OFFSET 2   /* Control registers are 0, 2, 4, etc. */
#define MIPS24K_PMC_MORE 0x800000 /* Test for more PMCs (bit 31) */

#ifdef _KERNEL
/* MD extension for 'struct pmc' */
struct pmc_md_mips24k_pmc {
	uint32_t	pm_mips24k_evsel;
};
#endif /* _KERNEL */

#endif /* _DEV_HWPMC_MIPS_H_ */


code:
/*-
 * Copyright (c) 2005, Joseph Koshy
 * 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 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 AUTHOR 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.
 *
 * $FreeBSD: release/9.0.0/sys/dev/hwpmc/hwpmc_pentium.h 184802 2008-11-09 17:37:54Z jkoshy $
 */

/* Machine dependent interfaces */

#ifndef _DEV_HWPMC_PENTIUM_H_
#define	_DEV_HWPMC_PENTIUM_H_ 1

/* Intel Pentium PMCs */

#define	PENTIUM_NPMCS	2
#define	PENTIUM_CESR_PC1		(1 << 25)
#define	PENTIUM_CESR_CC1_MASK		0x01C00000
#define	PENTIUM_CESR_TO_CC1(C)		(((C) & 0x07) << 22)
#define	PENTIUM_CESR_ES1_MASK		0x003F0000
#define	PENTIUM_CESR_TO_ES1(E)		(((E) & 0x3F) << 16)
#define	PENTIUM_CESR_PC0		(1 << 9)
#define	PENTIUM_CESR_CC0_MASK		0x000001C0
#define	PENTIUM_CESR_TO_CC0(C)		(((C) & 0x07) << 6)
#define	PENTIUM_CESR_ES0_MASK		0x0000003F
#define	PENTIUM_CESR_TO_ES0(E)		((E) & 0x3F)
#define	PENTIUM_CESR_RESERVED		0xFC00FC00

#define	PENTIUM_MSR_CESR		0x11
#define	PENTIUM_MSR_CTR0		0x12
#define	PENTIUM_MSR_CTR1		0x13

struct pmc_md_pentium_op_pmcallocate {
	uint32_t	pm_pentium_config;
};

#ifdef _KERNEL

/* MD extension for 'struct pmc' */
struct pmc_md_pentium_pmc {
	uint32_t	pm_pentium_cesr;
};

/*
 * Prototypes
 */

int	pmc_p5_initialize(struct pmc_mdep *_md, int _ncpus);
void	pmc_p5_finalize(struct pmc_mdep *_md);

#endif /* _KERNEL */
#endif /* _DEV_HWPMC_PENTIUM_H_ */