1265236Sken/*-
2265236Sken * Copyright (c) 2011-2014 LSI Corp.
3265236Sken * All rights reserved.
4265236Sken *
5265236Sken * Redistribution and use in source and binary forms, with or without
6265236Sken * modification, are permitted provided that the following conditions
7265236Sken * are met:
8265236Sken * 1. Redistributions of source code must retain the above copyright
9265236Sken *    notice, this list of conditions and the following disclaimer.
10265236Sken * 2. Redistributions in binary form must reproduce the above copyright
11265236Sken *    notice, this list of conditions and the following disclaimer in the
12265236Sken *    documentation and/or other materials provided with the distribution.
13265236Sken *
14265236Sken * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15265236Sken * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16265236Sken * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17265236Sken * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18265236Sken * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19265236Sken * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20265236Sken * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21265236Sken * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22265236Sken * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23265236Sken * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24265236Sken * SUCH DAMAGE.
25265236Sken *
26265236Sken * LSI MPT-Fusion Host Adapter FreeBSD
27265236Sken *
28265236Sken * $FreeBSD$
29265236Sken */
30265236Sken
31265236Skenstruct mpr_fw_event_work;
32265236Sken
33265236Skenstruct mprsas_lun {
34265236Sken	SLIST_ENTRY(mprsas_lun) lun_link;
35265236Sken	lun_id_t	lun_id;
36265236Sken	uint8_t		eedp_formatted;
37265236Sken	uint32_t	eedp_block_size;
38265236Sken	uint8_t		stop_at_shutdown;
39265236Sken};
40265236Sken
41265236Skenstruct mprsas_target {
42265236Sken	uint16_t	handle;
43265236Sken	uint8_t		linkrate;
44265236Sken	uint8_t		encl_level_valid;
45265236Sken	uint8_t		encl_level;
46265236Sken	char		connector_name[4];
47265236Sken	uint64_t	devname;
48265236Sken	uint32_t	devinfo;
49265236Sken	uint16_t	encl_handle;
50265236Sken	uint16_t	encl_slot;
51265236Sken	uint8_t		flags;
52265236Sken#define MPRSAS_TARGET_INABORT	(1 << 0)
53265236Sken#define MPRSAS_TARGET_INRESET	(1 << 1)
54265236Sken#define MPRSAS_TARGET_INDIAGRESET (1 << 2)
55265236Sken#define MPRSAS_TARGET_INREMOVAL	(1 << 3)
56265236Sken#define MPR_TARGET_FLAGS_RAID_COMPONENT (1 << 4)
57265236Sken#define MPR_TARGET_FLAGS_VOLUME         (1 << 5)
58265236Sken#define MPRSAS_TARGET_INRECOVERY (MPRSAS_TARGET_INABORT | \
59265236Sken    MPRSAS_TARGET_INRESET | MPRSAS_TARGET_INCHIPRESET)
60265236Sken
61265236Sken#define MPRSAS_TARGET_ADD       (1 << 29)
62265236Sken#define MPRSAS_TARGET_REMOVE    (1 << 30)
63265236Sken	uint16_t	tid;
64265236Sken	SLIST_HEAD(, mprsas_lun) luns;
65265236Sken	TAILQ_HEAD(, mpr_command) commands;
66265236Sken	struct mpr_command *tm;
67265236Sken	TAILQ_HEAD(, mpr_command) timedout_commands;
68265236Sken	uint16_t        exp_dev_handle;
69265236Sken	uint16_t        phy_num;
70265236Sken	uint64_t	sasaddr;
71265236Sken	uint16_t	parent_handle;
72265236Sken	uint64_t	parent_sasaddr;
73265236Sken	uint32_t	parent_devinfo;
74265236Sken	struct sysctl_ctx_list sysctl_ctx;
75265236Sken	struct sysctl_oid *sysctl_tree;
76265236Sken	TAILQ_ENTRY(mprsas_target) sysctl_link;
77265236Sken	uint64_t        issued;
78265236Sken	uint64_t        completed;
79265236Sken	unsigned int    outstanding;
80265236Sken	unsigned int    timeouts;
81265236Sken	unsigned int    aborts;
82265236Sken	unsigned int    logical_unit_resets;
83265236Sken	unsigned int    target_resets;
84265236Sken	uint8_t		scsi_req_desc_type;
85265236Sken};
86265236Sken
87265236Skenstruct mprsas_softc {
88265236Sken	struct mpr_softc	*sc;
89265236Sken	u_int			flags;
90265236Sken#define MPRSAS_IN_DISCOVERY	(1 << 0)
91265236Sken#define MPRSAS_IN_STARTUP	(1 << 1)
92265236Sken#define MPRSAS_DISCOVERY_TIMEOUT_PENDING	(1 << 2)
93265236Sken#define MPRSAS_QUEUE_FROZEN	(1 << 3)
94265236Sken#define	MPRSAS_SHUTDOWN		(1 << 4)
95265236Sken#define	MPRSAS_SCANTHREAD	(1 << 5)
96265236Sken	u_int			maxtargets;
97265236Sken	struct mprsas_target	*targets;
98265236Sken	struct cam_devq		*devq;
99265236Sken	struct cam_sim		*sim;
100265236Sken	struct cam_path		*path;
101265236Sken	struct intr_config_hook	sas_ich;
102265236Sken	struct callout		discovery_callout;
103265236Sken	struct mpr_event_handle	*mprsas_eh;
104265236Sken
105265236Sken	u_int                   startup_refcount;
106265236Sken	u_int                   tm_count;
107265236Sken	struct proc             *sysctl_proc;
108265236Sken
109265236Sken	struct taskqueue	*ev_tq;
110265236Sken	struct task		ev_task;
111265236Sken	TAILQ_HEAD(, mpr_fw_event_work)	ev_queue;
112265236Sken};
113265236Sken
114265236SkenMALLOC_DECLARE(M_MPRSAS);
115265236Sken
116265236Sken/*
117265236Sken * Abstracted so that the driver can be backwards and forwards compatible
118265236Sken * with future versions of CAM that will provide this functionality.
119265236Sken */
120265236Sken#define MPR_SET_LUN(lun, ccblun)	\
121265236Sken	mprsas_set_lun(lun, ccblun)
122265236Sken
123265236Skenstatic __inline int
124265236Skenmprsas_set_lun(uint8_t *lun, u_int ccblun)
125265236Sken{
126265236Sken	uint64_t *newlun;
127265236Sken
128265236Sken	newlun = (uint64_t *)lun;
129265236Sken	*newlun = 0;
130265236Sken	if (ccblun <= 0xff) {
131265236Sken		/* Peripheral device address method, LUN is 0 to 255 */
132265236Sken		lun[1] = ccblun;
133265236Sken	} else if (ccblun <= 0x3fff) {
134265236Sken		/* Flat space address method, LUN is <= 16383 */
135265236Sken		scsi_ulto2b(ccblun, lun);
136265236Sken		lun[0] |= 0x40;
137265236Sken	} else if (ccblun <= 0xffffff) {
138265236Sken		/* Extended flat space address method, LUN is <= 16777215 */
139265236Sken		scsi_ulto3b(ccblun, &lun[1]);
140265236Sken		/* Extended Flat space address method */
141265236Sken		lun[0] = 0xc0;
142265236Sken		/* Length = 1, i.e. LUN is 3 bytes long */
143265236Sken		lun[0] |= 0x10;
144265236Sken		/* Extended Address Method */
145265236Sken		lun[0] |= 0x02;
146265236Sken	} else {
147265236Sken		return (EINVAL);
148265236Sken	}
149265236Sken
150265236Sken	return (0);
151265236Sken}
152265236Sken
153265236Sken#define MPR_SET_SINGLE_LUN(req, lun)	\
154265236Skendo {					\
155265236Sken	bzero((req)->LUN, 8);		\
156265236Sken	(req)->LUN[1] = lun;		\
157265236Sken} while(0)
158265236Sken
159265236Skenvoid mprsas_rescan_target(struct mpr_softc *sc, struct mprsas_target *targ);
160265236Skenvoid mprsas_discovery_end(struct mprsas_softc *sassc);
161265236Skenvoid mprsas_startup_increment(struct mprsas_softc *sassc);
162265236Skenvoid mprsas_startup_decrement(struct mprsas_softc *sassc);
163265236Skenvoid mprsas_release_simq_reinit(struct mprsas_softc *sassc);
164265236Sken
165265236Skenstruct mpr_command * mprsas_alloc_tm(struct mpr_softc *sc);
166265236Skenvoid mprsas_free_tm(struct mpr_softc *sc, struct mpr_command *tm);
167265236Skenvoid mprsas_firmware_event_work(void *arg, int pending);
168265236Skenint mprsas_check_id(struct mprsas_softc *sassc, int id);
169