mfivar.h revision 233877
119370Spst/*-
298948Sobrien * Copyright (c) 2006 IronPort Systems
398948Sobrien * All rights reserved.
4130809Smarcel *
519370Spst * Redistribution and use in source and binary forms, with or without
619370Spst * modification, are permitted provided that the following conditions
798948Sobrien * are met:
819370Spst * 1. Redistributions of source code must retain the above copyright
998948Sobrien *    notice, this list of conditions and the following disclaimer.
1098948Sobrien * 2. Redistributions in binary form must reproduce the above copyright
1198948Sobrien *    notice, this list of conditions and the following disclaimer in the
1298948Sobrien *    documentation and/or other materials provided with the distribution.
1319370Spst *
1498948Sobrien * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1598948Sobrien * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1698948Sobrien * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1798948Sobrien * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
1819370Spst * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1998948Sobrien * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2098948Sobrien * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2198948Sobrien * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2298948Sobrien * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2319370Spst * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2419370Spst * SUCH DAMAGE.
2519370Spst */
2619370Spst/*-
2798948Sobrien * Copyright (c) 2007 LSI Corp.
2898948Sobrien * Copyright (c) 2007 Rajesh Prabhakaran.
2998948Sobrien * All rights reserved.
30130809Smarcel *
3119370Spst * Redistribution and use in source and binary forms, with or without
3219370Spst * modification, are permitted provided that the following conditions
3398948Sobrien * are met:
3419370Spst * 1. Redistributions of source code must retain the above copyright
3519370Spst *    notice, this list of conditions and the following disclaimer.
3619370Spst * 2. Redistributions in binary form must reproduce the above copyright
3719370Spst *    notice, this list of conditions and the following disclaimer in the
3819370Spst *    documentation and/or other materials provided with the distribution.
3919370Spst *
4098948Sobrien * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
4119370Spst * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
4298948Sobrien * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
4319370Spst * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
4498948Sobrien * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
4598948Sobrien * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
4698948Sobrien * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
4798948Sobrien * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
4819370Spst * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
4919370Spst * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
50130809Smarcel * SUCH DAMAGE.
51130809Smarcel */
5219370Spst
5319370Spst#ifndef _MFIVAR_H
5419370Spst#define _MFIVAR_H
5519370Spst
5619370Spst#include <sys/cdefs.h>
5719370Spst__FBSDID("$FreeBSD: head/sys/dev/mfi/mfivar.h 233877 2012-04-04 16:15:40Z jkim $");
5898948Sobrien
5998948Sobrien#include <sys/lock.h>
6098948Sobrien#include <sys/sx.h>
6119370Spst
6219370Spst#include <sys/types.h>
6319370Spst#include <sys/taskqueue.h>
6498948Sobrien
6598948Sobrien/*
6619370Spst * SCSI structures and definitions are used from here, but no linking
6798948Sobrien * requirements are made to CAM.
6819370Spst */
6998948Sobrien#include <cam/scsi/scsi_all.h>
7098948Sobrien
7146283Sdfrstruct mfi_hwcomms {
7246283Sdfr	uint32_t		hw_pi;
7319370Spst	uint32_t		hw_ci;
7419370Spst	uint32_t		hw_reply_q[1];
7519370Spst};
7619370Spst#define	MEGASAS_MAX_NAME	32
7719370Spst#define	MEGASAS_VERSION		"4.23"
7819370Spst
7919370Spststruct mfi_softc;
8019370Spststruct disk;
8119370Spststruct ccb_hdr;
8219370Spst
8319370Spststruct mfi_command {
8419370Spst	TAILQ_ENTRY(mfi_command) cm_link;
85130809Smarcel	time_t			cm_timestamp;
8619370Spst	struct mfi_softc	*cm_sc;
8719370Spst	union mfi_frame		*cm_frame;
8819370Spst	bus_addr_t		cm_frame_busaddr;
8919370Spst	struct mfi_sense	*cm_sense;
9019370Spst	bus_addr_t		cm_sense_busaddr;
9198948Sobrien	bus_dmamap_t		cm_dmamap;
9219370Spst	union mfi_sgl		*cm_sg;
9319370Spst	void			*cm_data;
9419370Spst	int			cm_len;
9546283Sdfr	int			cm_stp_len;
9619370Spst	int			cm_total_frame_size;
9719370Spst	int			cm_extra_frames;
9819370Spst	int			cm_flags;
9919370Spst#define MFI_CMD_MAPPED		(1<<0)
10019370Spst#define MFI_CMD_DATAIN		(1<<1)
10119370Spst#define MFI_CMD_DATAOUT		(1<<2)
10219370Spst#define MFI_CMD_COMPLETED	(1<<3)
10319370Spst#define MFI_CMD_POLLED		(1<<4)
10419370Spst#define MFI_ON_MFIQ_FREE	(1<<5)
10519370Spst#define MFI_ON_MFIQ_READY	(1<<6)
10619370Spst#define MFI_ON_MFIQ_BUSY	(1<<7)
10719370Spst#define MFI_ON_MFIQ_MASK	((1<<5)|(1<<6)|(1<<7))
10819370Spst	int			cm_aen_abort;
10919370Spst	uint8_t			retry_for_fw_reset;
11098948Sobrien	void			(* cm_complete)(struct mfi_command *cm);
11119370Spst	void			*cm_private;
11219370Spst	int			cm_index;
11319370Spst	int			cm_error;
11419370Spst};
11519370Spst
11698948Sobrienstruct mfi_disk {
11719370Spst	TAILQ_ENTRY(mfi_disk)	ld_link;
11819370Spst	device_t	ld_dev;
11919370Spst	int		ld_id;
12019370Spst	int		ld_unit;
12119370Spst	struct mfi_softc *ld_controller;
12219370Spst	struct mfi_ld_info	*ld_info;
12319370Spst	struct disk	*ld_disk;
12419370Spst	int		ld_flags;
12598948Sobrien#define MFI_DISK_FLAGS_OPEN	0x01
12619370Spst#define	MFI_DISK_FLAGS_DISABLED	0x02
12719370Spst};
12819370Spst
12919370Spststruct mfi_system_pd {
13019370Spst	TAILQ_ENTRY(mfi_system_pd) pd_link;
13119370Spst	device_t	pd_dev;
13219370Spst	int		pd_id;
13319370Spst	int		pd_unit;
13419370Spst	struct mfi_softc *pd_controller;
13519370Spst	struct mfi_pd_info *pd_info;
13619370Spst	struct disk	*pd_disk;
13719370Spst	int		pd_flags;
13819370Spst};
13946283Sdfr
14046283Sdfrstruct mfi_evt_queue_elm {
14198948Sobrien	TAILQ_ENTRY(mfi_evt_queue_elm)	link;
14298948Sobrien	struct mfi_evt_detail		detail;
14398948Sobrien};
14498948Sobrien
14598948Sobrienstruct mfi_aen {
14646283Sdfr	TAILQ_ENTRY(mfi_aen) aen_link;
14798948Sobrien	struct proc			*p;
14898948Sobrien};
14998948Sobrien
150130809Smarcelstruct mfi_skinny_dma_info {
15198948Sobrien	bus_dma_tag_t			dmat[514];
15298948Sobrien	bus_dmamap_t			dmamap[514];
15398948Sobrien	uint32_t			mem[514];
15498948Sobrien	int				noofmaps;
15598948Sobrien};
15698948Sobrien
15798948Sobrienstruct megasas_sge
15898948Sobrien{
15998948Sobrien	bus_addr_t			phys_addr;
16098948Sobrien	uint32_t			length;
16119370Spst};
16219370Spst
16319370Spststruct mfi_cmd_tbolt;
16419370Spst
16598948Sobrienstruct mfi_softc {
16698948Sobrien	device_t			mfi_dev;
16798948Sobrien	int				mfi_flags;
16898948Sobrien#define MFI_FLAGS_SG64		(1<<0)
16998948Sobrien#define MFI_FLAGS_QFRZN		(1<<1)
17098948Sobrien#define MFI_FLAGS_OPEN		(1<<2)
17119370Spst#define MFI_FLAGS_STOP		(1<<3)
17219370Spst#define MFI_FLAGS_1064R		(1<<4)
17319370Spst#define MFI_FLAGS_1078		(1<<5)
174130809Smarcel#define MFI_FLAGS_GEN2		(1<<6)
175130809Smarcel#define MFI_FLAGS_SKINNY	(1<<7)
176130809Smarcel#define MFI_FLAGS_TBOLT		(1<<8)
177130809Smarcel	// Start: LSIP200113393
178130809Smarcel	bus_dma_tag_t			verbuf_h_dmat;
17919370Spst	bus_dmamap_t			verbuf_h_dmamap;
18019370Spst	uint32_t			verbuf_h_busaddr;
18119370Spst	uint32_t			*verbuf;
18219370Spst	void				*kbuff_arr[MAX_IOCTL_SGE];
18319370Spst	bus_dma_tag_t			mfi_kbuff_arr_dmat[2];
18498948Sobrien	bus_dmamap_t			mfi_kbuff_arr_dmamap[2];
18519370Spst	bus_addr_t			mfi_kbuff_arr_busaddr[2];
18619370Spst
18719370Spst	struct mfi_hwcomms		*mfi_comms;
18819370Spst	TAILQ_HEAD(,mfi_command)	mfi_free;
18919370Spst	TAILQ_HEAD(,mfi_command)	mfi_ready;
19019370Spst	TAILQ_HEAD(BUSYQ,mfi_command)	mfi_busy;
19198948Sobrien	struct bio_queue_head		mfi_bioq;
19219370Spst	struct mfi_qstat		mfi_qstat[MFIQ_COUNT];
19398948Sobrien
19498948Sobrien	struct resource			*mfi_regs_resource;
19519370Spst	bus_space_handle_t		mfi_bhandle;
19698948Sobrien	bus_space_tag_t			mfi_btag;
19719370Spst	int				mfi_regs_rid;
19898948Sobrien
19998948Sobrien	bus_dma_tag_t			mfi_parent_dmat;
20098948Sobrien	bus_dma_tag_t			mfi_buffer_dmat;
20119370Spst
20298948Sobrien	bus_dma_tag_t			mfi_comms_dmat;
20319370Spst	bus_dmamap_t			mfi_comms_dmamap;
20498948Sobrien	bus_addr_t			mfi_comms_busaddr;
20598948Sobrien
20619370Spst	bus_dma_tag_t			mfi_frames_dmat;
20798948Sobrien	bus_dmamap_t			mfi_frames_dmamap;
20819370Spst	bus_addr_t			mfi_frames_busaddr;
20919370Spst	union mfi_frame			*mfi_frames;
21019370Spst
21119370Spst	bus_dma_tag_t			mfi_tb_init_dmat;
21298948Sobrien	bus_dmamap_t			mfi_tb_init_dmamap;
21398948Sobrien	bus_addr_t			mfi_tb_init_busaddr;
21419370Spst	bus_addr_t			mfi_tb_ioc_init_busaddr;
21519370Spst	union mfi_frame			*mfi_tb_init;
21698948Sobrien
21719370Spst	TAILQ_HEAD(,mfi_evt_queue_elm)	mfi_evt_queue;
21846283Sdfr	struct task			mfi_evt_task;
21946283Sdfr	TAILQ_HEAD(,mfi_aen)		mfi_aen_pids;
22098948Sobrien	struct mfi_command		*mfi_aen_cm;
22146283Sdfr	struct mfi_command		*mfi_skinny_cm;
22246283Sdfr	uint32_t			mfi_aen_triggered;
22346283Sdfr	uint32_t			mfi_poll_waiting;
22446283Sdfr	uint32_t			mfi_boot_seq_num;
22546283Sdfr	struct selinfo			mfi_select;
22646283Sdfr	int				mfi_delete_busy_volumes;
22746283Sdfr	int				mfi_keep_deleted_volumes;
22846283Sdfr	int				mfi_detaching;
22946283Sdfr
23046283Sdfr	bus_dma_tag_t			mfi_sense_dmat;
23146283Sdfr	bus_dmamap_t			mfi_sense_dmamap;
23246283Sdfr	uint32_t			mfi_sense_busaddr;
23398948Sobrien	struct mfi_sense		*mfi_sense;
23498948Sobrien
23598948Sobrien	struct resource			*mfi_irq;
23646283Sdfr	void				*mfi_intr;
23719370Spst	int				mfi_irq_rid;
23819370Spst
23919370Spst	struct intr_config_hook		mfi_ich;
24098948Sobrien	eventhandler_tag		eh;
24198948Sobrien	/* OCR flags */
24298948Sobrien	uint8_t adpreset;
24319370Spst	uint8_t issuepend_done;
24498948Sobrien	uint8_t disableOnlineCtrlReset;
24598948Sobrien	uint32_t mfiStatus;
24698948Sobrien	uint32_t last_seq_num;
24798948Sobrien	uint32_t volatile hw_crit_error;
24898948Sobrien
24998948Sobrien	/*
25019370Spst	 * Allocation for the command array.  Used as an indexable array to
25119370Spst	 * recover completed commands.
25219370Spst	 */
25398948Sobrien	struct mfi_command		*mfi_commands;
25419370Spst	/*
25519370Spst	 * How many commands were actually allocated
25619370Spst	 */
25719370Spst	int				mfi_total_cmds;
25898948Sobrien	/*
25919370Spst	 * How many commands the firmware can handle.  Also how big the reply
26046283Sdfr	 * queue is, minus 1.
26146283Sdfr	 */
26298948Sobrien	int				mfi_max_fw_cmds;
26398948Sobrien	/*
26446283Sdfr	 * How many S/G elements we'll ever actually use
26546283Sdfr	 */
26698948Sobrien	int				mfi_max_sge;
26746283Sdfr	/*
26819370Spst	 * How many bytes a compound frame is, including all of the extra frames
26919370Spst	 * that are used for S/G elements.
27019370Spst	 */
27198948Sobrien	int				mfi_cmd_size;
27298948Sobrien	/*
27319370Spst	 * How large an S/G element is.  Used to calculate the number of single
27419370Spst	 * frames in a command.
27519370Spst	 */
27619370Spst	int				mfi_sge_size;
27798948Sobrien	/*
27898948Sobrien	 * Max number of sectors that the firmware allows
27919370Spst	 */
28098948Sobrien	uint32_t			mfi_max_io;
28198948Sobrien
28298948Sobrien	TAILQ_HEAD(,mfi_disk)		mfi_ld_tqh;
28398948Sobrien	TAILQ_HEAD(,mfi_system_pd)	mfi_syspd_tqh;
28498948Sobrien	eventhandler_tag		mfi_eh;
28546283Sdfr	struct cdev			*mfi_cdev;
28619370Spst
28798948Sobrien	TAILQ_HEAD(, ccb_hdr)		mfi_cam_ccbq;
28846283Sdfr	struct mfi_command *		(* mfi_cam_start)(void *);
28919370Spst	struct callout			mfi_watchdog_callout;
29019370Spst	struct mtx			mfi_io_lock;
29119370Spst	struct sx			mfi_config_lock;
29298948Sobrien
29319370Spst	/* Controller type specific interfaces */
29419370Spst	void	(*mfi_enable_intr)(struct mfi_softc *sc);
29598948Sobrien	void	(*mfi_disable_intr)(struct mfi_softc *sc);
29698948Sobrien	int32_t	(*mfi_read_fw_status)(struct mfi_softc *sc);
29798948Sobrien	int	(*mfi_check_clear_intr)(struct mfi_softc *sc);
29898948Sobrien	void	(*mfi_issue_cmd)(struct mfi_softc *sc, bus_addr_t bus_add,
29998948Sobrien		    uint32_t frame_cnt);
30098948Sobrien	int	(*mfi_adp_reset)(struct mfi_softc *sc);
30198948Sobrien	int	(*mfi_adp_check_reset)(struct mfi_softc *sc);
30298948Sobrien
30398948Sobrien	/* ThunderBolt */
30498948Sobrien	uint32_t			mfi_tbolt;
30598948Sobrien	uint32_t			MFA_enabled;
30619370Spst	uint64_t			map_id;
30798948Sobrien	struct mfi_command 		*map_update_cmd;
30898948Sobrien	/* Single Reply structure size */
30998948Sobrien	uint16_t			reply_size;
31098948Sobrien	/* Singler message size. */
31198948Sobrien	uint16_t			raid_io_msg_size;
31219370Spst	TAILQ_HEAD(TB, mfi_cmd_tbolt)	mfi_cmd_tbolt_tqh;
31398948Sobrien	/* ThunderBolt base contiguous memory mapping. */
31419370Spst	bus_dma_tag_t			mfi_tb_dmat;
31519370Spst	bus_dmamap_t			mfi_tb_dmamap;
31619370Spst	bus_addr_t			mfi_tb_busaddr;
31719370Spst	/* ThunderBolt Contiguous DMA memory Mapping */
31819370Spst	uint8_t	*			request_message_pool;
31919370Spst	uint8_t *			request_message_pool_align;
32098948Sobrien	uint8_t *			request_desc_pool;
32119370Spst	//uint32_t			request_desc_busaddr;
32219370Spst	bus_addr_t			request_msg_busaddr;
32319370Spst	bus_addr_t			reply_frame_busaddr;
32498948Sobrien	bus_addr_t			sg_frame_busaddr;
32598948Sobrien	/* ThunderBolt IOC Init Descriptor */
32698948Sobrien	bus_dma_tag_t			mfi_tb_ioc_init_dmat;
32798948Sobrien	bus_dmamap_t			mfi_tb_ioc_init_dmamap;
32819370Spst	uint8_t *			mfi_tb_ioc_init_desc;
32919370Spst	struct mfi_cmd_tbolt		**mfi_cmd_pool_tbolt;
33019370Spst	/* Virtual address of reply Frame Pool */
33119370Spst	struct mfi_mpi2_reply_header*	reply_frame_pool;
33219370Spst	struct mfi_mpi2_reply_header*	reply_frame_pool_align;
33319370Spst
33419370Spst	/* Last reply frame address */
33519370Spst	uint8_t *			reply_pool_limit;
33619370Spst	uint16_t			last_reply_idx;
33719370Spst	uint8_t				max_SGEs_in_chain_message;
33819370Spst	uint8_t				max_SGEs_in_main_message;
33919370Spst	uint8_t				chain_offset_value_for_main_message;
34098948Sobrien	uint8_t				chain_offset_value_for_mpt_ptmsg;
34198948Sobrien};
34298948Sobrien
34398948Sobrienunion desc_value {
34498948Sobrien	uint64_t	word;
34519370Spst	struct {
34619370Spst		uint32_t	low;
34798948Sobrien		uint32_t	high;
34898948Sobrien	}u;
34998948Sobrien};
35098948Sobrien
35198948Sobrien// TODO find the right definition
35219370Spst#define XXX_MFI_CMD_OP_INIT2                    0x9
35319370Spst/*
35419370Spst * Request descriptor types
35519370Spst */
35619370Spst#define MFI_REQ_DESCRIPT_FLAGS_LD_IO           0x7
35719370Spst#define MFI_REQ_DESCRIPT_FLAGS_MFA             0x1
35819370Spst#define MFI_REQ_DESCRIPT_FLAGS_TYPE_SHIFT	0x1
35919370Spst#define MFI_FUSION_FP_DEFAULT_TIMEOUT		0x14
36019370Spst#define MFI_LOAD_BALANCE_FLAG			0x1
36119370Spst#define MFI_DCMD_MBOX_PEND_FLAG			0x1
36219370Spst
36319370Spst//#define MR_PROT_INFO_TYPE_CONTROLLER	0x08
36419370Spst#define	MEGASAS_SCSI_VARIABLE_LENGTH_CMD	0x7f
36519370Spst#define MEGASAS_SCSI_SERVICE_ACTION_READ32	0x9
36619370Spst#define MEGASAS_SCSI_SERVICE_ACTION_WRITE32	0xB
36798948Sobrien#define	MEGASAS_SCSI_ADDL_CDB_LEN   		0x18
36898948Sobrien#define MEGASAS_RD_WR_PROTECT_CHECK_ALL		0x20
36998948Sobrien#define MEGASAS_RD_WR_PROTECT_CHECK_NONE	0x60
37098948Sobrien#define MEGASAS_EEDPBLOCKSIZE			512
37198948Sobrienstruct mfi_cmd_tbolt {
37298948Sobrien	union mfi_mpi2_request_descriptor *request_desc;
37398948Sobrien	struct mfi_mpi2_request_raid_scsi_io *io_request;
37498948Sobrien	bus_addr_t		io_request_phys_addr;
37598948Sobrien	bus_addr_t		sg_frame_phys_addr;
37698948Sobrien	bus_addr_t 		sense_phys_addr;
37798948Sobrien	MPI2_SGE_IO_UNION	*sg_frame;
37898948Sobrien	uint8_t			*sense;
37998948Sobrien	TAILQ_ENTRY(mfi_cmd_tbolt) next;
38098948Sobrien	/*
38198948Sobrien	 * Context for a MFI frame.
38298948Sobrien	 * Used to get the mfi cmd from list when a MFI cmd is completed
38398948Sobrien	 */
38498948Sobrien	uint32_t		sync_cmd_idx;
38598948Sobrien	uint16_t		index;
386130809Smarcel	uint8_t			status;
38798948Sobrien};
38819370Spst
38998948Sobrienextern int mfi_attach(struct mfi_softc *);
39098948Sobrienextern void mfi_free(struct mfi_softc *);
39119370Spstextern int mfi_shutdown(struct mfi_softc *);
39219370Spstextern void mfi_startio(struct mfi_softc *);
39319370Spstextern void mfi_disk_complete(struct bio *);
39498948Sobrienextern int mfi_disk_disable(struct mfi_disk *);
39519370Spstextern void mfi_disk_enable(struct mfi_disk *);
39698948Sobrienextern int mfi_dump_blocks(struct mfi_softc *, int id, uint64_t, void *, int);
39798948Sobrienextern int mfi_syspd_disable(struct mfi_system_pd *);
39898948Sobrienextern void mfi_syspd_enable(struct mfi_system_pd *);
39919370Spstextern int mfi_dump_syspd_blocks(struct mfi_softc *, int id, uint64_t, void *,
40098948Sobrien    int);
40198948Sobrienextern int mfi_transition_firmware(struct mfi_softc *sc);
40298948Sobrienextern int mfi_aen_setup(struct mfi_softc *sc, uint32_t seq_start);
40319370Spstextern void mfi_complete(struct mfi_softc *sc, struct mfi_command *cm);
40498948Sobrienextern int mfi_mapcmd(struct mfi_softc *sc,struct mfi_command *cm);
40519370Spstextern int mfi_wait_command(struct mfi_softc *sc, struct mfi_command *cm);
40698948Sobrienextern void mfi_tbolt_enable_intr_ppc(struct mfi_softc *);
40798948Sobrienextern void mfi_tbolt_disable_intr_ppc(struct mfi_softc *);
40819370Spstextern int32_t mfi_tbolt_read_fw_status_ppc(struct mfi_softc *);
40919370Spstextern int32_t mfi_tbolt_check_clear_intr_ppc(struct mfi_softc *);
41098948Sobrienextern void mfi_tbolt_issue_cmd_ppc(struct mfi_softc *, bus_addr_t, uint32_t);
41119370Spstextern void mfi_tbolt_init_globals(struct mfi_softc*);
41298948Sobrienextern uint32_t mfi_tbolt_get_memory_requirement(struct mfi_softc *);
41319370Spstextern int mfi_tbolt_init_desc_pool(struct mfi_softc *, uint8_t *, uint32_t);
41498948Sobrienextern int mfi_tbolt_init_MFI_queue(struct mfi_softc *);
41519370Spstextern void mfi_intr_tbolt(void *arg);
41698948Sobrienextern int mfi_tbolt_alloc_cmd(struct mfi_softc *sc);
41798948Sobrienextern int mfi_tbolt_send_frame(struct mfi_softc *sc, struct mfi_command *cm);
41819370Spstextern int mfi_tbolt_adp_reset(struct mfi_softc *sc);
41998948Sobrienextern int mfi_tbolt_reset(struct mfi_softc *sc);
42098948Sobrienextern int mfi_tbolt_sync_map_info(struct mfi_softc *sc);
42119370Spst
42298948Sobrien#define MFIQ_ADD(sc, qname)					\
42319370Spst	do {							\
42498948Sobrien		struct mfi_qstat *qs;				\
42519370Spst								\
42698948Sobrien		qs = &(sc)->mfi_qstat[qname];			\
42798948Sobrien		qs->q_length++;					\
42898948Sobrien		if (qs->q_length > qs->q_max)			\
42998948Sobrien			qs->q_max = qs->q_length;		\
43098948Sobrien	} while (0)
43198948Sobrien
432130809Smarcel#define MFIQ_REMOVE(sc, qname)	(sc)->mfi_qstat[qname].q_length--
433130809Smarcel
434130809Smarcel#define MFIQ_INIT(sc, qname)					\
435130809Smarcel	do {							\
436130809Smarcel		sc->mfi_qstat[qname].q_length = 0;		\
437130809Smarcel		sc->mfi_qstat[qname].q_max = 0;			\
438130809Smarcel	} while (0)
439130809Smarcel
44098948Sobrien#define MFIQ_COMMAND_QUEUE(name, index)					\
44119370Spst	static __inline void						\
44298948Sobrien	mfi_initq_ ## name (struct mfi_softc *sc)			\
44398948Sobrien	{								\
44498948Sobrien		TAILQ_INIT(&sc->mfi_ ## name);				\
44598948Sobrien		MFIQ_INIT(sc, index);					\
44698948Sobrien	}								\
44798948Sobrien	static __inline void						\
44819370Spst	mfi_enqueue_ ## name (struct mfi_command *cm)			\
44998948Sobrien	{								\
45098948Sobrien		if ((cm->cm_flags & MFI_ON_MFIQ_MASK) != 0) {		\
45119370Spst			printf("command %p is on another queue, "	\
45298948Sobrien			    "flags = %#x\n", cm, cm->cm_flags);		\
45319370Spst			panic("command is on another queue");		\
45498948Sobrien		}							\
45519370Spst		TAILQ_INSERT_TAIL(&cm->cm_sc->mfi_ ## name, cm, cm_link); \
45698948Sobrien		cm->cm_flags |= MFI_ON_ ## index;			\
45798948Sobrien		MFIQ_ADD(cm->cm_sc, index);				\
45898948Sobrien	}								\
45998948Sobrien	static __inline void						\
46019370Spst	mfi_requeue_ ## name (struct mfi_command *cm)			\
46198948Sobrien	{								\
46298948Sobrien		if ((cm->cm_flags & MFI_ON_MFIQ_MASK) != 0) {		\
46398948Sobrien			printf("command %p is on another queue, "	\
46419370Spst			    "flags = %#x\n", cm, cm->cm_flags);		\
46598948Sobrien			panic("command is on another queue");		\
46698948Sobrien		}							\
46798948Sobrien		TAILQ_INSERT_HEAD(&cm->cm_sc->mfi_ ## name, cm, cm_link); \
46898948Sobrien		cm->cm_flags |= MFI_ON_ ## index;			\
46998948Sobrien		MFIQ_ADD(cm->cm_sc, index);				\
47098948Sobrien	}								\
47119370Spst	static __inline struct mfi_command *				\
47298948Sobrien	mfi_dequeue_ ## name (struct mfi_softc *sc)			\
47398948Sobrien	{								\
47419370Spst		struct mfi_command *cm;					\
47598948Sobrien									\
47619370Spst		if ((cm = TAILQ_FIRST(&sc->mfi_ ## name)) != NULL) {	\
47719370Spst			if ((cm->cm_flags & MFI_ON_ ## index) == 0) {	\
47898948Sobrien				printf("command %p not in queue, "	\
47998948Sobrien				    "flags = %#x, bit = %#x\n", cm,	\
48098948Sobrien				    cm->cm_flags, MFI_ON_ ## index);	\
48198948Sobrien				panic("command not in queue");		\
48298948Sobrien			}						\
48398948Sobrien			TAILQ_REMOVE(&sc->mfi_ ## name, cm, cm_link);	\
48419370Spst			cm->cm_flags &= ~MFI_ON_ ## index;		\
48598948Sobrien			MFIQ_REMOVE(sc, index);				\
48698948Sobrien		}							\
487130809Smarcel		return (cm);						\
48898948Sobrien	}								\
48998948Sobrien	static __inline void						\
49098948Sobrien	mfi_remove_ ## name (struct mfi_command *cm)			\
49198948Sobrien	{								\
49298948Sobrien		if ((cm->cm_flags & MFI_ON_ ## index) == 0) {		\
49319370Spst			printf("command %p not in queue, flags = %#x, " \
49419370Spst			    "bit = %#x\n", cm, cm->cm_flags,		\
495130809Smarcel			    MFI_ON_ ## index);				\
496130809Smarcel			panic("command not in queue");			\
497130809Smarcel		}							\
498130809Smarcel		TAILQ_REMOVE(&cm->cm_sc->mfi_ ## name, cm, cm_link);	\
499130809Smarcel		cm->cm_flags &= ~MFI_ON_ ## index;			\
500130809Smarcel		MFIQ_REMOVE(cm->cm_sc, index);				\
501130809Smarcel	}								\
502130809Smarcelstruct hack
503130809Smarcel
504130809SmarcelMFIQ_COMMAND_QUEUE(free, MFIQ_FREE);
505130809SmarcelMFIQ_COMMAND_QUEUE(ready, MFIQ_READY);
506130809SmarcelMFIQ_COMMAND_QUEUE(busy, MFIQ_BUSY);
507130809Smarcel
508130809Smarcelstatic __inline void
509130809Smarcelmfi_initq_bio(struct mfi_softc *sc)
510130809Smarcel{
511130809Smarcel	bioq_init(&sc->mfi_bioq);
512130809Smarcel	MFIQ_INIT(sc, MFIQ_BIO);
51398948Sobrien}
51498948Sobrien
51598948Sobrienstatic __inline void
51698948Sobrienmfi_enqueue_bio(struct mfi_softc *sc, struct bio *bp)
51798948Sobrien{
51819370Spst	bioq_insert_tail(&sc->mfi_bioq, bp);
519130809Smarcel	MFIQ_ADD(sc, MFIQ_BIO);
52098948Sobrien}
52119370Spst
52298948Sobrienstatic __inline struct bio *
52398948Sobrienmfi_dequeue_bio(struct mfi_softc *sc)
52419370Spst{
52519370Spst	struct bio *bp;
52698948Sobrien
52798948Sobrien	if ((bp = bioq_first(&sc->mfi_bioq)) != NULL) {
52898948Sobrien		bioq_remove(&sc->mfi_bioq, bp);
52919370Spst		MFIQ_REMOVE(sc, MFIQ_BIO);
53098948Sobrien	}
53198948Sobrien	return (bp);
53298948Sobrien}
53398948Sobrien
53498948Sobrien/*
535130809Smarcel * This is from the original scsi_extract_sense() in CAM.  It's copied
536130809Smarcel * here because CAM now uses a non-inline version that follows more complex
53798948Sobrien * additions to the SPC spec, and we don't want to force a dependency on
53898948Sobrien * the CAM module for such a trivial action.
53998948Sobrien */
54019370Spststatic __inline void
54119370Spstmfi_extract_sense(struct scsi_sense_data_fixed *sense,
54298948Sobrien    int *error_code, int *sense_key, int *asc, int *ascq)
54398948Sobrien{
54498948Sobrien
54598948Sobrien	*error_code = sense->error_code & SSD_ERRCODE;
54698948Sobrien	*sense_key = sense->flags & SSD_KEY;
54798948Sobrien	*asc = (sense->extra_len >= 5) ? sense->add_sense_code : 0;
54819370Spst	*ascq = (sense->extra_len >= 6) ? sense->add_sense_code_qual : 0;
54998948Sobrien}
55098948Sobrien
55119370Spststatic __inline void
55298948Sobrienmfi_print_sense(struct mfi_softc *sc, void *sense)
55398948Sobrien{
55498948Sobrien	int error, key, asc, ascq;
55598948Sobrien
55698948Sobrien	mfi_extract_sense((struct scsi_sense_data_fixed *)sense,
55798948Sobrien	    &error, &key, &asc, &ascq);
55898948Sobrien	device_printf(sc->mfi_dev, "sense error %d, sense_key %d, "
55998948Sobrien	    "asc %d, ascq %d\n", error, key, asc, ascq);
56098948Sobrien}
56198948Sobrien
56298948Sobrien
56319370Spst#define MFI_WRITE4(sc, reg, val)	bus_space_write_4((sc)->mfi_btag, \
56419370Spst	sc->mfi_bhandle, (reg), (val))
56598948Sobrien#define MFI_READ4(sc, reg)		bus_space_read_4((sc)->mfi_btag, \
56698948Sobrien	(sc)->mfi_bhandle, (reg))
56798948Sobrien#define MFI_WRITE2(sc, reg, val)	bus_space_write_2((sc)->mfi_btag, \
56819370Spst	sc->mfi_bhandle, (reg), (val))
56998948Sobrien#define MFI_READ2(sc, reg)		bus_space_read_2((sc)->mfi_btag, \
57098948Sobrien	(sc)->mfi_bhandle, (reg))
57198948Sobrien#define MFI_WRITE1(sc, reg, val)	bus_space_write_1((sc)->mfi_btag, \
57298948Sobrien	sc->mfi_bhandle, (reg), (val))
57398948Sobrien#define MFI_READ1(sc, reg)		bus_space_read_1((sc)->mfi_btag, \
57498948Sobrien	(sc)->mfi_bhandle, (reg))
57519370Spst
57619370SpstMALLOC_DECLARE(M_MFIBUF);
57798948SobrienSYSCTL_DECL(_hw_mfi);
57819370Spst
57998948Sobrien#define MFI_RESET_WAIT_TIME 180
58098948Sobrien#define MFI_CMD_TIMEOUT 30
58119370Spst#define MFI_SYS_PD_IO	0
58298948Sobrien#define MFI_LD_IO	1
58398948Sobrien#define MFI_SKINNY_MEMORY 0x02000000
58498948Sobrien#define MFI_MAXPHYS (128 * 1024)
58598948Sobrien
58698948Sobrien#ifdef MFI_DEBUG
58719370Spstextern void mfi_print_cmd(struct mfi_command *cm);
58898948Sobrienextern void mfi_dump_cmds(struct mfi_softc *sc);
58998948Sobrienextern void mfi_validate_sg(struct mfi_softc *, struct mfi_command *, const char *, int );
59098948Sobrien#define MFI_PRINT_CMD(cm)	mfi_print_cmd(cm)
59198948Sobrien#define MFI_DUMP_CMDS(sc)	mfi_dump_cmds(sc)
59219370Spst#define MFI_VALIDATE_CMD(sc, cm) mfi_validate_sg(sc, cm, __FUNCTION__, __LINE__)
59319370Spst#else
59419370Spst#define MFI_PRINT_CMD(cm)
59598948Sobrien#define MFI_DUMP_CMDS(sc)
59619370Spst#define MFI_VALIDATE_CMD(sc, cm)
59798948Sobrien#endif
59898948Sobrien
59998948Sobrienextern void mfi_release_command(struct mfi_command *cm);
60098948Sobrien
60119370Spst#endif /* _MFIVAR_H */
60298948Sobrien