1/* $OpenBSD: mfii.c,v 1.91 2024/05/24 06:02:58 jsg Exp $ */
2
3/*
4 * Copyright (c) 2012 David Gwynne <dlg@openbsd.org>
5 *
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18
19#include "bio.h"
20
21#include <sys/param.h>
22#include <sys/systm.h>
23#include <sys/malloc.h>
24#include <sys/device.h>
25#include <sys/dkio.h>
26#include <sys/pool.h>
27#include <sys/task.h>
28#include <sys/atomic.h>
29#include <sys/sensors.h>
30#include <sys/rwlock.h>
31#include <sys/smr.h>
32
33#include <dev/biovar.h>
34#include <dev/pci/pcidevs.h>
35#include <dev/pci/pcivar.h>
36
37#include <machine/bus.h>
38
39#include <scsi/scsi_all.h>
40#include <scsi/scsi_disk.h>
41#include <scsi/scsiconf.h>
42
43#include <dev/ic/mfireg.h>
44#include <dev/pci/mpiireg.h>
45
46#define	MFII_BAR		0x14
47#define MFII_BAR_35		0x10
48#define	MFII_PCI_MEMSIZE	0x2000 /* 8k */
49
50#define MFII_OSTS_INTR_VALID	0x00000009
51#define MFII_RPI		0x6c /* reply post host index */
52#define MFII_OSP2		0xb4 /* outbound scratch pad 2 */
53#define MFII_OSP3		0xb8 /* outbound scratch pad 3 */
54
55#define MFII_REQ_TYPE_SCSI	MPII_REQ_DESCR_SCSI_IO
56#define MFII_REQ_TYPE_LDIO	(0x7 << 1)
57#define MFII_REQ_TYPE_MFA	(0x1 << 1)
58#define MFII_REQ_TYPE_NO_LOCK	(0x2 << 1)
59#define MFII_REQ_TYPE_HI_PRI	(0x6 << 1)
60
61#define MFII_REQ_MFA(_a)	htole64((_a) | MFII_REQ_TYPE_MFA)
62
63#define MFII_FUNCTION_PASSTHRU_IO			(0xf0)
64#define MFII_FUNCTION_LDIO_REQUEST			(0xf1)
65
66#define MFII_MAX_CHAIN_UNIT	0x00400000
67#define MFII_MAX_CHAIN_MASK	0x000003E0
68#define MFII_MAX_CHAIN_SHIFT	5
69
70#define MFII_256K_IO		128
71#define MFII_1MB_IO		(MFII_256K_IO * 4)
72
73#define MFII_CHAIN_FRAME_MIN	1024
74
75struct mfii_request_descr {
76	u_int8_t	flags;
77	u_int8_t	msix_index;
78	u_int16_t	smid;
79
80	u_int16_t	lmid;
81	u_int16_t	dev_handle;
82} __packed;
83
84#define MFII_RAID_CTX_IO_TYPE_SYSPD	(0x1 << 4)
85#define MFII_RAID_CTX_TYPE_CUDA		(0x2 << 4)
86
87struct mfii_raid_context {
88	u_int8_t	type_nseg;
89	u_int8_t	_reserved1;
90	u_int16_t	timeout_value;
91
92	u_int16_t	reg_lock_flags;
93#define MFII_RAID_CTX_RL_FLAGS_SEQNO_EN	(0x08)
94#define MFII_RAID_CTX_RL_FLAGS_CPU0	(0x00)
95#define MFII_RAID_CTX_RL_FLAGS_CPU1	(0x10)
96#define MFII_RAID_CTX_RL_FLAGS_CUDA	(0x80)
97
98#define MFII_RAID_CTX_ROUTING_FLAGS_SQN	(1 << 4)
99#define MFII_RAID_CTX_ROUTING_FLAGS_CPU0 0
100	u_int16_t	virtual_disk_target_id;
101
102	u_int64_t	reg_lock_row_lba;
103
104	u_int32_t	reg_lock_length;
105
106	u_int16_t	next_lm_id;
107	u_int8_t	ex_status;
108	u_int8_t	status;
109
110	u_int8_t	raid_flags;
111	u_int8_t	num_sge;
112	u_int16_t	config_seq_num;
113
114	u_int8_t	span_arm;
115	u_int8_t	_reserved3[3];
116} __packed;
117
118struct mfii_sge {
119	u_int64_t	sg_addr;
120	u_int32_t	sg_len;
121	u_int16_t	_reserved;
122	u_int8_t	sg_next_chain_offset;
123	u_int8_t	sg_flags;
124} __packed;
125
126#define MFII_SGE_ADDR_MASK		(0x03)
127#define MFII_SGE_ADDR_SYSTEM		(0x00)
128#define MFII_SGE_ADDR_IOCDDR		(0x01)
129#define MFII_SGE_ADDR_IOCPLB		(0x02)
130#define MFII_SGE_ADDR_IOCPLBNTA		(0x03)
131#define MFII_SGE_END_OF_LIST		(0x40)
132#define MFII_SGE_CHAIN_ELEMENT		(0x80)
133
134#define MFII_REQUEST_SIZE	256
135
136#define MR_DCMD_LD_MAP_GET_INFO			0x0300e101
137
138#define MFII_MAX_ROW		32
139#define MFII_MAX_ARRAY		128
140
141struct mfii_array_map {
142	uint16_t		mam_pd[MFII_MAX_ROW];
143} __packed;
144
145struct mfii_dev_handle {
146	uint16_t		mdh_cur_handle;
147	uint8_t			mdh_valid;
148	uint8_t			mdh_reserved;
149	uint16_t		mdh_handle[2];
150} __packed;
151
152struct mfii_ld_map {
153	uint32_t		mlm_total_size;
154	uint32_t		mlm_reserved1[5];
155	uint32_t		mlm_num_lds;
156	uint32_t		mlm_reserved2;
157	uint8_t			mlm_tgtid_to_ld[2 * MFI_MAX_LD];
158	uint8_t			mlm_pd_timeout;
159	uint8_t			mlm_reserved3[7];
160	struct mfii_array_map	mlm_am[MFII_MAX_ARRAY];
161	struct mfii_dev_handle	mlm_dev_handle[MFI_MAX_PD];
162} __packed;
163
164struct mfii_task_mgmt {
165	union {
166		uint8_t			request[128];
167		struct mpii_msg_scsi_task_request
168					mpii_request;
169	} __packed __aligned(8);
170
171	union {
172		uint8_t			reply[128];
173		uint32_t		flags;
174#define MFII_TASK_MGMT_FLAGS_LD				(1 << 0)
175#define MFII_TASK_MGMT_FLAGS_PD				(1 << 1)
176		struct mpii_msg_scsi_task_reply
177					mpii_reply;
178	} __packed __aligned(8);
179} __packed __aligned(8);
180
181struct mfii_dmamem {
182	bus_dmamap_t		mdm_map;
183	bus_dma_segment_t	mdm_seg;
184	size_t			mdm_size;
185	caddr_t			mdm_kva;
186};
187#define MFII_DMA_MAP(_mdm)	((_mdm)->mdm_map)
188#define MFII_DMA_LEN(_mdm)	((_mdm)->mdm_size)
189#define MFII_DMA_DVA(_mdm)	((u_int64_t)(_mdm)->mdm_map->dm_segs[0].ds_addr)
190#define MFII_DMA_KVA(_mdm)	((void *)(_mdm)->mdm_kva)
191
192struct mfii_softc;
193
194struct mfii_ccb {
195	void			*ccb_request;
196	u_int64_t		ccb_request_dva;
197	bus_addr_t		ccb_request_offset;
198
199	void			*ccb_mfi;
200	u_int64_t		ccb_mfi_dva;
201	bus_addr_t		ccb_mfi_offset;
202
203	struct mfi_sense	*ccb_sense;
204	u_int64_t		ccb_sense_dva;
205	bus_addr_t		ccb_sense_offset;
206
207	struct mfii_sge		*ccb_sgl;
208	u_int64_t		ccb_sgl_dva;
209	bus_addr_t		ccb_sgl_offset;
210	u_int			ccb_sgl_len;
211
212	struct mfii_request_descr ccb_req;
213
214	bus_dmamap_t		ccb_dmamap;
215
216	/* data for sgl */
217	void			*ccb_data;
218	size_t			ccb_len;
219
220	int			ccb_direction;
221#define MFII_DATA_NONE			0
222#define MFII_DATA_IN			1
223#define MFII_DATA_OUT			2
224
225	void			*ccb_cookie;
226	void			(*ccb_done)(struct mfii_softc *,
227				    struct mfii_ccb *);
228
229	u_int32_t		ccb_flags;
230#define MFI_CCB_F_ERR			(1<<0)
231	u_int			ccb_smid;
232	u_int			ccb_refcnt;
233	SIMPLEQ_ENTRY(mfii_ccb)	ccb_link;
234};
235SIMPLEQ_HEAD(mfii_ccb_list, mfii_ccb);
236
237struct mfii_pd_dev_handles {
238	struct smr_entry	pd_smr;
239	uint16_t		pd_handles[MFI_MAX_PD];
240};
241
242struct mfii_pd_softc {
243	struct scsibus_softc	*pd_scsibus;
244	struct mfii_pd_dev_handles *pd_dev_handles;
245	uint8_t			pd_timeout;
246};
247
248struct mfii_iop {
249	int bar;
250	int num_sge_loc;
251#define MFII_IOP_NUM_SGE_LOC_ORIG	0
252#define MFII_IOP_NUM_SGE_LOC_35		1
253	u_int16_t ldio_ctx_reg_lock_flags;
254	u_int8_t ldio_req_type;
255	u_int8_t ldio_ctx_type_nseg;
256	u_int8_t sge_flag_chain;
257	u_int8_t sge_flag_eol;
258};
259
260struct mfii_softc {
261	struct device		sc_dev;
262	const struct mfii_iop	*sc_iop;
263
264	pci_chipset_tag_t	sc_pc;
265	pcitag_t		sc_tag;
266
267	bus_space_tag_t		sc_iot;
268	bus_space_handle_t	sc_ioh;
269	bus_size_t		sc_ios;
270	bus_dma_tag_t		sc_dmat;
271
272	void			*sc_ih;
273
274	struct mutex		sc_ccb_mtx;
275	struct mutex		sc_post_mtx;
276
277	u_int			sc_max_fw_cmds;
278	u_int			sc_max_cmds;
279	u_int			sc_max_sgl;
280
281	u_int			sc_reply_postq_depth;
282	u_int			sc_reply_postq_index;
283	struct mutex		sc_reply_postq_mtx;
284	struct mfii_dmamem	*sc_reply_postq;
285
286	struct mfii_dmamem	*sc_requests;
287	struct mfii_dmamem	*sc_mfi;
288	struct mfii_dmamem	*sc_sense;
289	struct mfii_dmamem	*sc_sgl;
290
291	struct mfii_ccb		*sc_ccb;
292	struct mfii_ccb_list	sc_ccb_freeq;
293
294	struct mfii_ccb		*sc_aen_ccb;
295	struct task		sc_aen_task;
296
297	struct mutex		sc_abort_mtx;
298	struct mfii_ccb_list	sc_abort_list;
299	struct task		sc_abort_task;
300
301	struct scsibus_softc	*sc_scsibus;
302	struct mfii_pd_softc	*sc_pd;
303	struct scsi_iopool	sc_iopool;
304
305	/* save some useful information for logical drives that is missing
306	 * in sc_ld_list
307	 */
308	struct {
309		char		ld_dev[16];	/* device name sd? */
310	}			sc_ld[MFI_MAX_LD];
311	int			sc_target_lds[MFI_MAX_LD];
312
313	/* scsi ioctl from sd device */
314	int			(*sc_ioctl)(struct device *, u_long, caddr_t);
315
316	/* bio */
317	struct mfi_conf		*sc_cfg;
318	struct mfi_ctrl_info	sc_info;
319	struct mfi_ld_list	sc_ld_list;
320	struct mfi_ld_details	*sc_ld_details; /* array to all logical disks */
321	int			sc_no_pd; /* used physical disks */
322	int			sc_ld_sz; /* sizeof sc_ld_details */
323
324	/* mgmt lock */
325	struct rwlock		sc_lock;
326
327	/* sensors */
328	struct ksensordev	sc_sensordev;
329	struct ksensor		*sc_bbu;
330	struct ksensor		*sc_bbu_status;
331	struct ksensor		*sc_sensors;
332};
333
334#ifdef MFII_DEBUG
335#define DPRINTF(x...)		do { if (mfii_debug) printf(x); } while(0)
336#define DNPRINTF(n,x...)	do { if (mfii_debug & n) printf(x); } while(0)
337#define	MFII_D_CMD		0x0001
338#define	MFII_D_INTR		0x0002
339#define	MFII_D_MISC		0x0004
340#define	MFII_D_DMA		0x0008
341#define	MFII_D_IOCTL		0x0010
342#define	MFII_D_RW		0x0020
343#define	MFII_D_MEM		0x0040
344#define	MFII_D_CCB		0x0080
345uint32_t	mfii_debug = 0
346/*		    | MFII_D_CMD */
347/*		    | MFII_D_INTR */
348		    | MFII_D_MISC
349/*		    | MFII_D_DMA */
350/*		    | MFII_D_IOCTL */
351/*		    | MFII_D_RW */
352/*		    | MFII_D_MEM */
353/*		    | MFII_D_CCB */
354		;
355#else
356#define DPRINTF(x...)
357#define DNPRINTF(n,x...)
358#endif
359
360int		mfii_match(struct device *, void *, void *);
361void		mfii_attach(struct device *, struct device *, void *);
362int		mfii_detach(struct device *, int);
363int		mfii_activate(struct device *, int);
364
365const struct cfattach mfii_ca = {
366	sizeof(struct mfii_softc),
367	mfii_match,
368	mfii_attach,
369	mfii_detach,
370	mfii_activate,
371};
372
373struct cfdriver mfii_cd = {
374	NULL,
375	"mfii",
376	DV_DULL
377};
378
379void		mfii_scsi_cmd(struct scsi_xfer *);
380void		mfii_scsi_cmd_done(struct mfii_softc *, struct mfii_ccb *);
381int		mfii_scsi_ioctl(struct scsi_link *, u_long, caddr_t, int);
382int		mfii_ioctl_cache(struct scsi_link *, u_long, struct dk_cache *);
383
384const struct scsi_adapter mfii_switch = {
385	mfii_scsi_cmd, NULL, NULL, NULL, mfii_scsi_ioctl
386};
387
388void		mfii_pd_scsi_cmd(struct scsi_xfer *);
389int		mfii_pd_scsi_probe(struct scsi_link *);
390
391const struct scsi_adapter mfii_pd_switch = {
392	mfii_pd_scsi_cmd, NULL, mfii_pd_scsi_probe, NULL, NULL,
393};
394
395#define DEVNAME(_sc)		((_sc)->sc_dev.dv_xname)
396
397u_int32_t		mfii_read(struct mfii_softc *, bus_size_t);
398void			mfii_write(struct mfii_softc *, bus_size_t, u_int32_t);
399
400struct mfii_dmamem *	mfii_dmamem_alloc(struct mfii_softc *, size_t);
401void			mfii_dmamem_free(struct mfii_softc *,
402			    struct mfii_dmamem *);
403
404void *			mfii_get_ccb(void *);
405void			mfii_put_ccb(void *, void *);
406int			mfii_init_ccb(struct mfii_softc *);
407void			mfii_scrub_ccb(struct mfii_ccb *);
408
409int			mfii_reset_hard(struct mfii_softc *);
410int			mfii_transition_firmware(struct mfii_softc *);
411int			mfii_initialise_firmware(struct mfii_softc *);
412int			mfii_get_info(struct mfii_softc *);
413int			mfii_syspd(struct mfii_softc *);
414
415void			mfii_start(struct mfii_softc *, struct mfii_ccb *);
416void			mfii_done(struct mfii_softc *, struct mfii_ccb *);
417int			mfii_poll(struct mfii_softc *, struct mfii_ccb *);
418void			mfii_poll_done(struct mfii_softc *, struct mfii_ccb *);
419int			mfii_exec(struct mfii_softc *, struct mfii_ccb *);
420void			mfii_exec_done(struct mfii_softc *, struct mfii_ccb *);
421int			mfii_my_intr(struct mfii_softc *);
422int			mfii_intr(void *);
423void			mfii_postq(struct mfii_softc *);
424
425int			mfii_load_ccb(struct mfii_softc *, struct mfii_ccb *,
426			    void *, int);
427int			mfii_load_mfa(struct mfii_softc *, struct mfii_ccb *,
428			    void *, int);
429
430int			mfii_mfa_poll(struct mfii_softc *, struct mfii_ccb *);
431
432int			mfii_mgmt(struct mfii_softc *, uint32_t,
433			    const union mfi_mbox *, void *, size_t, int);
434int			mfii_do_mgmt(struct mfii_softc *, struct mfii_ccb *,
435			    uint32_t, const union mfi_mbox *, void *, size_t,
436			    int);
437void			mfii_empty_done(struct mfii_softc *, struct mfii_ccb *);
438
439int			mfii_scsi_cmd_io(struct mfii_softc *,
440			    struct scsi_xfer *);
441int			mfii_scsi_cmd_cdb(struct mfii_softc *,
442			    struct scsi_xfer *);
443int			mfii_pd_scsi_cmd_cdb(struct mfii_softc *,
444			    struct scsi_xfer *);
445void			mfii_scsi_cmd_tmo(void *);
446
447int			mfii_dev_handles_update(struct mfii_softc *sc);
448void			mfii_dev_handles_smr(void *pd_arg);
449
450void			mfii_abort_task(void *);
451void			mfii_abort(struct mfii_softc *, struct mfii_ccb *,
452			    uint16_t, uint16_t, uint8_t, uint32_t);
453void			mfii_scsi_cmd_abort_done(struct mfii_softc *,
454			    struct mfii_ccb *);
455
456int			mfii_aen_register(struct mfii_softc *);
457void			mfii_aen_start(struct mfii_softc *, struct mfii_ccb *,
458			    struct mfii_dmamem *, uint32_t);
459void			mfii_aen_done(struct mfii_softc *, struct mfii_ccb *);
460void			mfii_aen(void *);
461void			mfii_aen_unregister(struct mfii_softc *);
462
463void			mfii_aen_pd_insert(struct mfii_softc *,
464			    const struct mfi_evtarg_pd_address *);
465void			mfii_aen_pd_remove(struct mfii_softc *,
466			    const struct mfi_evtarg_pd_address *);
467void			mfii_aen_pd_state_change(struct mfii_softc *,
468			    const struct mfi_evtarg_pd_state *);
469void			mfii_aen_ld_update(struct mfii_softc *);
470
471#if NBIO > 0
472int		mfii_ioctl(struct device *, u_long, caddr_t);
473int		mfii_bio_getitall(struct mfii_softc *);
474int		mfii_ioctl_inq(struct mfii_softc *, struct bioc_inq *);
475int		mfii_ioctl_vol(struct mfii_softc *, struct bioc_vol *);
476int		mfii_ioctl_disk(struct mfii_softc *, struct bioc_disk *);
477int		mfii_ioctl_alarm(struct mfii_softc *, struct bioc_alarm *);
478int		mfii_ioctl_blink(struct mfii_softc *sc, struct bioc_blink *);
479int		mfii_ioctl_setstate(struct mfii_softc *,
480		    struct bioc_setstate *);
481int		mfii_ioctl_patrol(struct mfii_softc *sc, struct bioc_patrol *);
482int		mfii_bio_hs(struct mfii_softc *, int, int, void *);
483
484#ifndef SMALL_KERNEL
485static const char *mfi_bbu_indicators[] = {
486	"pack missing",
487	"voltage low",
488	"temp high",
489	"charge active",
490	"discharge active",
491	"learn cycle req'd",
492	"learn cycle active",
493	"learn cycle failed",
494	"learn cycle timeout",
495	"I2C errors",
496	"replace pack",
497	"low capacity",
498	"periodic learn req'd"
499};
500
501void		mfii_init_ld_sensor(struct mfii_softc *, int);
502void		mfii_refresh_ld_sensor(struct mfii_softc *, int);
503int		mfii_create_sensors(struct mfii_softc *);
504void		mfii_refresh_sensors(void *);
505void		mfii_bbu(struct mfii_softc *);
506#endif /* SMALL_KERNEL */
507#endif /* NBIO > 0 */
508
509/*
510 * mfii boards support asynchronous (and non-polled) completion of
511 * dcmds by proxying them through a passthru mpii command that points
512 * at a dcmd frame. since the passthru command is submitted like
513 * the scsi commands using an SMID in the request descriptor,
514 * ccb_request memory * must contain the passthru command because
515 * that is what the SMID refers to. this means ccb_request cannot
516 * contain the dcmd. rather than allocating separate dma memory to
517 * hold the dcmd, we reuse the sense memory buffer for it.
518 */
519
520void			mfii_dcmd_start(struct mfii_softc *,
521			    struct mfii_ccb *);
522
523static inline void
524mfii_dcmd_scrub(struct mfii_ccb *ccb)
525{
526	memset(ccb->ccb_sense, 0, sizeof(*ccb->ccb_sense));
527}
528
529static inline struct mfi_dcmd_frame *
530mfii_dcmd_frame(struct mfii_ccb *ccb)
531{
532	CTASSERT(sizeof(struct mfi_dcmd_frame) <= sizeof(*ccb->ccb_sense));
533	return ((struct mfi_dcmd_frame *)ccb->ccb_sense);
534}
535
536static inline void
537mfii_dcmd_sync(struct mfii_softc *sc, struct mfii_ccb *ccb, int flags)
538{
539	bus_dmamap_sync(sc->sc_dmat, MFII_DMA_MAP(sc->sc_sense),
540	    ccb->ccb_sense_offset, sizeof(*ccb->ccb_sense), flags);
541}
542
543#define mfii_fw_state(_sc) mfii_read((_sc), MFI_OSP)
544
545const struct mfii_iop mfii_iop_thunderbolt = {
546	MFII_BAR,
547	MFII_IOP_NUM_SGE_LOC_ORIG,
548	0,
549	MFII_REQ_TYPE_LDIO,
550	0,
551	MFII_SGE_CHAIN_ELEMENT | MFII_SGE_ADDR_IOCPLBNTA,
552	0
553};
554
555/*
556 * a lot of these values depend on us not implementing fastpath yet.
557 */
558const struct mfii_iop mfii_iop_25 = {
559	MFII_BAR,
560	MFII_IOP_NUM_SGE_LOC_ORIG,
561	MFII_RAID_CTX_RL_FLAGS_CPU0, /* | MFII_RAID_CTX_RL_FLAGS_SEQNO_EN */
562	MFII_REQ_TYPE_NO_LOCK,
563	MFII_RAID_CTX_TYPE_CUDA | 0x1,
564	MFII_SGE_CHAIN_ELEMENT,
565	MFII_SGE_END_OF_LIST
566};
567
568const struct mfii_iop mfii_iop_35 = {
569	MFII_BAR_35,
570	MFII_IOP_NUM_SGE_LOC_35,
571	MFII_RAID_CTX_ROUTING_FLAGS_CPU0, /* | MFII_RAID_CTX_ROUTING_FLAGS_SQN */
572	MFII_REQ_TYPE_NO_LOCK,
573	MFII_RAID_CTX_TYPE_CUDA | 0x1,
574	MFII_SGE_CHAIN_ELEMENT,
575	MFII_SGE_END_OF_LIST
576};
577
578struct mfii_device {
579	pcireg_t		mpd_vendor;
580	pcireg_t		mpd_product;
581	const struct mfii_iop	*mpd_iop;
582};
583
584const struct mfii_device mfii_devices[] = {
585	{ PCI_VENDOR_SYMBIOS,	PCI_PRODUCT_SYMBIOS_MEGARAID_2208,
586	    &mfii_iop_thunderbolt },
587	{ PCI_VENDOR_SYMBIOS,	PCI_PRODUCT_SYMBIOS_MEGARAID_3008,
588	    &mfii_iop_25 },
589	{ PCI_VENDOR_SYMBIOS,	PCI_PRODUCT_SYMBIOS_MEGARAID_3108,
590	    &mfii_iop_25 },
591	{ PCI_VENDOR_SYMBIOS,	PCI_PRODUCT_SYMBIOS_MEGARAID_3404,
592	    &mfii_iop_35 },
593	{ PCI_VENDOR_SYMBIOS,	PCI_PRODUCT_SYMBIOS_MEGARAID_3504,
594	    &mfii_iop_35 },
595	{ PCI_VENDOR_SYMBIOS,	PCI_PRODUCT_SYMBIOS_MEGARAID_3408,
596	    &mfii_iop_35 },
597	{ PCI_VENDOR_SYMBIOS,	PCI_PRODUCT_SYMBIOS_MEGARAID_3508,
598	    &mfii_iop_35 },
599	{ PCI_VENDOR_SYMBIOS,	PCI_PRODUCT_SYMBIOS_MEGARAID_3416,
600	    &mfii_iop_35 },
601	{ PCI_VENDOR_SYMBIOS,	PCI_PRODUCT_SYMBIOS_MEGARAID_3516,
602	    &mfii_iop_35 },
603	{ PCI_VENDOR_SYMBIOS,   PCI_PRODUCT_SYMBIOS_MEGARAID_38XX,
604	    &mfii_iop_35 },
605	{ PCI_VENDOR_SYMBIOS,   PCI_PRODUCT_SYMBIOS_MEGARAID_38XX_2,
606	    &mfii_iop_35 },
607	{ PCI_VENDOR_SYMBIOS,   PCI_PRODUCT_SYMBIOS_MEGARAID_39XX,
608	    &mfii_iop_35 },
609	{ PCI_VENDOR_SYMBIOS,   PCI_PRODUCT_SYMBIOS_MEGARAID_39XX_2,
610	    &mfii_iop_35 }
611};
612
613const struct mfii_iop *mfii_find_iop(struct pci_attach_args *);
614
615const struct mfii_iop *
616mfii_find_iop(struct pci_attach_args *pa)
617{
618	const struct mfii_device *mpd;
619	int i;
620
621	for (i = 0; i < nitems(mfii_devices); i++) {
622		mpd = &mfii_devices[i];
623
624		if (mpd->mpd_vendor == PCI_VENDOR(pa->pa_id) &&
625		    mpd->mpd_product == PCI_PRODUCT(pa->pa_id))
626			return (mpd->mpd_iop);
627	}
628
629	return (NULL);
630}
631
632int
633mfii_match(struct device *parent, void *match, void *aux)
634{
635	return ((mfii_find_iop(aux) != NULL) ? 1 : 0);
636}
637
638void
639mfii_attach(struct device *parent, struct device *self, void *aux)
640{
641	struct mfii_softc *sc = (struct mfii_softc *)self;
642	struct pci_attach_args *pa = aux;
643	pcireg_t memtype;
644	pci_intr_handle_t ih;
645	struct scsibus_attach_args saa;
646	u_int32_t status, scpad2, scpad3;
647	int chain_frame_sz, nsge_in_io, nsge_in_chain, i;
648
649	/* init sc */
650	sc->sc_iop = mfii_find_iop(aux);
651	sc->sc_dmat = pa->pa_dmat;
652	SIMPLEQ_INIT(&sc->sc_ccb_freeq);
653	mtx_init(&sc->sc_ccb_mtx, IPL_BIO);
654	mtx_init(&sc->sc_post_mtx, IPL_BIO);
655	mtx_init(&sc->sc_reply_postq_mtx, IPL_BIO);
656	scsi_iopool_init(&sc->sc_iopool, sc, mfii_get_ccb, mfii_put_ccb);
657
658	rw_init(&sc->sc_lock, "mfii_lock");
659
660	sc->sc_aen_ccb = NULL;
661	task_set(&sc->sc_aen_task, mfii_aen, sc);
662
663	mtx_init(&sc->sc_abort_mtx, IPL_BIO);
664	SIMPLEQ_INIT(&sc->sc_abort_list);
665	task_set(&sc->sc_abort_task, mfii_abort_task, sc);
666
667	/* wire up the bus shizz */
668	memtype = pci_mapreg_type(pa->pa_pc, pa->pa_tag, sc->sc_iop->bar);
669	if (pci_mapreg_map(pa, sc->sc_iop->bar, memtype, 0,
670	    &sc->sc_iot, &sc->sc_ioh, NULL, &sc->sc_ios, MFII_PCI_MEMSIZE)) {
671		printf(": unable to map registers\n");
672		return;
673	}
674
675	/* disable interrupts */
676	mfii_write(sc, MFI_OMSK, 0xffffffff);
677
678	if (pci_intr_map_msi(pa, &ih) != 0 && pci_intr_map(pa, &ih) != 0) {
679		printf(": unable to map interrupt\n");
680		goto pci_unmap;
681	}
682	printf(": %s\n", pci_intr_string(pa->pa_pc, ih));
683
684	/* lets get started */
685	if (mfii_transition_firmware(sc))
686		goto pci_unmap;
687
688	/* determine max_cmds (refer to the Linux megaraid_sas driver) */
689	scpad3 = mfii_read(sc, MFII_OSP3);
690	status = mfii_fw_state(sc);
691	sc->sc_max_fw_cmds = scpad3 & MFI_STATE_MAXCMD_MASK;
692	if (sc->sc_max_fw_cmds == 0)
693		sc->sc_max_fw_cmds = status & MFI_STATE_MAXCMD_MASK;
694	/*
695	 * reduce max_cmds by 1 to ensure that the reply queue depth does not
696	 * exceed FW supplied max_fw_cmds.
697	 */
698	sc->sc_max_cmds = min(sc->sc_max_fw_cmds, 1024) - 1;
699
700	/* determine max_sgl (refer to the Linux megaraid_sas driver) */
701	scpad2 = mfii_read(sc, MFII_OSP2);
702	chain_frame_sz =
703		((scpad2 & MFII_MAX_CHAIN_MASK) >> MFII_MAX_CHAIN_SHIFT) *
704		((scpad2 & MFII_MAX_CHAIN_UNIT) ? MFII_1MB_IO : MFII_256K_IO);
705	if (chain_frame_sz < MFII_CHAIN_FRAME_MIN)
706		chain_frame_sz = MFII_CHAIN_FRAME_MIN;
707
708	nsge_in_io = (MFII_REQUEST_SIZE -
709		sizeof(struct mpii_msg_scsi_io) -
710		sizeof(struct mfii_raid_context)) / sizeof(struct mfii_sge);
711	nsge_in_chain = chain_frame_sz / sizeof(struct mfii_sge);
712
713	/* round down to nearest power of two */
714	sc->sc_max_sgl = 1;
715	while ((sc->sc_max_sgl << 1) <= (nsge_in_io + nsge_in_chain))
716		sc->sc_max_sgl <<= 1;
717
718	DNPRINTF(MFII_D_MISC, "%s: OSP 0x%08x, OSP2 0x%08x, OSP3 0x%08x\n",
719	    DEVNAME(sc), status, scpad2, scpad3);
720	DNPRINTF(MFII_D_MISC, "%s: max_fw_cmds %d, max_cmds %d\n",
721	    DEVNAME(sc), sc->sc_max_fw_cmds, sc->sc_max_cmds);
722	DNPRINTF(MFII_D_MISC, "%s: nsge_in_io %d, nsge_in_chain %d, "
723	    "max_sgl %d\n", DEVNAME(sc), nsge_in_io, nsge_in_chain,
724	    sc->sc_max_sgl);
725
726	/* sense memory */
727	CTASSERT(sizeof(struct mfi_sense) == MFI_SENSE_SIZE);
728	sc->sc_sense = mfii_dmamem_alloc(sc, sc->sc_max_cmds * MFI_SENSE_SIZE);
729	if (sc->sc_sense == NULL) {
730		printf("%s: unable to allocate sense memory\n", DEVNAME(sc));
731		goto pci_unmap;
732	}
733
734	/* reply post queue */
735	sc->sc_reply_postq_depth = roundup(sc->sc_max_fw_cmds, 16);
736
737	sc->sc_reply_postq = mfii_dmamem_alloc(sc,
738	    sc->sc_reply_postq_depth * sizeof(struct mpii_reply_descr));
739	if (sc->sc_reply_postq == NULL)
740		goto free_sense;
741
742	memset(MFII_DMA_KVA(sc->sc_reply_postq), 0xff,
743	    MFII_DMA_LEN(sc->sc_reply_postq));
744
745	/* MPII request frame array */
746	sc->sc_requests = mfii_dmamem_alloc(sc,
747	    MFII_REQUEST_SIZE * (sc->sc_max_cmds + 1));
748	if (sc->sc_requests == NULL)
749		goto free_reply_postq;
750
751	/* MFI command frame array */
752	sc->sc_mfi = mfii_dmamem_alloc(sc, sc->sc_max_cmds * MFI_FRAME_SIZE);
753	if (sc->sc_mfi == NULL)
754		goto free_requests;
755
756	/* MPII SGL array */
757	sc->sc_sgl = mfii_dmamem_alloc(sc, sc->sc_max_cmds *
758	    sizeof(struct mfii_sge) * sc->sc_max_sgl);
759	if (sc->sc_sgl == NULL)
760		goto free_mfi;
761
762	if (mfii_init_ccb(sc) != 0) {
763		printf("%s: could not init ccb list\n", DEVNAME(sc));
764		goto free_sgl;
765	}
766
767	/* kickstart firmware with all addresses and pointers */
768	if (mfii_initialise_firmware(sc) != 0) {
769		printf("%s: could not initialize firmware\n", DEVNAME(sc));
770		goto free_sgl;
771	}
772
773	if (mfii_get_info(sc) != 0) {
774		printf("%s: could not retrieve controller information\n",
775		    DEVNAME(sc));
776		goto free_sgl;
777	}
778
779	printf("%s: \"%s\", firmware %s", DEVNAME(sc),
780	    sc->sc_info.mci_product_name, sc->sc_info.mci_package_version);
781	if (letoh16(sc->sc_info.mci_memory_size) > 0)
782		printf(", %uMB cache", letoh16(sc->sc_info.mci_memory_size));
783	printf("\n");
784
785	sc->sc_ih = pci_intr_establish(sc->sc_pc, ih, IPL_BIO,
786	    mfii_intr, sc, DEVNAME(sc));
787	if (sc->sc_ih == NULL)
788		goto free_sgl;
789
790	saa.saa_adapter_softc = sc;
791	saa.saa_adapter = &mfii_switch;
792	saa.saa_adapter_target = SDEV_NO_ADAPTER_TARGET;
793	saa.saa_adapter_buswidth = sc->sc_info.mci_max_lds;
794	saa.saa_luns = 8;
795	saa.saa_openings = sc->sc_max_cmds;
796	saa.saa_pool = &sc->sc_iopool;
797	saa.saa_quirks = saa.saa_flags = 0;
798	saa.saa_wwpn = saa.saa_wwnn = 0;
799
800	sc->sc_scsibus = (struct scsibus_softc *)config_found(&sc->sc_dev, &saa,
801	    scsiprint);
802
803	mfii_syspd(sc);
804
805	if (mfii_aen_register(sc) != 0) {
806		/* error printed by mfii_aen_register */
807		goto intr_disestablish;
808	}
809
810	if (mfii_mgmt(sc, MR_DCMD_LD_GET_LIST, NULL, &sc->sc_ld_list,
811	    sizeof(sc->sc_ld_list), SCSI_DATA_IN) != 0) {
812		printf("%s: getting list of logical disks failed\n", DEVNAME(sc));
813		goto intr_disestablish;
814	}
815	memset(sc->sc_target_lds, -1, sizeof(sc->sc_target_lds));
816	for (i = 0; i < sc->sc_ld_list.mll_no_ld; i++) {
817		int target = sc->sc_ld_list.mll_list[i].mll_ld.mld_target;
818		sc->sc_target_lds[target] = i;
819	}
820
821	/* enable interrupts */
822	mfii_write(sc, MFI_OSTS, 0xffffffff);
823	mfii_write(sc, MFI_OMSK, ~MFII_OSTS_INTR_VALID);
824
825#if NBIO > 0
826	if (bio_register(&sc->sc_dev, mfii_ioctl) != 0)
827		panic("%s: controller registration failed", DEVNAME(sc));
828	else
829		sc->sc_ioctl = mfii_ioctl;
830
831#ifndef SMALL_KERNEL
832	if (mfii_create_sensors(sc) != 0)
833		printf("%s: unable to create sensors\n", DEVNAME(sc));
834#endif
835#endif /* NBIO > 0 */
836
837	return;
838intr_disestablish:
839	pci_intr_disestablish(sc->sc_pc, sc->sc_ih);
840free_sgl:
841	mfii_dmamem_free(sc, sc->sc_sgl);
842free_mfi:
843	mfii_dmamem_free(sc, sc->sc_mfi);
844free_requests:
845	mfii_dmamem_free(sc, sc->sc_requests);
846free_reply_postq:
847	mfii_dmamem_free(sc, sc->sc_reply_postq);
848free_sense:
849	mfii_dmamem_free(sc, sc->sc_sense);
850pci_unmap:
851	bus_space_unmap(sc->sc_iot, sc->sc_ioh, sc->sc_ios);
852}
853
854static inline uint16_t
855mfii_dev_handle(struct mfii_softc *sc, uint16_t target)
856{
857	struct mfii_pd_dev_handles *handles;
858	uint16_t handle;
859
860	smr_read_enter();
861	handles = SMR_PTR_GET(&sc->sc_pd->pd_dev_handles);
862	handle = handles->pd_handles[target];
863	smr_read_leave();
864
865	return (handle);
866}
867
868void
869mfii_dev_handles_smr(void *pd_arg)
870{
871	struct mfii_pd_dev_handles *handles = pd_arg;
872
873	free(handles, M_DEVBUF, sizeof(*handles));
874}
875
876int
877mfii_dev_handles_update(struct mfii_softc *sc)
878{
879	struct mfii_ld_map *lm;
880	struct mfii_pd_dev_handles *handles, *old_handles;
881	int i;
882	int rv = 0;
883
884	lm = malloc(sizeof(*lm), M_TEMP, M_WAITOK|M_ZERO);
885
886	rv = mfii_mgmt(sc, MR_DCMD_LD_MAP_GET_INFO, NULL, lm, sizeof(*lm),
887	    SCSI_DATA_IN|SCSI_NOSLEEP);
888
889	if (rv != 0) {
890		rv = EIO;
891		goto free_lm;
892	}
893
894	handles = malloc(sizeof(*handles), M_DEVBUF, M_WAITOK);
895	smr_init(&handles->pd_smr);
896	for (i = 0; i < MFI_MAX_PD; i++)
897		handles->pd_handles[i] = lm->mlm_dev_handle[i].mdh_cur_handle;
898
899	/* commit the updated info */
900	sc->sc_pd->pd_timeout = lm->mlm_pd_timeout;
901	old_handles = SMR_PTR_GET_LOCKED(&sc->sc_pd->pd_dev_handles);
902	SMR_PTR_SET_LOCKED(&sc->sc_pd->pd_dev_handles, handles);
903
904	if (old_handles != NULL)
905		smr_call(&old_handles->pd_smr, mfii_dev_handles_smr, old_handles);
906
907free_lm:
908	free(lm, M_TEMP, sizeof(*lm));
909
910	return (rv);
911}
912
913int
914mfii_syspd(struct mfii_softc *sc)
915{
916	struct scsibus_attach_args saa;
917
918	sc->sc_pd = malloc(sizeof(*sc->sc_pd), M_DEVBUF, M_WAITOK|M_ZERO);
919	if (sc->sc_pd == NULL)
920		return (1);
921
922	if (mfii_dev_handles_update(sc) != 0)
923		goto free_pdsc;
924
925	saa.saa_adapter =  &mfii_pd_switch;
926	saa.saa_adapter_softc = sc;
927	saa.saa_adapter_buswidth = MFI_MAX_PD;
928	saa.saa_adapter_target = SDEV_NO_ADAPTER_TARGET;
929	saa.saa_luns = 8;
930	saa.saa_openings = sc->sc_max_cmds - 1;
931	saa.saa_pool = &sc->sc_iopool;
932	saa.saa_quirks = saa.saa_flags = 0;
933	saa.saa_wwpn = saa.saa_wwnn = 0;
934
935	sc->sc_pd->pd_scsibus = (struct scsibus_softc *)
936	    config_found(&sc->sc_dev, &saa, scsiprint);
937
938	return (0);
939
940free_pdsc:
941	free(sc->sc_pd, M_DEVBUF, sizeof(*sc->sc_pd));
942	return (1);
943}
944
945int
946mfii_detach(struct device *self, int flags)
947{
948	struct mfii_softc *sc = (struct mfii_softc *)self;
949
950	if (sc->sc_ih == NULL)
951		return (0);
952
953#ifndef SMALL_KERNEL
954	if (sc->sc_sensors) {
955		sensordev_deinstall(&sc->sc_sensordev);
956		free(sc->sc_sensors, M_DEVBUF,
957		    MFI_MAX_LD * sizeof(struct ksensor));
958	}
959
960	if (sc->sc_bbu) {
961		free(sc->sc_bbu, M_DEVBUF, 4 * sizeof(*sc->sc_bbu));
962	}
963
964	if (sc->sc_bbu_status) {
965		free(sc->sc_bbu_status, M_DEVBUF,
966		    sizeof(*sc->sc_bbu_status) * sizeof(mfi_bbu_indicators));
967	}
968#endif /* SMALL_KERNEL */
969
970	mfii_aen_unregister(sc);
971	pci_intr_disestablish(sc->sc_pc, sc->sc_ih);
972	mfii_dmamem_free(sc, sc->sc_sgl);
973	mfii_dmamem_free(sc, sc->sc_mfi);
974	mfii_dmamem_free(sc, sc->sc_requests);
975	mfii_dmamem_free(sc, sc->sc_reply_postq);
976	mfii_dmamem_free(sc, sc->sc_sense);
977	bus_space_unmap(sc->sc_iot, sc->sc_ioh, sc->sc_ios);
978
979	return (0);
980}
981
982static void
983mfii_flush_cache(struct mfii_softc *sc, struct mfii_ccb *ccb)
984{
985#if 0
986	union mfi_mbox mbox = {
987		.b[0] = MR_FLUSH_CTRL_CACHE | MR_FLUSH_DISK_CACHE,
988	};
989	int rv;
990
991	mfii_scrub_ccb(ccb);
992	rv = mfii_do_mgmt(sc, ccb, MR_DCMD_CTRL_CACHE_FLUSH, &mbox,
993	    NULL, 0, SCSI_NOSLEEP);
994	if (rv != 0) {
995		printf("%s: unable to flush cache\n", DEVNAME(sc));
996		return;
997	}
998#endif
999}
1000
1001static void
1002mfii_shutdown(struct mfii_softc *sc, struct mfii_ccb *ccb)
1003{
1004#if 0
1005	int rv;
1006
1007	mfii_scrub_ccb(ccb);
1008	rv = mfii_do_mgmt(sc, ccb, MR_DCMD_CTRL_SHUTDOWN, NULL,
1009	    NULL, 0, SCSI_POLL);
1010	if (rv != 0) {
1011		printf("%s: unable to shutdown controller\n", DEVNAME(sc));
1012		return;
1013	}
1014#endif
1015}
1016
1017static void
1018mfii_powerdown(struct mfii_softc *sc)
1019{
1020	struct mfii_ccb *ccb;
1021
1022	ccb = scsi_io_get(&sc->sc_iopool, SCSI_NOSLEEP);
1023	if (ccb == NULL) {
1024		printf("%s: unable to allocate ccb for shutdown\n",
1025		    DEVNAME(sc));
1026		return;
1027	}
1028
1029	mfii_flush_cache(sc, ccb);
1030	mfii_shutdown(sc, ccb);
1031	scsi_io_put(&sc->sc_iopool, ccb);
1032}
1033
1034int
1035mfii_activate(struct device *self, int act)
1036{
1037	struct mfii_softc *sc = (struct mfii_softc *)self;
1038	int rv;
1039
1040	switch (act) {
1041	case DVACT_POWERDOWN:
1042		rv = config_activate_children(&sc->sc_dev, act);
1043		mfii_powerdown(sc);
1044		break;
1045	default:
1046		rv = config_activate_children(&sc->sc_dev, act);
1047		break;
1048	}
1049
1050	return (rv);
1051}
1052
1053u_int32_t
1054mfii_read(struct mfii_softc *sc, bus_size_t r)
1055{
1056	bus_space_barrier(sc->sc_iot, sc->sc_ioh, r, 4,
1057	    BUS_SPACE_BARRIER_READ);
1058	return (bus_space_read_4(sc->sc_iot, sc->sc_ioh, r));
1059}
1060
1061void
1062mfii_write(struct mfii_softc *sc, bus_size_t r, u_int32_t v)
1063{
1064	bus_space_write_4(sc->sc_iot, sc->sc_ioh, r, v);
1065	bus_space_barrier(sc->sc_iot, sc->sc_ioh, r, 4,
1066	    BUS_SPACE_BARRIER_WRITE);
1067}
1068
1069struct mfii_dmamem *
1070mfii_dmamem_alloc(struct mfii_softc *sc, size_t size)
1071{
1072	struct mfii_dmamem *m;
1073	int nsegs;
1074
1075	m = malloc(sizeof(*m), M_DEVBUF, M_NOWAIT | M_ZERO);
1076	if (m == NULL)
1077		return (NULL);
1078
1079	m->mdm_size = size;
1080
1081	if (bus_dmamap_create(sc->sc_dmat, size, 1, size, 0,
1082	    BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW, &m->mdm_map) != 0)
1083		goto mdmfree;
1084
1085	if (bus_dmamem_alloc(sc->sc_dmat, size, PAGE_SIZE, 0, &m->mdm_seg, 1,
1086	    &nsegs, BUS_DMA_NOWAIT | BUS_DMA_ZERO) != 0)
1087		goto destroy;
1088
1089	if (bus_dmamem_map(sc->sc_dmat, &m->mdm_seg, nsegs, size, &m->mdm_kva,
1090	    BUS_DMA_NOWAIT) != 0)
1091		goto free;
1092
1093	if (bus_dmamap_load(sc->sc_dmat, m->mdm_map, m->mdm_kva, size, NULL,
1094	    BUS_DMA_NOWAIT) != 0)
1095		goto unmap;
1096
1097	return (m);
1098
1099unmap:
1100	bus_dmamem_unmap(sc->sc_dmat, m->mdm_kva, m->mdm_size);
1101free:
1102	bus_dmamem_free(sc->sc_dmat, &m->mdm_seg, 1);
1103destroy:
1104	bus_dmamap_destroy(sc->sc_dmat, m->mdm_map);
1105mdmfree:
1106	free(m, M_DEVBUF, sizeof *m);
1107
1108	return (NULL);
1109}
1110
1111void
1112mfii_dmamem_free(struct mfii_softc *sc, struct mfii_dmamem *m)
1113{
1114	bus_dmamap_unload(sc->sc_dmat, m->mdm_map);
1115	bus_dmamem_unmap(sc->sc_dmat, m->mdm_kva, m->mdm_size);
1116	bus_dmamem_free(sc->sc_dmat, &m->mdm_seg, 1);
1117	bus_dmamap_destroy(sc->sc_dmat, m->mdm_map);
1118	free(m, M_DEVBUF, sizeof *m);
1119}
1120
1121void
1122mfii_dcmd_start(struct mfii_softc *sc, struct mfii_ccb *ccb)
1123{
1124	struct mpii_msg_scsi_io *io = ccb->ccb_request;
1125	struct mfii_raid_context *ctx = (struct mfii_raid_context *)(io + 1);
1126	struct mfii_sge *sge = (struct mfii_sge *)(ctx + 1);
1127
1128	io->function = MFII_FUNCTION_PASSTHRU_IO;
1129	io->sgl_offset0 = (uint32_t *)sge - (uint32_t *)io;
1130	io->chain_offset = io->sgl_offset0 / 4;
1131
1132	htolem64(&sge->sg_addr, ccb->ccb_sense_dva);
1133	htolem32(&sge->sg_len, sizeof(*ccb->ccb_sense));
1134	sge->sg_flags = MFII_SGE_CHAIN_ELEMENT | MFII_SGE_ADDR_IOCPLBNTA;
1135
1136	ccb->ccb_req.flags = MFII_REQ_TYPE_SCSI;
1137	ccb->ccb_req.smid = letoh16(ccb->ccb_smid);
1138
1139	mfii_start(sc, ccb);
1140}
1141
1142int
1143mfii_aen_register(struct mfii_softc *sc)
1144{
1145	struct mfi_evt_log_info mel;
1146	struct mfii_ccb *ccb;
1147	struct mfii_dmamem *mdm;
1148	int rv;
1149
1150	ccb = scsi_io_get(&sc->sc_iopool, SCSI_NOSLEEP);
1151	if (ccb == NULL) {
1152		printf("%s: unable to allocate ccb for aen\n", DEVNAME(sc));
1153		return (ENOMEM);
1154	}
1155
1156	memset(&mel, 0, sizeof(mel));
1157	mfii_scrub_ccb(ccb);
1158
1159	rv = mfii_do_mgmt(sc, ccb, MR_DCMD_CTRL_EVENT_GET_INFO, NULL,
1160	    &mel, sizeof(mel), SCSI_DATA_IN|SCSI_NOSLEEP);
1161	if (rv != 0) {
1162		scsi_io_put(&sc->sc_iopool, ccb);
1163		printf("%s: unable to get event info\n", DEVNAME(sc));
1164		return (EIO);
1165	}
1166
1167	mdm = mfii_dmamem_alloc(sc, sizeof(struct mfi_evt_detail));
1168	if (mdm == NULL) {
1169		scsi_io_put(&sc->sc_iopool, ccb);
1170		printf("%s: unable to allocate event data\n", DEVNAME(sc));
1171		return (ENOMEM);
1172	}
1173
1174	/* replay all the events from boot */
1175	mfii_aen_start(sc, ccb, mdm, lemtoh32(&mel.mel_boot_seq_num));
1176
1177	return (0);
1178}
1179
1180void
1181mfii_aen_start(struct mfii_softc *sc, struct mfii_ccb *ccb,
1182    struct mfii_dmamem *mdm, uint32_t seq)
1183{
1184	struct mfi_dcmd_frame *dcmd = mfii_dcmd_frame(ccb);
1185	struct mfi_frame_header *hdr = &dcmd->mdf_header;
1186	union mfi_sgl *sgl = &dcmd->mdf_sgl;
1187	union mfi_evt_class_locale mec;
1188
1189	mfii_scrub_ccb(ccb);
1190	mfii_dcmd_scrub(ccb);
1191	memset(MFII_DMA_KVA(mdm), 0, MFII_DMA_LEN(mdm));
1192
1193	ccb->ccb_cookie = mdm;
1194	ccb->ccb_done = mfii_aen_done;
1195	sc->sc_aen_ccb = ccb;
1196
1197	mec.mec_members.class = MFI_EVT_CLASS_DEBUG;
1198	mec.mec_members.reserved = 0;
1199	mec.mec_members.locale = htole16(MFI_EVT_LOCALE_ALL);
1200
1201	hdr->mfh_cmd = MFI_CMD_DCMD;
1202	hdr->mfh_sg_count = 1;
1203	hdr->mfh_flags = htole16(MFI_FRAME_DIR_READ | MFI_FRAME_SGL64);
1204	htolem32(&hdr->mfh_data_len, MFII_DMA_LEN(mdm));
1205	dcmd->mdf_opcode = htole32(MR_DCMD_CTRL_EVENT_WAIT);
1206	htolem32(&dcmd->mdf_mbox.w[0], seq);
1207	htolem32(&dcmd->mdf_mbox.w[1], mec.mec_word);
1208	htolem64(&sgl->sg64[0].addr, MFII_DMA_DVA(mdm));
1209	htolem32(&sgl->sg64[0].len, MFII_DMA_LEN(mdm));
1210
1211	bus_dmamap_sync(sc->sc_dmat, MFII_DMA_MAP(mdm),
1212	    0, MFII_DMA_LEN(mdm), BUS_DMASYNC_PREREAD);
1213
1214	mfii_dcmd_sync(sc, ccb, BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
1215	mfii_dcmd_start(sc, ccb);
1216}
1217
1218void
1219mfii_aen_done(struct mfii_softc *sc, struct mfii_ccb *ccb)
1220{
1221	KASSERT(sc->sc_aen_ccb == ccb);
1222
1223	/* defer to a thread with KERNEL_LOCK so we can run autoconf */
1224	task_add(systq, &sc->sc_aen_task);
1225}
1226
1227void
1228mfii_aen(void *arg)
1229{
1230	struct mfii_softc *sc = arg;
1231	struct mfii_ccb *ccb = sc->sc_aen_ccb;
1232	struct mfii_dmamem *mdm = ccb->ccb_cookie;
1233	const struct mfi_evt_detail *med = MFII_DMA_KVA(mdm);
1234	uint32_t code;
1235
1236	mfii_dcmd_sync(sc, ccb,
1237	    BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
1238	bus_dmamap_sync(sc->sc_dmat, MFII_DMA_MAP(mdm),
1239	    0, MFII_DMA_LEN(mdm), BUS_DMASYNC_POSTREAD);
1240
1241	code = lemtoh32(&med->med_code);
1242
1243#if 0
1244	log(LOG_DEBUG, "%s (seq %u, code %08x) %s\n", DEVNAME(sc),
1245	    lemtoh32(&med->med_seq_num), code, med->med_description);
1246#endif
1247
1248	switch (code) {
1249	case MFI_EVT_PD_INSERTED_EXT:
1250		if (med->med_arg_type != MFI_EVT_ARGS_PD_ADDRESS)
1251			break;
1252
1253		mfii_aen_pd_insert(sc, &med->args.pd_address);
1254		break;
1255 	case MFI_EVT_PD_REMOVED_EXT:
1256		if (med->med_arg_type != MFI_EVT_ARGS_PD_ADDRESS)
1257			break;
1258
1259		mfii_aen_pd_remove(sc, &med->args.pd_address);
1260		break;
1261
1262	case MFI_EVT_PD_STATE_CHANGE:
1263		if (med->med_arg_type != MFI_EVT_ARGS_PD_STATE)
1264			break;
1265
1266		mfii_aen_pd_state_change(sc, &med->args.pd_state);
1267		break;
1268
1269	case MFI_EVT_LD_CREATED:
1270	case MFI_EVT_LD_DELETED:
1271		mfii_aen_ld_update(sc);
1272		break;
1273
1274	default:
1275		break;
1276	}
1277
1278	mfii_aen_start(sc, ccb, mdm, lemtoh32(&med->med_seq_num) + 1);
1279}
1280
1281void
1282mfii_aen_pd_insert(struct mfii_softc *sc,
1283    const struct mfi_evtarg_pd_address *pd)
1284{
1285#if 0
1286	printf("%s: pd inserted ext\n", DEVNAME(sc));
1287	printf("%s:  device_id %04x encl_id: %04x type %x\n", DEVNAME(sc),
1288	    lemtoh16(&pd->device_id), lemtoh16(&pd->encl_id),
1289	    pd->scsi_dev_type);
1290	printf("%s:  connected %02x addrs %016llx %016llx\n", DEVNAME(sc),
1291	    pd->connected.port_bitmap, lemtoh64(&pd->sas_addr[0]),
1292	    lemtoh64(&pd->sas_addr[1]));
1293#endif
1294
1295	if (mfii_dev_handles_update(sc) != 0) /* refresh map */
1296		return;
1297
1298	scsi_probe_target(sc->sc_pd->pd_scsibus, lemtoh16(&pd->device_id));
1299}
1300
1301void
1302mfii_aen_pd_remove(struct mfii_softc *sc,
1303    const struct mfi_evtarg_pd_address *pd)
1304{
1305#if 0
1306	printf("%s: pd removed ext\n", DEVNAME(sc));
1307	printf("%s:  device_id %04x encl_id: %04x type %u\n", DEVNAME(sc),
1308	    lemtoh16(&pd->device_id), lemtoh16(&pd->encl_id),
1309	    pd->scsi_dev_type);
1310	printf("%s:  connected %02x addrs %016llx %016llx\n", DEVNAME(sc),
1311	    pd->connected.port_bitmap, lemtoh64(&pd->sas_addr[0]),
1312	    lemtoh64(&pd->sas_addr[1]));
1313#endif
1314	uint16_t target = lemtoh16(&pd->device_id);
1315
1316	scsi_activate(sc->sc_pd->pd_scsibus, target, -1, DVACT_DEACTIVATE);
1317
1318	/* the firmware will abort outstanding commands for us */
1319
1320	scsi_detach_target(sc->sc_pd->pd_scsibus, target, DETACH_FORCE);
1321}
1322
1323void
1324mfii_aen_pd_state_change(struct mfii_softc *sc,
1325    const struct mfi_evtarg_pd_state *state)
1326{
1327	uint16_t target = lemtoh16(&state->pd.mep_device_id);
1328
1329	if (state->prev_state == htole32(MFI_PD_SYSTEM) &&
1330	    state->new_state != htole32(MFI_PD_SYSTEM)) {
1331		/* it's been pulled or configured for raid */
1332
1333		scsi_activate(sc->sc_pd->pd_scsibus, target, -1,
1334		    DVACT_DEACTIVATE);
1335		/* outstanding commands will simply complete or get aborted */
1336		scsi_detach_target(sc->sc_pd->pd_scsibus, target,
1337		    DETACH_FORCE);
1338
1339	} else if (state->prev_state == htole32(MFI_PD_UNCONFIG_GOOD) &&
1340	    state->new_state == htole32(MFI_PD_SYSTEM)) {
1341		/* the firmware is handing the disk over */
1342
1343		scsi_probe_target(sc->sc_pd->pd_scsibus, target);
1344	}
1345}
1346
1347void
1348mfii_aen_ld_update(struct mfii_softc *sc)
1349{
1350	int i, state, target, old, nld;
1351	int newlds[MFI_MAX_LD];
1352
1353	if (mfii_mgmt(sc, MR_DCMD_LD_GET_LIST, NULL, &sc->sc_ld_list,
1354	    sizeof(sc->sc_ld_list), SCSI_DATA_IN) != 0) {
1355		DNPRINTF(MFII_D_MISC, "%s: getting list of logical disks failed\n",
1356		    DEVNAME(sc));
1357		return;
1358	}
1359
1360	memset(newlds, -1, sizeof(newlds));
1361
1362	for (i = 0; i < sc->sc_ld_list.mll_no_ld; i++) {
1363		state = sc->sc_ld_list.mll_list[i].mll_state;
1364		target = sc->sc_ld_list.mll_list[i].mll_ld.mld_target;
1365		DNPRINTF(MFII_D_MISC, "%s: target %d: state %d\n",
1366		    DEVNAME(sc), target, state);
1367		newlds[target] = i;
1368	}
1369
1370	for (i = 0; i < MFI_MAX_LD; i++) {
1371		old = sc->sc_target_lds[i];
1372		nld = newlds[i];
1373
1374		if (old == -1 && nld != -1) {
1375			DNPRINTF(MFII_D_MISC, "%s: attaching target %d\n",
1376			    DEVNAME(sc), i);
1377
1378			scsi_probe_target(sc->sc_scsibus, i);
1379
1380#ifndef SMALL_KERNEL
1381			mfii_init_ld_sensor(sc, nld);
1382			sensor_attach(&sc->sc_sensordev, &sc->sc_sensors[i]);
1383#endif
1384		} else if (nld == -1 && old != -1) {
1385			DNPRINTF(MFII_D_MISC, "%s: detaching target %d\n",
1386			    DEVNAME(sc), i);
1387
1388			scsi_activate(sc->sc_scsibus, i, -1,
1389			    DVACT_DEACTIVATE);
1390			scsi_detach_target(sc->sc_scsibus, i,
1391			    DETACH_FORCE);
1392#ifndef SMALL_KERNEL
1393			sensor_detach(&sc->sc_sensordev, &sc->sc_sensors[i]);
1394#endif
1395		}
1396	}
1397
1398	memcpy(sc->sc_target_lds, newlds, sizeof(sc->sc_target_lds));
1399}
1400
1401void
1402mfii_aen_unregister(struct mfii_softc *sc)
1403{
1404	/* XXX */
1405}
1406
1407int
1408mfii_reset_hard(struct mfii_softc *sc)
1409{
1410	u_int16_t		i;
1411
1412	mfii_write(sc, MFI_OSTS, 0);
1413
1414	/* enable diagnostic register */
1415	mfii_write(sc, MPII_WRITESEQ, MPII_WRITESEQ_FLUSH);
1416	mfii_write(sc, MPII_WRITESEQ, MPII_WRITESEQ_1);
1417	mfii_write(sc, MPII_WRITESEQ, MPII_WRITESEQ_2);
1418	mfii_write(sc, MPII_WRITESEQ, MPII_WRITESEQ_3);
1419	mfii_write(sc, MPII_WRITESEQ, MPII_WRITESEQ_4);
1420	mfii_write(sc, MPII_WRITESEQ, MPII_WRITESEQ_5);
1421	mfii_write(sc, MPII_WRITESEQ, MPII_WRITESEQ_6);
1422
1423	delay(100);
1424
1425	if ((mfii_read(sc, MPII_HOSTDIAG) & MPII_HOSTDIAG_DWRE) == 0) {
1426		printf("%s: failed to enable diagnostic read/write\n",
1427		    DEVNAME(sc));
1428		return(1);
1429	}
1430
1431	/* reset ioc */
1432	mfii_write(sc, MPII_HOSTDIAG, MPII_HOSTDIAG_RESET_ADAPTER);
1433
1434	/* 240 milliseconds */
1435	delay(240000);
1436
1437	for (i = 0; i < 30000; i++) {
1438		if ((mfii_read(sc, MPII_HOSTDIAG) &
1439		    MPII_HOSTDIAG_RESET_ADAPTER) == 0)
1440			break;
1441		delay(10000);
1442	}
1443	if (i >= 30000) {
1444		printf("%s: failed to reset device\n", DEVNAME(sc));
1445		return (1);
1446	}
1447
1448	/* disable diagnostic register */
1449	mfii_write(sc, MPII_WRITESEQ, 0xff);
1450
1451	return(0);
1452}
1453
1454int
1455mfii_transition_firmware(struct mfii_softc *sc)
1456{
1457	int32_t			fw_state, cur_state;
1458	int			max_wait, i, reset_on_fault = 1;
1459
1460	fw_state = mfii_fw_state(sc) & MFI_STATE_MASK;
1461
1462	while (fw_state != MFI_STATE_READY) {
1463		cur_state = fw_state;
1464		switch (fw_state) {
1465		case MFI_STATE_FAULT:
1466			if (!reset_on_fault) {
1467				printf("%s: firmware fault\n", DEVNAME(sc));
1468				return (1);
1469			}
1470			printf("%s: firmware fault; attempting full device "
1471			    "reset, this can take some time\n", DEVNAME(sc));
1472			if (mfii_reset_hard(sc))
1473				return (1);
1474			max_wait = 20;
1475			reset_on_fault = 0;
1476			break;
1477		case MFI_STATE_WAIT_HANDSHAKE:
1478			mfii_write(sc, MFI_SKINNY_IDB,
1479			    MFI_INIT_CLEAR_HANDSHAKE);
1480			max_wait = 2;
1481			break;
1482		case MFI_STATE_OPERATIONAL:
1483			mfii_write(sc, MFI_SKINNY_IDB, MFI_INIT_READY);
1484			max_wait = 10;
1485			break;
1486		case MFI_STATE_BB_INIT:
1487			max_wait = 20;
1488			break;
1489		case MFI_STATE_UNDEFINED:
1490		case MFI_STATE_FW_INIT:
1491		case MFI_STATE_FW_INIT_2:
1492		case MFI_STATE_DEVICE_SCAN:
1493		case MFI_STATE_FLUSH_CACHE:
1494			max_wait = 40;
1495			break;
1496		case MFI_STATE_BOOT_MESSAGE_PENDING:
1497			mfii_write(sc, MFI_SKINNY_IDB, MFI_INIT_HOTPLUG);
1498			max_wait = 10;
1499			break;
1500		default:
1501			printf("%s: unknown firmware state %#x\n",
1502			    DEVNAME(sc), fw_state);
1503			return (1);
1504		}
1505		for (i = 0; i < (max_wait * 10); i++) {
1506			fw_state = mfii_fw_state(sc) & MFI_STATE_MASK;
1507			if (fw_state == cur_state)
1508				DELAY(100000);
1509			else
1510				break;
1511		}
1512		if (fw_state == cur_state) {
1513			printf("%s: firmware stuck in state %#x\n",
1514			    DEVNAME(sc), fw_state);
1515			return (1);
1516		} else {
1517			DPRINTF("%s: firmware state change %#x -> %#x after "
1518			    "%d iterations\n",
1519			    DEVNAME(sc), cur_state, fw_state, i);
1520		}
1521	}
1522
1523	return (0);
1524}
1525
1526int
1527mfii_get_info(struct mfii_softc *sc)
1528{
1529	int i, rv;
1530
1531	rv = mfii_mgmt(sc, MR_DCMD_CTRL_GET_INFO, NULL, &sc->sc_info,
1532	    sizeof(sc->sc_info), SCSI_DATA_IN|SCSI_NOSLEEP);
1533
1534	if (rv != 0)
1535		return (rv);
1536
1537	for (i = 0; i < sc->sc_info.mci_image_component_count; i++) {
1538		DPRINTF("%s: active FW %s Version %s date %s time %s\n",
1539		    DEVNAME(sc),
1540		    sc->sc_info.mci_image_component[i].mic_name,
1541		    sc->sc_info.mci_image_component[i].mic_version,
1542		    sc->sc_info.mci_image_component[i].mic_build_date,
1543		    sc->sc_info.mci_image_component[i].mic_build_time);
1544	}
1545
1546	for (i = 0; i < sc->sc_info.mci_pending_image_component_count; i++) {
1547		DPRINTF("%s: pending FW %s Version %s date %s time %s\n",
1548		    DEVNAME(sc),
1549		    sc->sc_info.mci_pending_image_component[i].mic_name,
1550		    sc->sc_info.mci_pending_image_component[i].mic_version,
1551		    sc->sc_info.mci_pending_image_component[i].mic_build_date,
1552		    sc->sc_info.mci_pending_image_component[i].mic_build_time);
1553	}
1554
1555	DPRINTF("%s: max_arms %d max_spans %d max_arrs %d max_lds %d name %s\n",
1556	    DEVNAME(sc),
1557	    sc->sc_info.mci_max_arms,
1558	    sc->sc_info.mci_max_spans,
1559	    sc->sc_info.mci_max_arrays,
1560	    sc->sc_info.mci_max_lds,
1561	    sc->sc_info.mci_product_name);
1562
1563	DPRINTF("%s: serial %s present %#x fw time %d max_cmds %d max_sg %d\n",
1564	    DEVNAME(sc),
1565	    sc->sc_info.mci_serial_number,
1566	    sc->sc_info.mci_hw_present,
1567	    sc->sc_info.mci_current_fw_time,
1568	    sc->sc_info.mci_max_cmds,
1569	    sc->sc_info.mci_max_sg_elements);
1570
1571	DPRINTF("%s: max_rq %d lds_pres %d lds_deg %d lds_off %d pd_pres %d\n",
1572	    DEVNAME(sc),
1573	    sc->sc_info.mci_max_request_size,
1574	    sc->sc_info.mci_lds_present,
1575	    sc->sc_info.mci_lds_degraded,
1576	    sc->sc_info.mci_lds_offline,
1577	    sc->sc_info.mci_pd_present);
1578
1579	DPRINTF("%s: pd_dsk_prs %d pd_dsk_pred_fail %d pd_dsk_fail %d\n",
1580	    DEVNAME(sc),
1581	    sc->sc_info.mci_pd_disks_present,
1582	    sc->sc_info.mci_pd_disks_pred_failure,
1583	    sc->sc_info.mci_pd_disks_failed);
1584
1585	DPRINTF("%s: nvram %d mem %d flash %d\n",
1586	    DEVNAME(sc),
1587	    sc->sc_info.mci_nvram_size,
1588	    sc->sc_info.mci_memory_size,
1589	    sc->sc_info.mci_flash_size);
1590
1591	DPRINTF("%s: ram_cor %d ram_uncor %d clus_all %d clus_act %d\n",
1592	    DEVNAME(sc),
1593	    sc->sc_info.mci_ram_correctable_errors,
1594	    sc->sc_info.mci_ram_uncorrectable_errors,
1595	    sc->sc_info.mci_cluster_allowed,
1596	    sc->sc_info.mci_cluster_active);
1597
1598	DPRINTF("%s: max_strps_io %d raid_lvl %#x adapt_ops %#x ld_ops %#x\n",
1599	    DEVNAME(sc),
1600	    sc->sc_info.mci_max_strips_per_io,
1601	    sc->sc_info.mci_raid_levels,
1602	    sc->sc_info.mci_adapter_ops,
1603	    sc->sc_info.mci_ld_ops);
1604
1605	DPRINTF("%s: strp_sz_min %d strp_sz_max %d pd_ops %#x pd_mix %#x\n",
1606	    DEVNAME(sc),
1607	    sc->sc_info.mci_stripe_sz_ops.min,
1608	    sc->sc_info.mci_stripe_sz_ops.max,
1609	    sc->sc_info.mci_pd_ops,
1610	    sc->sc_info.mci_pd_mix_support);
1611
1612	DPRINTF("%s: ecc_bucket %d pckg_prop %s\n",
1613	    DEVNAME(sc),
1614	    sc->sc_info.mci_ecc_bucket_count,
1615	    sc->sc_info.mci_package_version);
1616
1617	DPRINTF("%s: sq_nm %d prd_fail_poll %d intr_thrtl %d intr_thrtl_to %d\n",
1618	    DEVNAME(sc),
1619	    sc->sc_info.mci_properties.mcp_seq_num,
1620	    sc->sc_info.mci_properties.mcp_pred_fail_poll_interval,
1621	    sc->sc_info.mci_properties.mcp_intr_throttle_cnt,
1622	    sc->sc_info.mci_properties.mcp_intr_throttle_timeout);
1623
1624	DPRINTF("%s: rbld_rate %d patr_rd_rate %d bgi_rate %d cc_rate %d\n",
1625	    DEVNAME(sc),
1626	    sc->sc_info.mci_properties.mcp_rebuild_rate,
1627	    sc->sc_info.mci_properties.mcp_patrol_read_rate,
1628	    sc->sc_info.mci_properties.mcp_bgi_rate,
1629	    sc->sc_info.mci_properties.mcp_cc_rate);
1630
1631	DPRINTF("%s: rc_rate %d ch_flsh %d spin_cnt %d spin_dly %d clus_en %d\n",
1632	    DEVNAME(sc),
1633	    sc->sc_info.mci_properties.mcp_recon_rate,
1634	    sc->sc_info.mci_properties.mcp_cache_flush_interval,
1635	    sc->sc_info.mci_properties.mcp_spinup_drv_cnt,
1636	    sc->sc_info.mci_properties.mcp_spinup_delay,
1637	    sc->sc_info.mci_properties.mcp_cluster_enable);
1638
1639	DPRINTF("%s: coerc %d alarm %d dis_auto_rbld %d dis_bat_wrn %d ecc %d\n",
1640	    DEVNAME(sc),
1641	    sc->sc_info.mci_properties.mcp_coercion_mode,
1642	    sc->sc_info.mci_properties.mcp_alarm_enable,
1643	    sc->sc_info.mci_properties.mcp_disable_auto_rebuild,
1644	    sc->sc_info.mci_properties.mcp_disable_battery_warn,
1645	    sc->sc_info.mci_properties.mcp_ecc_bucket_size);
1646
1647	DPRINTF("%s: ecc_leak %d rest_hs %d exp_encl_dev %d\n",
1648	    DEVNAME(sc),
1649	    sc->sc_info.mci_properties.mcp_ecc_bucket_leak_rate,
1650	    sc->sc_info.mci_properties.mcp_restore_hotspare_on_insertion,
1651	    sc->sc_info.mci_properties.mcp_expose_encl_devices);
1652
1653	DPRINTF("%s: vendor %#x device %#x subvendor %#x subdevice %#x\n",
1654	    DEVNAME(sc),
1655	    sc->sc_info.mci_pci.mip_vendor,
1656	    sc->sc_info.mci_pci.mip_device,
1657	    sc->sc_info.mci_pci.mip_subvendor,
1658	    sc->sc_info.mci_pci.mip_subdevice);
1659
1660	DPRINTF("%s: type %#x port_count %d port_addr ",
1661	    DEVNAME(sc),
1662	    sc->sc_info.mci_host.mih_type,
1663	    sc->sc_info.mci_host.mih_port_count);
1664
1665	for (i = 0; i < 8; i++)
1666		DPRINTF("%.0llx ", sc->sc_info.mci_host.mih_port_addr[i]);
1667	DPRINTF("\n");
1668
1669	DPRINTF("%s: type %.x port_count %d port_addr ",
1670	    DEVNAME(sc),
1671	    sc->sc_info.mci_device.mid_type,
1672	    sc->sc_info.mci_device.mid_port_count);
1673
1674	for (i = 0; i < 8; i++)
1675		DPRINTF("%.0llx ", sc->sc_info.mci_device.mid_port_addr[i]);
1676	DPRINTF("\n");
1677
1678	return (0);
1679}
1680
1681int
1682mfii_mfa_poll(struct mfii_softc *sc, struct mfii_ccb *ccb)
1683{
1684	struct mfi_frame_header	*hdr = ccb->ccb_request;
1685	u_int64_t r;
1686	int to = 0, rv = 0;
1687
1688#ifdef DIAGNOSTIC
1689	if (ccb->ccb_cookie != NULL || ccb->ccb_done != NULL)
1690		panic("mfii_mfa_poll called with cookie or done set");
1691#endif
1692
1693	hdr->mfh_context = ccb->ccb_smid;
1694	hdr->mfh_cmd_status = MFI_STAT_INVALID_STATUS;
1695	hdr->mfh_flags |= htole16(MFI_FRAME_DONT_POST_IN_REPLY_QUEUE);
1696
1697	r = MFII_REQ_MFA(ccb->ccb_request_dva);
1698	memcpy(&ccb->ccb_req, &r, sizeof(ccb->ccb_req));
1699
1700	mfii_start(sc, ccb);
1701
1702	for (;;) {
1703		bus_dmamap_sync(sc->sc_dmat, MFII_DMA_MAP(sc->sc_requests),
1704		    ccb->ccb_request_offset, MFII_REQUEST_SIZE,
1705		    BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
1706
1707		if (hdr->mfh_cmd_status != MFI_STAT_INVALID_STATUS)
1708			break;
1709
1710		if (to++ > 5000) { /* XXX 5 seconds busywait sucks */
1711			printf("%s: timeout on ccb %d\n", DEVNAME(sc),
1712			    ccb->ccb_smid);
1713			ccb->ccb_flags |= MFI_CCB_F_ERR;
1714			rv = 1;
1715			break;
1716		}
1717
1718		bus_dmamap_sync(sc->sc_dmat, MFII_DMA_MAP(sc->sc_requests),
1719		    ccb->ccb_request_offset, MFII_REQUEST_SIZE,
1720		    BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
1721
1722		delay(1000);
1723	}
1724
1725	if (ccb->ccb_len > 0) {
1726		bus_dmamap_sync(sc->sc_dmat, ccb->ccb_dmamap,
1727		    0, ccb->ccb_dmamap->dm_mapsize,
1728		    (ccb->ccb_direction == MFII_DATA_IN) ?
1729		    BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE);
1730
1731		bus_dmamap_unload(sc->sc_dmat, ccb->ccb_dmamap);
1732	}
1733
1734	return (rv);
1735}
1736
1737int
1738mfii_poll(struct mfii_softc *sc, struct mfii_ccb *ccb)
1739{
1740	void (*done)(struct mfii_softc *, struct mfii_ccb *);
1741	void *cookie;
1742	int rv = 1;
1743
1744	done = ccb->ccb_done;
1745	cookie = ccb->ccb_cookie;
1746
1747	ccb->ccb_done = mfii_poll_done;
1748	ccb->ccb_cookie = &rv;
1749
1750	mfii_start(sc, ccb);
1751
1752	do {
1753		delay(10);
1754		mfii_postq(sc);
1755	} while (rv == 1);
1756
1757	ccb->ccb_cookie = cookie;
1758	done(sc, ccb);
1759
1760	return (0);
1761}
1762
1763void
1764mfii_poll_done(struct mfii_softc *sc, struct mfii_ccb *ccb)
1765{
1766	int *rv = ccb->ccb_cookie;
1767
1768	*rv = 0;
1769}
1770
1771int
1772mfii_exec(struct mfii_softc *sc, struct mfii_ccb *ccb)
1773{
1774	struct mutex m;
1775
1776	mtx_init(&m, IPL_BIO);
1777
1778#ifdef DIAGNOSTIC
1779	if (ccb->ccb_cookie != NULL || ccb->ccb_done != NULL)
1780		panic("mfii_exec called with cookie or done set");
1781#endif
1782
1783	ccb->ccb_cookie = &m;
1784	ccb->ccb_done = mfii_exec_done;
1785
1786	mfii_start(sc, ccb);
1787
1788	mtx_enter(&m);
1789	while (ccb->ccb_cookie != NULL)
1790		msleep_nsec(ccb, &m, PRIBIO, "mfiiexec", INFSLP);
1791	mtx_leave(&m);
1792
1793	return (0);
1794}
1795
1796void
1797mfii_exec_done(struct mfii_softc *sc, struct mfii_ccb *ccb)
1798{
1799	struct mutex *m = ccb->ccb_cookie;
1800
1801	mtx_enter(m);
1802	ccb->ccb_cookie = NULL;
1803	wakeup_one(ccb);
1804	mtx_leave(m);
1805}
1806
1807int
1808mfii_mgmt(struct mfii_softc *sc, uint32_t opc, const union mfi_mbox *mbox,
1809    void *buf, size_t len, int flags)
1810{
1811	struct mfii_ccb *ccb;
1812	int rv;
1813
1814	ccb = scsi_io_get(&sc->sc_iopool, flags);
1815	if (ccb == NULL)
1816		return (ENOMEM);
1817
1818	mfii_scrub_ccb(ccb);
1819	rv = mfii_do_mgmt(sc, ccb, opc, mbox, buf, len, flags);
1820	scsi_io_put(&sc->sc_iopool, ccb);
1821
1822	return (rv);
1823}
1824
1825int
1826mfii_do_mgmt(struct mfii_softc *sc, struct mfii_ccb *ccb, uint32_t opc,
1827    const union mfi_mbox *mbox, void *buf, size_t len, int flags)
1828{
1829	struct mpii_msg_scsi_io *io = ccb->ccb_request;
1830	struct mfii_raid_context *ctx = (struct mfii_raid_context *)(io + 1);
1831	struct mfii_sge *sge = (struct mfii_sge *)(ctx + 1);
1832	struct mfi_dcmd_frame *dcmd = ccb->ccb_mfi;
1833	struct mfi_frame_header *hdr = &dcmd->mdf_header;
1834	u_int8_t *dma_buf = NULL;
1835	int rv = EIO;
1836
1837	if (cold)
1838		flags |= SCSI_NOSLEEP;
1839
1840	if (buf != NULL) {
1841		dma_buf = dma_alloc(len, PR_WAITOK);
1842		if (dma_buf == NULL)
1843			return (ENOMEM);
1844	}
1845
1846	ccb->ccb_data = dma_buf;
1847	ccb->ccb_len = len;
1848	switch (flags & (SCSI_DATA_IN | SCSI_DATA_OUT)) {
1849	case SCSI_DATA_IN:
1850		ccb->ccb_direction = MFII_DATA_IN;
1851		hdr->mfh_flags = htole16(MFI_FRAME_DIR_READ);
1852		break;
1853	case SCSI_DATA_OUT:
1854		ccb->ccb_direction = MFII_DATA_OUT;
1855		hdr->mfh_flags = htole16(MFI_FRAME_DIR_WRITE);
1856		memcpy(dma_buf, buf, len);
1857		break;
1858	case 0:
1859		ccb->ccb_direction = MFII_DATA_NONE;
1860		hdr->mfh_flags = htole16(MFI_FRAME_DIR_NONE);
1861		break;
1862	}
1863
1864	if (mfii_load_mfa(sc, ccb, &dcmd->mdf_sgl,
1865	    ISSET(flags, SCSI_NOSLEEP)) != 0) {
1866		rv = ENOMEM;
1867		goto done;
1868	}
1869
1870	hdr->mfh_cmd = MFI_CMD_DCMD;
1871	hdr->mfh_context = ccb->ccb_smid;
1872	hdr->mfh_data_len = htole32(len);
1873	hdr->mfh_sg_count = len ? ccb->ccb_dmamap->dm_nsegs : 0;
1874
1875	dcmd->mdf_opcode = opc;
1876	/* handle special opcodes */
1877	if (mbox != NULL)
1878		memcpy(&dcmd->mdf_mbox, mbox, sizeof(dcmd->mdf_mbox));
1879
1880	io->function = MFII_FUNCTION_PASSTHRU_IO;
1881
1882	if (len) {
1883		io->sgl_offset0 = ((u_int8_t *)sge - (u_int8_t *)io) / 4;
1884		io->chain_offset = ((u_int8_t *)sge - (u_int8_t *)io) / 16;
1885		htolem64(&sge->sg_addr, ccb->ccb_mfi_dva);
1886		htolem32(&sge->sg_len, MFI_FRAME_SIZE);
1887		sge->sg_flags =
1888		    MFII_SGE_CHAIN_ELEMENT | MFII_SGE_ADDR_IOCPLBNTA;
1889	}
1890
1891	ccb->ccb_req.flags = MFII_REQ_TYPE_SCSI;
1892	ccb->ccb_req.smid = letoh16(ccb->ccb_smid);
1893
1894	if (ISSET(flags, SCSI_NOSLEEP)) {
1895		ccb->ccb_done = mfii_empty_done;
1896		mfii_poll(sc, ccb);
1897	} else
1898		mfii_exec(sc, ccb);
1899
1900	if (hdr->mfh_cmd_status == MFI_STAT_OK) {
1901		rv = 0;
1902
1903		if (ccb->ccb_direction == MFII_DATA_IN)
1904			memcpy(buf, dma_buf, len);
1905	}
1906
1907done:
1908	if (buf != NULL)
1909		dma_free(dma_buf, len);
1910
1911	return (rv);
1912}
1913
1914void
1915mfii_empty_done(struct mfii_softc *sc, struct mfii_ccb *ccb)
1916{
1917	return;
1918}
1919
1920int
1921mfii_load_mfa(struct mfii_softc *sc, struct mfii_ccb *ccb,
1922    void *sglp, int nosleep)
1923{
1924	union mfi_sgl *sgl = sglp;
1925	bus_dmamap_t dmap = ccb->ccb_dmamap;
1926	int error;
1927	int i;
1928
1929	if (ccb->ccb_len == 0)
1930		return (0);
1931
1932	error = bus_dmamap_load(sc->sc_dmat, dmap,
1933	    ccb->ccb_data, ccb->ccb_len, NULL,
1934	    nosleep ? BUS_DMA_NOWAIT : BUS_DMA_WAITOK);
1935	if (error) {
1936		printf("%s: error %d loading dmamap\n", DEVNAME(sc), error);
1937		return (1);
1938	}
1939
1940	for (i = 0; i < dmap->dm_nsegs; i++) {
1941		sgl->sg32[i].addr = htole32(dmap->dm_segs[i].ds_addr);
1942		sgl->sg32[i].len = htole32(dmap->dm_segs[i].ds_len);
1943	}
1944
1945	bus_dmamap_sync(sc->sc_dmat, dmap, 0, dmap->dm_mapsize,
1946	    ccb->ccb_direction == MFII_DATA_OUT ?
1947	    BUS_DMASYNC_PREWRITE : BUS_DMASYNC_PREREAD);
1948
1949	return (0);
1950}
1951
1952void
1953mfii_start(struct mfii_softc *sc, struct mfii_ccb *ccb)
1954{
1955	u_long *r = (u_long *)&ccb->ccb_req;
1956
1957	bus_dmamap_sync(sc->sc_dmat, MFII_DMA_MAP(sc->sc_requests),
1958	    ccb->ccb_request_offset, MFII_REQUEST_SIZE,
1959	    BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
1960
1961#if defined(__LP64__)
1962	bus_space_write_raw_8(sc->sc_iot, sc->sc_ioh, MFI_IQPL, *r);
1963#else
1964	mtx_enter(&sc->sc_post_mtx);
1965	bus_space_write_raw_4(sc->sc_iot, sc->sc_ioh, MFI_IQPL, r[0]);
1966	bus_space_barrier(sc->sc_iot, sc->sc_ioh,
1967	    MFI_IQPL, 8, BUS_SPACE_BARRIER_WRITE);
1968
1969	bus_space_write_raw_4(sc->sc_iot, sc->sc_ioh, MFI_IQPH, r[1]);
1970	bus_space_barrier(sc->sc_iot, sc->sc_ioh,
1971	    MFI_IQPH, 8, BUS_SPACE_BARRIER_WRITE);
1972	mtx_leave(&sc->sc_post_mtx);
1973#endif
1974}
1975
1976void
1977mfii_done(struct mfii_softc *sc, struct mfii_ccb *ccb)
1978{
1979	bus_dmamap_sync(sc->sc_dmat, MFII_DMA_MAP(sc->sc_requests),
1980	    ccb->ccb_request_offset, MFII_REQUEST_SIZE,
1981	    BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
1982
1983	if (ccb->ccb_sgl_len > 0) {
1984		bus_dmamap_sync(sc->sc_dmat, MFII_DMA_MAP(sc->sc_sgl),
1985		    ccb->ccb_sgl_offset, ccb->ccb_sgl_len,
1986		    BUS_DMASYNC_POSTWRITE);
1987	}
1988
1989	if (ccb->ccb_len > 0) {
1990		bus_dmamap_sync(sc->sc_dmat, ccb->ccb_dmamap,
1991		    0, ccb->ccb_dmamap->dm_mapsize,
1992		    (ccb->ccb_direction == MFII_DATA_IN) ?
1993		    BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE);
1994
1995		bus_dmamap_unload(sc->sc_dmat, ccb->ccb_dmamap);
1996	}
1997
1998	ccb->ccb_done(sc, ccb);
1999}
2000
2001int
2002mfii_initialise_firmware(struct mfii_softc *sc)
2003{
2004	struct mpii_msg_iocinit_request *iiq;
2005	struct mfii_dmamem *m;
2006	struct mfii_ccb *ccb;
2007	struct mfi_init_frame *init;
2008	int rv;
2009
2010	m = mfii_dmamem_alloc(sc, sizeof(*iiq));
2011	if (m == NULL)
2012		return (1);
2013
2014	iiq = MFII_DMA_KVA(m);
2015	memset(iiq, 0, sizeof(*iiq));
2016
2017	iiq->function = MPII_FUNCTION_IOC_INIT;
2018	iiq->whoinit = MPII_WHOINIT_HOST_DRIVER;
2019
2020	iiq->msg_version_maj = 0x02;
2021	iiq->msg_version_min = 0x00;
2022	iiq->hdr_version_unit = 0x10;
2023	iiq->hdr_version_dev = 0x0;
2024
2025	iiq->system_request_frame_size = htole16(MFII_REQUEST_SIZE / 4);
2026
2027	iiq->reply_descriptor_post_queue_depth =
2028	    htole16(sc->sc_reply_postq_depth);
2029	iiq->reply_free_queue_depth = htole16(0);
2030
2031	htolem32(&iiq->sense_buffer_address_high,
2032	    MFII_DMA_DVA(sc->sc_sense) >> 32);
2033
2034	htolem32(&iiq->reply_descriptor_post_queue_address_lo,
2035	    MFII_DMA_DVA(sc->sc_reply_postq));
2036	htolem32(&iiq->reply_descriptor_post_queue_address_hi,
2037	    MFII_DMA_DVA(sc->sc_reply_postq) >> 32);
2038
2039	htolem32(&iiq->system_request_frame_base_address_lo,
2040	    MFII_DMA_DVA(sc->sc_requests));
2041	htolem32(&iiq->system_request_frame_base_address_hi,
2042	    MFII_DMA_DVA(sc->sc_requests) >> 32);
2043
2044	iiq->timestamp = htole64(getuptime());
2045
2046	ccb = scsi_io_get(&sc->sc_iopool, SCSI_NOSLEEP);
2047	if (ccb == NULL) {
2048		/* shouldn't ever run out of ccbs during attach */
2049		return (1);
2050	}
2051	mfii_scrub_ccb(ccb);
2052	init = ccb->ccb_request;
2053
2054	init->mif_header.mfh_cmd = MFI_CMD_INIT;
2055	init->mif_header.mfh_data_len = htole32(sizeof(*iiq));
2056	init->mif_qinfo_new_addr = htole64(MFII_DMA_DVA(m));
2057
2058	bus_dmamap_sync(sc->sc_dmat, MFII_DMA_MAP(sc->sc_reply_postq),
2059	    0, MFII_DMA_LEN(sc->sc_reply_postq),
2060	    BUS_DMASYNC_PREREAD);
2061
2062	bus_dmamap_sync(sc->sc_dmat, MFII_DMA_MAP(m),
2063	    0, sizeof(*iiq), BUS_DMASYNC_PREREAD);
2064
2065	rv = mfii_mfa_poll(sc, ccb);
2066
2067	bus_dmamap_sync(sc->sc_dmat, MFII_DMA_MAP(m),
2068	    0, sizeof(*iiq), BUS_DMASYNC_POSTREAD);
2069
2070	scsi_io_put(&sc->sc_iopool, ccb);
2071	mfii_dmamem_free(sc, m);
2072
2073	return (rv);
2074}
2075
2076int
2077mfii_my_intr(struct mfii_softc *sc)
2078{
2079	u_int32_t status;
2080
2081	status = mfii_read(sc, MFI_OSTS);
2082	if (ISSET(status, 0x1)) {
2083		mfii_write(sc, MFI_OSTS, status);
2084		return (1);
2085	}
2086
2087	return (ISSET(status, MFII_OSTS_INTR_VALID) ? 1 : 0);
2088}
2089
2090int
2091mfii_intr(void *arg)
2092{
2093	struct mfii_softc *sc = arg;
2094
2095	if (!mfii_my_intr(sc))
2096		return (0);
2097
2098	mfii_postq(sc);
2099
2100	return (1);
2101}
2102
2103void
2104mfii_postq(struct mfii_softc *sc)
2105{
2106	struct mfii_ccb_list ccbs = SIMPLEQ_HEAD_INITIALIZER(ccbs);
2107	struct mpii_reply_descr *postq = MFII_DMA_KVA(sc->sc_reply_postq);
2108	struct mpii_reply_descr *rdp;
2109	struct mfii_ccb *ccb;
2110	int rpi = 0;
2111
2112	mtx_enter(&sc->sc_reply_postq_mtx);
2113
2114	bus_dmamap_sync(sc->sc_dmat, MFII_DMA_MAP(sc->sc_reply_postq),
2115	    0, MFII_DMA_LEN(sc->sc_reply_postq),
2116	    BUS_DMASYNC_POSTREAD);
2117
2118	for (;;) {
2119		rdp = &postq[sc->sc_reply_postq_index];
2120		if ((rdp->reply_flags & MPII_REPLY_DESCR_TYPE_MASK) ==
2121		    MPII_REPLY_DESCR_UNUSED)
2122			break;
2123		if (rdp->data == 0xffffffff) {
2124			/*
2125			 * ioc is still writing to the reply post queue
2126			 * race condition - bail!
2127			 */
2128			break;
2129		}
2130
2131		ccb = &sc->sc_ccb[letoh16(rdp->smid) - 1];
2132		SIMPLEQ_INSERT_TAIL(&ccbs, ccb, ccb_link);
2133		memset(rdp, 0xff, sizeof(*rdp));
2134
2135		sc->sc_reply_postq_index++;
2136		sc->sc_reply_postq_index %= sc->sc_reply_postq_depth;
2137		rpi = 1;
2138	}
2139
2140	bus_dmamap_sync(sc->sc_dmat, MFII_DMA_MAP(sc->sc_reply_postq),
2141	    0, MFII_DMA_LEN(sc->sc_reply_postq),
2142	    BUS_DMASYNC_PREREAD);
2143
2144	if (rpi)
2145		mfii_write(sc, MFII_RPI, sc->sc_reply_postq_index);
2146
2147	mtx_leave(&sc->sc_reply_postq_mtx);
2148
2149	while ((ccb = SIMPLEQ_FIRST(&ccbs)) != NULL) {
2150		SIMPLEQ_REMOVE_HEAD(&ccbs, ccb_link);
2151		mfii_done(sc, ccb);
2152	}
2153}
2154
2155void
2156mfii_scsi_cmd(struct scsi_xfer *xs)
2157{
2158	struct scsi_link *link = xs->sc_link;
2159	struct mfii_softc *sc = link->bus->sb_adapter_softc;
2160	struct mfii_ccb *ccb = xs->io;
2161
2162	mfii_scrub_ccb(ccb);
2163	ccb->ccb_cookie = xs;
2164	ccb->ccb_done = mfii_scsi_cmd_done;
2165	ccb->ccb_data = xs->data;
2166	ccb->ccb_len = xs->datalen;
2167
2168	timeout_set(&xs->stimeout, mfii_scsi_cmd_tmo, xs);
2169
2170	switch (xs->cmd.opcode) {
2171	case READ_COMMAND:
2172	case READ_10:
2173	case READ_12:
2174	case READ_16:
2175	case WRITE_COMMAND:
2176	case WRITE_10:
2177	case WRITE_12:
2178	case WRITE_16:
2179		if (mfii_scsi_cmd_io(sc, xs) != 0)
2180			goto stuffup;
2181
2182		break;
2183
2184	default:
2185		if (mfii_scsi_cmd_cdb(sc, xs) != 0)
2186			goto stuffup;
2187		break;
2188	}
2189
2190	xs->error = XS_NOERROR;
2191	xs->resid = 0;
2192
2193	if (ISSET(xs->flags, SCSI_POLL)) {
2194		if (mfii_poll(sc, ccb) != 0)
2195			goto stuffup;
2196		return;
2197	}
2198
2199	ccb->ccb_refcnt = 2; /* one for the chip, one for the timeout */
2200	timeout_add_msec(&xs->stimeout, xs->timeout);
2201	mfii_start(sc, ccb);
2202
2203	return;
2204
2205stuffup:
2206	xs->error = XS_DRIVER_STUFFUP;
2207	scsi_done(xs);
2208}
2209
2210void
2211mfii_scsi_cmd_done(struct mfii_softc *sc, struct mfii_ccb *ccb)
2212{
2213	struct scsi_xfer *xs = ccb->ccb_cookie;
2214	struct mpii_msg_scsi_io *io = ccb->ccb_request;
2215	struct mfii_raid_context *ctx = (struct mfii_raid_context *)(io + 1);
2216	u_int refs = 1;
2217
2218	if (timeout_del(&xs->stimeout))
2219		refs = 2;
2220
2221	switch (ctx->status) {
2222	case MFI_STAT_OK:
2223		break;
2224
2225	case MFI_STAT_SCSI_DONE_WITH_ERROR:
2226		xs->error = XS_SENSE;
2227		memset(&xs->sense, 0, sizeof(xs->sense));
2228		memcpy(&xs->sense, ccb->ccb_sense, sizeof(xs->sense));
2229		break;
2230
2231	case MFI_STAT_LD_OFFLINE:
2232	case MFI_STAT_DEVICE_NOT_FOUND:
2233		xs->error = XS_SELTIMEOUT;
2234		break;
2235
2236	default:
2237		xs->error = XS_DRIVER_STUFFUP;
2238		break;
2239	}
2240
2241	if (atomic_sub_int_nv(&ccb->ccb_refcnt, refs) == 0)
2242		scsi_done(xs);
2243}
2244
2245int
2246mfii_scsi_ioctl(struct scsi_link *link, u_long cmd, caddr_t addr, int flag)
2247{
2248	struct mfii_softc	*sc = link->bus->sb_adapter_softc;
2249
2250	DNPRINTF(MFII_D_IOCTL, "%s: mfii_scsi_ioctl\n", DEVNAME(sc));
2251
2252	switch (cmd) {
2253	case DIOCGCACHE:
2254	case DIOCSCACHE:
2255		return (mfii_ioctl_cache(link, cmd, (struct dk_cache *)addr));
2256		break;
2257
2258	default:
2259		if (sc->sc_ioctl)
2260			return (sc->sc_ioctl(&sc->sc_dev, cmd, addr));
2261		break;
2262	}
2263
2264	return (ENOTTY);
2265}
2266
2267int
2268mfii_ioctl_cache(struct scsi_link *link, u_long cmd,  struct dk_cache *dc)
2269{
2270	struct mfii_softc	*sc = link->bus->sb_adapter_softc;
2271	int			 rv, wrenable, rdenable;
2272	struct mfi_ld_prop	 ldp;
2273	union mfi_mbox		 mbox;
2274
2275	if (mfii_get_info(sc)) {
2276		rv = EIO;
2277		goto done;
2278	}
2279
2280	if (sc->sc_target_lds[link->target] == -1) {
2281		rv = EIO;
2282		goto done;
2283	}
2284
2285	memset(&mbox, 0, sizeof(mbox));
2286	mbox.b[0] = link->target;
2287	rv = mfii_mgmt(sc, MR_DCMD_LD_GET_PROPERTIES, &mbox, &ldp, sizeof(ldp),
2288	    SCSI_DATA_IN);
2289	if (rv != 0)
2290		goto done;
2291
2292	if (sc->sc_info.mci_memory_size > 0) {
2293		wrenable = ISSET(ldp.mlp_cur_cache_policy,
2294		    MR_LD_CACHE_ALLOW_WRITE_CACHE)? 1 : 0;
2295		rdenable = ISSET(ldp.mlp_cur_cache_policy,
2296		    MR_LD_CACHE_ALLOW_READ_CACHE)? 1 : 0;
2297	} else {
2298		wrenable = ISSET(ldp.mlp_diskcache_policy,
2299		    MR_LD_DISK_CACHE_ENABLE)? 1 : 0;
2300		rdenable = 0;
2301	}
2302
2303	if (cmd == DIOCGCACHE) {
2304		dc->wrcache = wrenable;
2305		dc->rdcache = rdenable;
2306		goto done;
2307	} /* else DIOCSCACHE */
2308
2309	if (((dc->wrcache) ? 1 : 0) == wrenable &&
2310	    ((dc->rdcache) ? 1 : 0) == rdenable)
2311		goto done;
2312
2313	memset(&mbox, 0, sizeof(mbox));
2314	mbox.b[0] = ldp.mlp_ld.mld_target;
2315	mbox.b[1] = ldp.mlp_ld.mld_res;
2316	mbox.s[1] = ldp.mlp_ld.mld_seq;
2317
2318	if (sc->sc_info.mci_memory_size > 0) {
2319		if (dc->rdcache)
2320			SET(ldp.mlp_cur_cache_policy,
2321			    MR_LD_CACHE_ALLOW_READ_CACHE);
2322		else
2323			CLR(ldp.mlp_cur_cache_policy,
2324			    MR_LD_CACHE_ALLOW_READ_CACHE);
2325		if (dc->wrcache)
2326			SET(ldp.mlp_cur_cache_policy,
2327			    MR_LD_CACHE_ALLOW_WRITE_CACHE);
2328		else
2329			CLR(ldp.mlp_cur_cache_policy,
2330			    MR_LD_CACHE_ALLOW_WRITE_CACHE);
2331	} else {
2332		if (dc->rdcache) {
2333			rv = EOPNOTSUPP;
2334			goto done;
2335		}
2336		if (dc->wrcache)
2337			ldp.mlp_diskcache_policy = MR_LD_DISK_CACHE_ENABLE;
2338		else
2339			ldp.mlp_diskcache_policy = MR_LD_DISK_CACHE_DISABLE;
2340	}
2341
2342	rv = mfii_mgmt(sc, MR_DCMD_LD_SET_PROPERTIES, &mbox, &ldp, sizeof(ldp),
2343	    SCSI_DATA_OUT);
2344done:
2345	return (rv);
2346}
2347
2348int
2349mfii_scsi_cmd_io(struct mfii_softc *sc, struct scsi_xfer *xs)
2350{
2351	struct scsi_link *link = xs->sc_link;
2352	struct mfii_ccb *ccb = xs->io;
2353	struct mpii_msg_scsi_io *io = ccb->ccb_request;
2354	struct mfii_raid_context *ctx = (struct mfii_raid_context *)(io + 1);
2355	int segs;
2356
2357	io->dev_handle = htole16(link->target);
2358	io->function = MFII_FUNCTION_LDIO_REQUEST;
2359	io->sense_buffer_low_address = htole32(ccb->ccb_sense_dva);
2360	io->sgl_flags = htole16(0x02); /* XXX */
2361	io->sense_buffer_length = sizeof(xs->sense);
2362	io->sgl_offset0 = (sizeof(*io) + sizeof(*ctx)) / 4;
2363	io->data_length = htole32(xs->datalen);
2364	io->io_flags = htole16(xs->cmdlen);
2365	switch (xs->flags & (SCSI_DATA_IN | SCSI_DATA_OUT)) {
2366	case SCSI_DATA_IN:
2367		ccb->ccb_direction = MFII_DATA_IN;
2368		io->direction = MPII_SCSIIO_DIR_READ;
2369		break;
2370	case SCSI_DATA_OUT:
2371		ccb->ccb_direction = MFII_DATA_OUT;
2372		io->direction = MPII_SCSIIO_DIR_WRITE;
2373		break;
2374	default:
2375		ccb->ccb_direction = MFII_DATA_NONE;
2376		io->direction = MPII_SCSIIO_DIR_NONE;
2377		break;
2378	}
2379	memcpy(io->cdb, &xs->cmd, xs->cmdlen);
2380
2381	ctx->type_nseg = sc->sc_iop->ldio_ctx_type_nseg;
2382	ctx->timeout_value = htole16(0x14); /* XXX */
2383	ctx->reg_lock_flags = htole16(sc->sc_iop->ldio_ctx_reg_lock_flags);
2384	ctx->virtual_disk_target_id = htole16(link->target);
2385
2386	if (mfii_load_ccb(sc, ccb, ctx + 1,
2387	    ISSET(xs->flags, SCSI_NOSLEEP)) != 0)
2388		return (1);
2389
2390	segs = (ccb->ccb_len == 0) ? 0 : ccb->ccb_dmamap->dm_nsegs;
2391	switch (sc->sc_iop->num_sge_loc) {
2392	case MFII_IOP_NUM_SGE_LOC_ORIG:
2393		ctx->num_sge = segs;
2394		break;
2395	case MFII_IOP_NUM_SGE_LOC_35:
2396		/* 12 bit field, but we're only using the lower 8 */
2397		ctx->span_arm = segs;
2398		break;
2399	}
2400
2401	ccb->ccb_req.flags = sc->sc_iop->ldio_req_type;
2402	ccb->ccb_req.smid = letoh16(ccb->ccb_smid);
2403
2404	return (0);
2405}
2406
2407int
2408mfii_scsi_cmd_cdb(struct mfii_softc *sc, struct scsi_xfer *xs)
2409{
2410	struct scsi_link *link = xs->sc_link;
2411	struct mfii_ccb *ccb = xs->io;
2412	struct mpii_msg_scsi_io *io = ccb->ccb_request;
2413	struct mfii_raid_context *ctx = (struct mfii_raid_context *)(io + 1);
2414
2415	io->dev_handle = htole16(link->target);
2416	io->function = MFII_FUNCTION_LDIO_REQUEST;
2417	io->sense_buffer_low_address = htole32(ccb->ccb_sense_dva);
2418	io->sgl_flags = htole16(0x02); /* XXX */
2419	io->sense_buffer_length = sizeof(xs->sense);
2420	io->sgl_offset0 = (sizeof(*io) + sizeof(*ctx)) / 4;
2421	io->data_length = htole32(xs->datalen);
2422	io->io_flags = htole16(xs->cmdlen);
2423	io->lun[0] = htobe16(link->lun);
2424	switch (xs->flags & (SCSI_DATA_IN | SCSI_DATA_OUT)) {
2425	case SCSI_DATA_IN:
2426		ccb->ccb_direction = MFII_DATA_IN;
2427		io->direction = MPII_SCSIIO_DIR_READ;
2428		break;
2429	case SCSI_DATA_OUT:
2430		ccb->ccb_direction = MFII_DATA_OUT;
2431		io->direction = MPII_SCSIIO_DIR_WRITE;
2432		break;
2433	default:
2434		ccb->ccb_direction = MFII_DATA_NONE;
2435		io->direction = MPII_SCSIIO_DIR_NONE;
2436		break;
2437	}
2438	memcpy(io->cdb, &xs->cmd, xs->cmdlen);
2439
2440	ctx->virtual_disk_target_id = htole16(link->target);
2441
2442	if (mfii_load_ccb(sc, ccb, ctx + 1,
2443	    ISSET(xs->flags, SCSI_NOSLEEP)) != 0)
2444		return (1);
2445
2446	ctx->num_sge = (ccb->ccb_len == 0) ? 0 : ccb->ccb_dmamap->dm_nsegs;
2447
2448	ccb->ccb_req.flags = MFII_REQ_TYPE_SCSI;
2449	ccb->ccb_req.smid = letoh16(ccb->ccb_smid);
2450
2451	return (0);
2452}
2453
2454void
2455mfii_pd_scsi_cmd(struct scsi_xfer *xs)
2456{
2457	struct scsi_link *link = xs->sc_link;
2458	struct mfii_softc *sc = link->bus->sb_adapter_softc;
2459	struct mfii_ccb *ccb = xs->io;
2460
2461	mfii_scrub_ccb(ccb);
2462	ccb->ccb_cookie = xs;
2463	ccb->ccb_done = mfii_scsi_cmd_done;
2464	ccb->ccb_data = xs->data;
2465	ccb->ccb_len = xs->datalen;
2466
2467	timeout_set(&xs->stimeout, mfii_scsi_cmd_tmo, xs);
2468
2469	xs->error = mfii_pd_scsi_cmd_cdb(sc, xs);
2470	if (xs->error != XS_NOERROR)
2471		goto done;
2472
2473	xs->resid = 0;
2474
2475	if (ISSET(xs->flags, SCSI_POLL)) {
2476		if (mfii_poll(sc, ccb) != 0)
2477			goto stuffup;
2478		return;
2479	}
2480
2481	ccb->ccb_refcnt = 2; /* one for the chip, one for the timeout */
2482	timeout_add_msec(&xs->stimeout, xs->timeout);
2483	mfii_start(sc, ccb);
2484
2485	return;
2486
2487stuffup:
2488	xs->error = XS_DRIVER_STUFFUP;
2489done:
2490	scsi_done(xs);
2491}
2492
2493int
2494mfii_pd_scsi_probe(struct scsi_link *link)
2495{
2496	struct mfii_softc *sc = link->bus->sb_adapter_softc;
2497	struct mfi_pd_details mpd;
2498	union mfi_mbox mbox;
2499	int rv;
2500
2501	if (link->lun > 0)
2502		return (0);
2503
2504	memset(&mbox, 0, sizeof(mbox));
2505	mbox.s[0] = htole16(link->target);
2506
2507	rv = mfii_mgmt(sc, MR_DCMD_PD_GET_INFO, &mbox, &mpd, sizeof(mpd),
2508	    SCSI_DATA_IN|SCSI_NOSLEEP);
2509	if (rv != 0)
2510		return (EIO);
2511
2512	if (mpd.mpd_fw_state != htole16(MFI_PD_SYSTEM))
2513		return (ENXIO);
2514
2515	return (0);
2516}
2517
2518int
2519mfii_pd_scsi_cmd_cdb(struct mfii_softc *sc, struct scsi_xfer *xs)
2520{
2521	struct scsi_link *link = xs->sc_link;
2522	struct mfii_ccb *ccb = xs->io;
2523	struct mpii_msg_scsi_io *io = ccb->ccb_request;
2524	struct mfii_raid_context *ctx = (struct mfii_raid_context *)(io + 1);
2525	uint16_t dev_handle;
2526
2527	dev_handle = mfii_dev_handle(sc, link->target);
2528	if (dev_handle == htole16(0xffff))
2529		return (XS_SELTIMEOUT);
2530
2531	io->dev_handle = dev_handle;
2532	io->function = 0;
2533	io->sense_buffer_low_address = htole32(ccb->ccb_sense_dva);
2534	io->sgl_flags = htole16(0x02); /* XXX */
2535	io->sense_buffer_length = sizeof(xs->sense);
2536	io->sgl_offset0 = (sizeof(*io) + sizeof(*ctx)) / 4;
2537	io->data_length = htole32(xs->datalen);
2538	io->io_flags = htole16(xs->cmdlen);
2539	io->lun[0] = htobe16(link->lun);
2540	switch (xs->flags & (SCSI_DATA_IN | SCSI_DATA_OUT)) {
2541	case SCSI_DATA_IN:
2542		ccb->ccb_direction = MFII_DATA_IN;
2543		io->direction = MPII_SCSIIO_DIR_READ;
2544		break;
2545	case SCSI_DATA_OUT:
2546		ccb->ccb_direction = MFII_DATA_OUT;
2547		io->direction = MPII_SCSIIO_DIR_WRITE;
2548		break;
2549	default:
2550		ccb->ccb_direction = MFII_DATA_NONE;
2551		io->direction = MPII_SCSIIO_DIR_NONE;
2552		break;
2553	}
2554	memcpy(io->cdb, &xs->cmd, xs->cmdlen);
2555
2556	ctx->virtual_disk_target_id = htole16(link->target);
2557	ctx->raid_flags = MFII_RAID_CTX_IO_TYPE_SYSPD;
2558	ctx->timeout_value = sc->sc_pd->pd_timeout;
2559
2560	if (mfii_load_ccb(sc, ccb, ctx + 1,
2561	    ISSET(xs->flags, SCSI_NOSLEEP)) != 0)
2562		return (XS_DRIVER_STUFFUP);
2563
2564	ctx->num_sge = (ccb->ccb_len == 0) ? 0 : ccb->ccb_dmamap->dm_nsegs;
2565
2566	ccb->ccb_req.flags = MFII_REQ_TYPE_HI_PRI;
2567	ccb->ccb_req.smid = letoh16(ccb->ccb_smid);
2568	ccb->ccb_req.dev_handle = dev_handle;
2569
2570	return (XS_NOERROR);
2571}
2572
2573int
2574mfii_load_ccb(struct mfii_softc *sc, struct mfii_ccb *ccb, void *sglp,
2575    int nosleep)
2576{
2577	struct mpii_msg_request *req = ccb->ccb_request;
2578	struct mfii_sge *sge = NULL, *nsge = sglp;
2579	struct mfii_sge *ce = NULL;
2580	bus_dmamap_t dmap = ccb->ccb_dmamap;
2581	u_int space;
2582	int i;
2583
2584	int error;
2585
2586	if (ccb->ccb_len == 0)
2587		return (0);
2588
2589	error = bus_dmamap_load(sc->sc_dmat, dmap,
2590	    ccb->ccb_data, ccb->ccb_len, NULL,
2591	    nosleep ? BUS_DMA_NOWAIT : BUS_DMA_WAITOK);
2592	if (error) {
2593		printf("%s: error %d loading dmamap\n", DEVNAME(sc), error);
2594		return (1);
2595	}
2596
2597	space = (MFII_REQUEST_SIZE - ((u_int8_t *)nsge - (u_int8_t *)req)) /
2598	    sizeof(*nsge);
2599	if (dmap->dm_nsegs > space) {
2600		space--;
2601
2602		ccb->ccb_sgl_len = (dmap->dm_nsegs - space) * sizeof(*nsge);
2603		memset(ccb->ccb_sgl, 0, ccb->ccb_sgl_len);
2604
2605		ce = nsge + space;
2606		ce->sg_addr = htole64(ccb->ccb_sgl_dva);
2607		ce->sg_len = htole32(ccb->ccb_sgl_len);
2608		ce->sg_flags = sc->sc_iop->sge_flag_chain;
2609
2610		req->chain_offset = ((u_int8_t *)ce - (u_int8_t *)req) / 16;
2611	}
2612
2613	for (i = 0; i < dmap->dm_nsegs; i++) {
2614		if (nsge == ce)
2615			nsge = ccb->ccb_sgl;
2616
2617		sge = nsge;
2618
2619		sge->sg_addr = htole64(dmap->dm_segs[i].ds_addr);
2620		sge->sg_len = htole32(dmap->dm_segs[i].ds_len);
2621		sge->sg_flags = MFII_SGE_ADDR_SYSTEM;
2622
2623		nsge = sge + 1;
2624	}
2625	sge->sg_flags |= sc->sc_iop->sge_flag_eol;
2626
2627	bus_dmamap_sync(sc->sc_dmat, dmap, 0, dmap->dm_mapsize,
2628	    ccb->ccb_direction == MFII_DATA_OUT ?
2629	    BUS_DMASYNC_PREWRITE : BUS_DMASYNC_PREREAD);
2630
2631	if (ccb->ccb_sgl_len > 0) {
2632		bus_dmamap_sync(sc->sc_dmat, MFII_DMA_MAP(sc->sc_sgl),
2633		    ccb->ccb_sgl_offset, ccb->ccb_sgl_len,
2634		    BUS_DMASYNC_PREWRITE);
2635	}
2636
2637	return (0);
2638}
2639
2640void
2641mfii_scsi_cmd_tmo(void *xsp)
2642{
2643	struct scsi_xfer *xs = xsp;
2644	struct scsi_link *link = xs->sc_link;
2645	struct mfii_softc *sc = link->bus->sb_adapter_softc;
2646	struct mfii_ccb *ccb = xs->io;
2647
2648	mtx_enter(&sc->sc_abort_mtx);
2649	SIMPLEQ_INSERT_TAIL(&sc->sc_abort_list, ccb, ccb_link);
2650	mtx_leave(&sc->sc_abort_mtx);
2651
2652	task_add(systqmp, &sc->sc_abort_task);
2653}
2654
2655void
2656mfii_abort_task(void *scp)
2657{
2658	struct mfii_softc *sc = scp;
2659	struct mfii_ccb *list;
2660
2661	mtx_enter(&sc->sc_abort_mtx);
2662	list = SIMPLEQ_FIRST(&sc->sc_abort_list);
2663	SIMPLEQ_INIT(&sc->sc_abort_list);
2664	mtx_leave(&sc->sc_abort_mtx);
2665
2666	while (list != NULL) {
2667		struct mfii_ccb *ccb = list;
2668		struct scsi_xfer *xs = ccb->ccb_cookie;
2669		struct scsi_link *link = xs->sc_link;
2670
2671		uint16_t dev_handle;
2672		struct mfii_ccb *accb;
2673
2674		list = SIMPLEQ_NEXT(ccb, ccb_link);
2675
2676		dev_handle = mfii_dev_handle(sc, link->target);
2677		if (dev_handle == htole16(0xffff)) {
2678			/* device is gone */
2679			if (atomic_dec_int_nv(&ccb->ccb_refcnt) == 0)
2680				scsi_done(xs);
2681			continue;
2682		}
2683
2684		accb = scsi_io_get(&sc->sc_iopool, 0);
2685		mfii_scrub_ccb(accb);
2686		mfii_abort(sc, accb, dev_handle, ccb->ccb_smid,
2687		    MPII_SCSI_TASK_ABORT_TASK,
2688		    htole32(MFII_TASK_MGMT_FLAGS_PD));
2689
2690		accb->ccb_cookie = ccb;
2691		accb->ccb_done = mfii_scsi_cmd_abort_done;
2692
2693		mfii_start(sc, accb);
2694	}
2695}
2696
2697void
2698mfii_abort(struct mfii_softc *sc, struct mfii_ccb *accb, uint16_t dev_handle,
2699    uint16_t smid, uint8_t type, uint32_t flags)
2700{
2701	struct mfii_task_mgmt *msg;
2702	struct mpii_msg_scsi_task_request *req;
2703
2704	msg = accb->ccb_request;
2705	req = &msg->mpii_request;
2706	req->dev_handle = dev_handle;
2707	req->function = MPII_FUNCTION_SCSI_TASK_MGMT;
2708	req->task_type = type;
2709	htolem16(&req->task_mid, smid);
2710	msg->flags = flags;
2711
2712	accb->ccb_req.flags = MFII_REQ_TYPE_HI_PRI;
2713	accb->ccb_req.smid = letoh16(accb->ccb_smid);
2714}
2715
2716void
2717mfii_scsi_cmd_abort_done(struct mfii_softc *sc, struct mfii_ccb *accb)
2718{
2719	struct mfii_ccb *ccb = accb->ccb_cookie;
2720	struct scsi_xfer *xs = ccb->ccb_cookie;
2721
2722	/* XXX check accb completion? */
2723
2724	scsi_io_put(&sc->sc_iopool, accb);
2725
2726	if (atomic_dec_int_nv(&ccb->ccb_refcnt) == 0)
2727		scsi_done(xs);
2728}
2729
2730void *
2731mfii_get_ccb(void *cookie)
2732{
2733	struct mfii_softc *sc = cookie;
2734	struct mfii_ccb *ccb;
2735
2736	mtx_enter(&sc->sc_ccb_mtx);
2737	ccb = SIMPLEQ_FIRST(&sc->sc_ccb_freeq);
2738	if (ccb != NULL)
2739		SIMPLEQ_REMOVE_HEAD(&sc->sc_ccb_freeq, ccb_link);
2740	mtx_leave(&sc->sc_ccb_mtx);
2741
2742	return (ccb);
2743}
2744
2745void
2746mfii_scrub_ccb(struct mfii_ccb *ccb)
2747{
2748	ccb->ccb_cookie = NULL;
2749	ccb->ccb_done = NULL;
2750	ccb->ccb_flags = 0;
2751	ccb->ccb_data = NULL;
2752	ccb->ccb_direction = 0;
2753	ccb->ccb_len = 0;
2754	ccb->ccb_sgl_len = 0;
2755	ccb->ccb_refcnt = 1;
2756
2757	memset(&ccb->ccb_req, 0, sizeof(ccb->ccb_req));
2758	memset(ccb->ccb_request, 0, MFII_REQUEST_SIZE);
2759	memset(ccb->ccb_mfi, 0, MFI_FRAME_SIZE);
2760}
2761
2762void
2763mfii_put_ccb(void *cookie, void *io)
2764{
2765	struct mfii_softc *sc = cookie;
2766	struct mfii_ccb *ccb = io;
2767
2768	mtx_enter(&sc->sc_ccb_mtx);
2769	SIMPLEQ_INSERT_HEAD(&sc->sc_ccb_freeq, ccb, ccb_link);
2770	mtx_leave(&sc->sc_ccb_mtx);
2771}
2772
2773int
2774mfii_init_ccb(struct mfii_softc *sc)
2775{
2776	struct mfii_ccb *ccb;
2777	u_int8_t *request = MFII_DMA_KVA(sc->sc_requests);
2778	u_int8_t *mfi = MFII_DMA_KVA(sc->sc_mfi);
2779	u_int8_t *sense = MFII_DMA_KVA(sc->sc_sense);
2780	u_int8_t *sgl = MFII_DMA_KVA(sc->sc_sgl);
2781	u_int i;
2782	int error;
2783
2784	sc->sc_ccb = mallocarray(sc->sc_max_cmds, sizeof(struct mfii_ccb),
2785	    M_DEVBUF, M_WAITOK|M_ZERO);
2786
2787	for (i = 0; i < sc->sc_max_cmds; i++) {
2788		ccb = &sc->sc_ccb[i];
2789
2790		/* create a dma map for transfer */
2791		error = bus_dmamap_create(sc->sc_dmat,
2792		    MAXPHYS, sc->sc_max_sgl, MAXPHYS, 0,
2793		    BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW, &ccb->ccb_dmamap);
2794		if (error) {
2795			printf("%s: cannot create ccb dmamap (%d)\n",
2796			    DEVNAME(sc), error);
2797			goto destroy;
2798		}
2799
2800		/* select i + 1'th request. 0 is reserved for events */
2801		ccb->ccb_smid = i + 1;
2802		ccb->ccb_request_offset = MFII_REQUEST_SIZE * (i + 1);
2803		ccb->ccb_request = request + ccb->ccb_request_offset;
2804		ccb->ccb_request_dva = MFII_DMA_DVA(sc->sc_requests) +
2805		    ccb->ccb_request_offset;
2806
2807		/* select i'th MFI command frame */
2808		ccb->ccb_mfi_offset = MFI_FRAME_SIZE * i;
2809		ccb->ccb_mfi = mfi + ccb->ccb_mfi_offset;
2810		ccb->ccb_mfi_dva = MFII_DMA_DVA(sc->sc_mfi) +
2811		    ccb->ccb_mfi_offset;
2812
2813		/* select i'th sense */
2814		ccb->ccb_sense_offset = MFI_SENSE_SIZE * i;
2815		ccb->ccb_sense = (struct mfi_sense *)(sense +
2816		    ccb->ccb_sense_offset);
2817		ccb->ccb_sense_dva = MFII_DMA_DVA(sc->sc_sense) +
2818		    ccb->ccb_sense_offset;
2819
2820		/* select i'th sgl */
2821		ccb->ccb_sgl_offset = sizeof(struct mfii_sge) *
2822		    sc->sc_max_sgl * i;
2823		ccb->ccb_sgl = (struct mfii_sge *)(sgl + ccb->ccb_sgl_offset);
2824		ccb->ccb_sgl_dva = MFII_DMA_DVA(sc->sc_sgl) +
2825		    ccb->ccb_sgl_offset;
2826
2827		/* add ccb to queue */
2828		mfii_put_ccb(sc, ccb);
2829	}
2830
2831	return (0);
2832
2833destroy:
2834	/* free dma maps and ccb memory */
2835	while ((ccb = mfii_get_ccb(sc)) != NULL)
2836		bus_dmamap_destroy(sc->sc_dmat, ccb->ccb_dmamap);
2837
2838	free(sc->sc_ccb, M_DEVBUF, 0);
2839
2840	return (1);
2841}
2842
2843#if NBIO > 0
2844int
2845mfii_ioctl(struct device *dev, u_long cmd, caddr_t addr)
2846{
2847	struct mfii_softc	*sc = (struct mfii_softc *)dev;
2848	int error = 0;
2849
2850	DNPRINTF(MFII_D_IOCTL, "%s: mfii_ioctl ", DEVNAME(sc));
2851
2852	rw_enter_write(&sc->sc_lock);
2853
2854	switch (cmd) {
2855	case BIOCINQ:
2856		DNPRINTF(MFII_D_IOCTL, "inq\n");
2857		error = mfii_ioctl_inq(sc, (struct bioc_inq *)addr);
2858		break;
2859
2860	case BIOCVOL:
2861		DNPRINTF(MFII_D_IOCTL, "vol\n");
2862		error = mfii_ioctl_vol(sc, (struct bioc_vol *)addr);
2863		break;
2864
2865	case BIOCDISK:
2866		DNPRINTF(MFII_D_IOCTL, "disk\n");
2867		error = mfii_ioctl_disk(sc, (struct bioc_disk *)addr);
2868		break;
2869
2870	case BIOCALARM:
2871		DNPRINTF(MFII_D_IOCTL, "alarm\n");
2872		error = mfii_ioctl_alarm(sc, (struct bioc_alarm *)addr);
2873		break;
2874
2875	case BIOCBLINK:
2876		DNPRINTF(MFII_D_IOCTL, "blink\n");
2877		error = mfii_ioctl_blink(sc, (struct bioc_blink *)addr);
2878		break;
2879
2880	case BIOCSETSTATE:
2881		DNPRINTF(MFII_D_IOCTL, "setstate\n");
2882		error = mfii_ioctl_setstate(sc, (struct bioc_setstate *)addr);
2883		break;
2884
2885	case BIOCPATROL:
2886		DNPRINTF(MFII_D_IOCTL, "patrol\n");
2887		error = mfii_ioctl_patrol(sc, (struct bioc_patrol *)addr);
2888		break;
2889
2890	default:
2891		DNPRINTF(MFII_D_IOCTL, " invalid ioctl\n");
2892		error = ENOTTY;
2893	}
2894
2895	rw_exit_write(&sc->sc_lock);
2896
2897	return (error);
2898}
2899
2900int
2901mfii_bio_getitall(struct mfii_softc *sc)
2902{
2903	int			i, d, rv = EINVAL;
2904	size_t			size;
2905	union mfi_mbox		mbox;
2906	struct mfi_conf		*cfg = NULL;
2907	struct mfi_ld_details	*ld_det = NULL;
2908
2909	/* get info */
2910	if (mfii_get_info(sc)) {
2911		DNPRINTF(MFII_D_IOCTL, "%s: mfii_get_info failed\n",
2912		    DEVNAME(sc));
2913		goto done;
2914	}
2915
2916	/* send single element command to retrieve size for full structure */
2917	cfg = malloc(sizeof *cfg, M_DEVBUF, M_NOWAIT | M_ZERO);
2918	if (cfg == NULL)
2919		goto done;
2920	if (mfii_mgmt(sc, MR_DCMD_CONF_GET, NULL, cfg, sizeof(*cfg),
2921	    SCSI_DATA_IN)) {
2922		free(cfg, M_DEVBUF, sizeof *cfg);
2923		goto done;
2924	}
2925
2926	size = cfg->mfc_size;
2927	free(cfg, M_DEVBUF, sizeof *cfg);
2928
2929	/* memory for read config */
2930	cfg = malloc(size, M_DEVBUF, M_NOWAIT | M_ZERO);
2931	if (cfg == NULL)
2932		goto done;
2933	if (mfii_mgmt(sc, MR_DCMD_CONF_GET, NULL, cfg, size, SCSI_DATA_IN)) {
2934		free(cfg, M_DEVBUF, size);
2935		goto done;
2936	}
2937
2938	/* replace current pointer with new one */
2939	if (sc->sc_cfg)
2940		free(sc->sc_cfg, M_DEVBUF, 0);
2941	sc->sc_cfg = cfg;
2942
2943	/* get all ld info */
2944	if (mfii_mgmt(sc, MR_DCMD_LD_GET_LIST, NULL, &sc->sc_ld_list,
2945	    sizeof(sc->sc_ld_list), SCSI_DATA_IN))
2946		goto done;
2947
2948	/* get memory for all ld structures */
2949	size = cfg->mfc_no_ld * sizeof(struct mfi_ld_details);
2950	if (sc->sc_ld_sz != size) {
2951		if (sc->sc_ld_details)
2952			free(sc->sc_ld_details, M_DEVBUF, 0);
2953
2954		ld_det = malloc(size, M_DEVBUF, M_NOWAIT | M_ZERO);
2955		if (ld_det == NULL)
2956			goto done;
2957		sc->sc_ld_sz = size;
2958		sc->sc_ld_details = ld_det;
2959	}
2960
2961	/* find used physical disks */
2962	size = sizeof(struct mfi_ld_details);
2963	for (i = 0, d = 0; i < cfg->mfc_no_ld; i++) {
2964		memset(&mbox, 0, sizeof(mbox));
2965		mbox.b[0] = sc->sc_ld_list.mll_list[i].mll_ld.mld_target;
2966		if (mfii_mgmt(sc, MR_DCMD_LD_GET_INFO, &mbox, &sc->sc_ld_details[i], size,
2967		    SCSI_DATA_IN))
2968			goto done;
2969
2970		d += sc->sc_ld_details[i].mld_cfg.mlc_parm.mpa_no_drv_per_span *
2971		    sc->sc_ld_details[i].mld_cfg.mlc_parm.mpa_span_depth;
2972	}
2973	sc->sc_no_pd = d;
2974
2975	rv = 0;
2976done:
2977	return (rv);
2978}
2979
2980int
2981mfii_ioctl_inq(struct mfii_softc *sc, struct bioc_inq *bi)
2982{
2983	int			rv = EINVAL;
2984	struct mfi_conf		*cfg = NULL;
2985
2986	DNPRINTF(MFII_D_IOCTL, "%s: mfii_ioctl_inq\n", DEVNAME(sc));
2987
2988	if (mfii_bio_getitall(sc)) {
2989		DNPRINTF(MFII_D_IOCTL, "%s: mfii_bio_getitall failed\n",
2990		    DEVNAME(sc));
2991		goto done;
2992	}
2993
2994	/* count unused disks as volumes */
2995	if (sc->sc_cfg == NULL)
2996		goto done;
2997	cfg = sc->sc_cfg;
2998
2999	bi->bi_nodisk = sc->sc_info.mci_pd_disks_present;
3000	bi->bi_novol = cfg->mfc_no_ld + cfg->mfc_no_hs;
3001#if notyet
3002	bi->bi_novol = cfg->mfc_no_ld + cfg->mfc_no_hs +
3003	    (bi->bi_nodisk - sc->sc_no_pd);
3004#endif
3005	/* tell bio who we are */
3006	strlcpy(bi->bi_dev, DEVNAME(sc), sizeof(bi->bi_dev));
3007
3008	rv = 0;
3009done:
3010	return (rv);
3011}
3012
3013int
3014mfii_ioctl_vol(struct mfii_softc *sc, struct bioc_vol *bv)
3015{
3016	int			i, per, target, rv = EINVAL;
3017	struct scsi_link	*link;
3018	struct device		*dev;
3019
3020	DNPRINTF(MFII_D_IOCTL, "%s: mfii_ioctl_vol %#x\n",
3021	    DEVNAME(sc), bv->bv_volid);
3022
3023	/* we really could skip and expect that inq took care of it */
3024	if (mfii_bio_getitall(sc)) {
3025		DNPRINTF(MFII_D_IOCTL, "%s: mfii_bio_getitall failed\n",
3026		    DEVNAME(sc));
3027		goto done;
3028	}
3029
3030	if (bv->bv_volid >= sc->sc_ld_list.mll_no_ld) {
3031		/* go do hotspares & unused disks */
3032		rv = mfii_bio_hs(sc, bv->bv_volid, MFI_MGMT_VD, bv);
3033		goto done;
3034	}
3035
3036	i = bv->bv_volid;
3037	target = sc->sc_ld_list.mll_list[i].mll_ld.mld_target;
3038	link = scsi_get_link(sc->sc_scsibus, target, 0);
3039	if (link == NULL) {
3040		strlcpy(bv->bv_dev, "cache", sizeof(bv->bv_dev));
3041	} else {
3042		dev = link->device_softc;
3043		if (dev == NULL)
3044			goto done;
3045
3046		strlcpy(bv->bv_dev, dev->dv_xname, sizeof(bv->bv_dev));
3047	}
3048
3049	switch(sc->sc_ld_list.mll_list[i].mll_state) {
3050	case MFI_LD_OFFLINE:
3051		bv->bv_status = BIOC_SVOFFLINE;
3052		break;
3053
3054	case MFI_LD_PART_DEGRADED:
3055	case MFI_LD_DEGRADED:
3056		bv->bv_status = BIOC_SVDEGRADED;
3057		break;
3058
3059	case MFI_LD_ONLINE:
3060		bv->bv_status = BIOC_SVONLINE;
3061		break;
3062
3063	default:
3064		bv->bv_status = BIOC_SVINVALID;
3065		DNPRINTF(MFII_D_IOCTL, "%s: invalid logical disk state %#x\n",
3066		    DEVNAME(sc),
3067		    sc->sc_ld_list.mll_list[i].mll_state);
3068	}
3069
3070	/* additional status can modify MFI status */
3071	switch (sc->sc_ld_details[i].mld_progress.mlp_in_prog) {
3072	case MFI_LD_PROG_CC:
3073		bv->bv_status = BIOC_SVSCRUB;
3074		per = (int)sc->sc_ld_details[i].mld_progress.mlp_cc.mp_progress;
3075		bv->bv_percent = (per * 100) / 0xffff;
3076		bv->bv_seconds =
3077		    sc->sc_ld_details[i].mld_progress.mlp_cc.mp_elapsed_seconds;
3078		break;
3079
3080	case MFI_LD_PROG_BGI:
3081		bv->bv_status = BIOC_SVSCRUB;
3082		per = (int)sc->sc_ld_details[i].mld_progress.mlp_bgi.mp_progress;
3083		bv->bv_percent = (per * 100) / 0xffff;
3084		bv->bv_seconds =
3085		    sc->sc_ld_details[i].mld_progress.mlp_bgi.mp_elapsed_seconds;
3086		break;
3087
3088	case MFI_LD_PROG_FGI:
3089	case MFI_LD_PROG_RECONSTRUCT:
3090		/* nothing yet */
3091		break;
3092	}
3093
3094	if (sc->sc_ld_details[i].mld_cfg.mlc_prop.mlp_cur_cache_policy & 0x01)
3095		bv->bv_cache = BIOC_CVWRITEBACK;
3096	else
3097		bv->bv_cache = BIOC_CVWRITETHROUGH;
3098
3099	/*
3100	 * The RAID levels are determined per the SNIA DDF spec, this is only
3101	 * a subset that is valid for the MFI controller.
3102	 */
3103	bv->bv_level = sc->sc_ld_details[i].mld_cfg.mlc_parm.mpa_pri_raid;
3104	if (sc->sc_ld_details[i].mld_cfg.mlc_parm.mpa_span_depth > 1)
3105		bv->bv_level *= 10;
3106
3107	bv->bv_nodisk = sc->sc_ld_details[i].mld_cfg.mlc_parm.mpa_no_drv_per_span *
3108	    sc->sc_ld_details[i].mld_cfg.mlc_parm.mpa_span_depth;
3109
3110	bv->bv_size = sc->sc_ld_details[i].mld_size * 512; /* bytes per block */
3111
3112	rv = 0;
3113done:
3114	return (rv);
3115}
3116
3117int
3118mfii_ioctl_disk(struct mfii_softc *sc, struct bioc_disk *bd)
3119{
3120	struct mfi_conf		*cfg;
3121	struct mfi_array	*ar;
3122	struct mfi_ld_cfg	*ld;
3123	struct mfi_pd_details	*pd;
3124	struct mfi_pd_list	*pl;
3125	struct mfi_pd_progress	*mfp;
3126	struct mfi_progress	*mp;
3127	struct scsi_inquiry_data *inqbuf;
3128	char			vend[8+16+4+1], *vendp;
3129	int			i, rv = EINVAL;
3130	int			arr, vol, disk, span;
3131	union mfi_mbox		mbox;
3132
3133	DNPRINTF(MFII_D_IOCTL, "%s: mfii_ioctl_disk %#x\n",
3134	    DEVNAME(sc), bd->bd_diskid);
3135
3136	/* we really could skip and expect that inq took care of it */
3137	if (mfii_bio_getitall(sc)) {
3138		DNPRINTF(MFII_D_IOCTL, "%s: mfii_bio_getitall failed\n",
3139		    DEVNAME(sc));
3140		return (rv);
3141	}
3142	cfg = sc->sc_cfg;
3143
3144	pd = malloc(sizeof *pd, M_DEVBUF, M_WAITOK);
3145	pl = malloc(sizeof *pl, M_DEVBUF, M_WAITOK);
3146
3147	ar = cfg->mfc_array;
3148	vol = bd->bd_volid;
3149	if (vol >= cfg->mfc_no_ld) {
3150		/* do hotspares */
3151		rv = mfii_bio_hs(sc, bd->bd_volid, MFI_MGMT_SD, bd);
3152		goto freeme;
3153	}
3154
3155	/* calculate offset to ld structure */
3156	ld = (struct mfi_ld_cfg *)(
3157	    ((uint8_t *)cfg) + offsetof(struct mfi_conf, mfc_array) +
3158	    cfg->mfc_array_size * cfg->mfc_no_array);
3159
3160	/* use span 0 only when raid group is not spanned */
3161	if (ld[vol].mlc_parm.mpa_span_depth > 1)
3162		span = bd->bd_diskid / ld[vol].mlc_parm.mpa_no_drv_per_span;
3163	else
3164		span = 0;
3165	arr = ld[vol].mlc_span[span].mls_index;
3166
3167	/* offset disk into pd list */
3168	disk = bd->bd_diskid % ld[vol].mlc_parm.mpa_no_drv_per_span;
3169
3170	if (ar[arr].pd[disk].mar_pd.mfp_id == 0xffffU) {
3171		/* disk is missing but succeed command */
3172		bd->bd_status = BIOC_SDFAILED;
3173		rv = 0;
3174
3175		/* try to find an unused disk for the target to rebuild */
3176		if (mfii_mgmt(sc, MR_DCMD_PD_GET_LIST, NULL, pl, sizeof(*pl),
3177		    SCSI_DATA_IN))
3178			goto freeme;
3179
3180		for (i = 0; i < pl->mpl_no_pd; i++) {
3181			if (pl->mpl_address[i].mpa_scsi_type != 0)
3182				continue;
3183
3184			memset(&mbox, 0, sizeof(mbox));
3185			mbox.s[0] = pl->mpl_address[i].mpa_pd_id;
3186			if (mfii_mgmt(sc, MR_DCMD_PD_GET_INFO, &mbox, pd, sizeof(*pd),
3187			    SCSI_DATA_IN))
3188				continue;
3189
3190			if (pd->mpd_fw_state == MFI_PD_UNCONFIG_GOOD ||
3191			    pd->mpd_fw_state == MFI_PD_UNCONFIG_BAD)
3192				break;
3193		}
3194
3195		if (i == pl->mpl_no_pd)
3196			goto freeme;
3197	} else {
3198		memset(&mbox, 0, sizeof(mbox));
3199		mbox.s[0] = ar[arr].pd[disk].mar_pd.mfp_id;
3200		if (mfii_mgmt(sc, MR_DCMD_PD_GET_INFO, &mbox, pd, sizeof(*pd),
3201		    SCSI_DATA_IN)) {
3202			bd->bd_status = BIOC_SDINVALID;
3203			goto freeme;
3204		}
3205	}
3206
3207	/* get the remaining fields */
3208	bd->bd_channel = pd->mpd_enc_idx;
3209	bd->bd_target = pd->mpd_enc_slot;
3210
3211	/* get status */
3212	switch (pd->mpd_fw_state){
3213	case MFI_PD_UNCONFIG_GOOD:
3214	case MFI_PD_UNCONFIG_BAD:
3215		bd->bd_status = BIOC_SDUNUSED;
3216		break;
3217
3218	case MFI_PD_HOTSPARE: /* XXX dedicated hotspare part of array? */
3219		bd->bd_status = BIOC_SDHOTSPARE;
3220		break;
3221
3222	case MFI_PD_OFFLINE:
3223		bd->bd_status = BIOC_SDOFFLINE;
3224		break;
3225
3226	case MFI_PD_FAILED:
3227		bd->bd_status = BIOC_SDFAILED;
3228		break;
3229
3230	case MFI_PD_REBUILD:
3231		bd->bd_status = BIOC_SDREBUILD;
3232		break;
3233
3234	case MFI_PD_ONLINE:
3235		bd->bd_status = BIOC_SDONLINE;
3236		break;
3237
3238	case MFI_PD_COPYBACK:
3239	case MFI_PD_SYSTEM:
3240	default:
3241		bd->bd_status = BIOC_SDINVALID;
3242		break;
3243	}
3244
3245	bd->bd_size = pd->mpd_size * 512; /* bytes per block */
3246
3247	inqbuf = (struct scsi_inquiry_data *)&pd->mpd_inq_data;
3248	vendp = inqbuf->vendor;
3249	memcpy(vend, vendp, sizeof vend - 1);
3250	vend[sizeof vend - 1] = '\0';
3251	strlcpy(bd->bd_vendor, vend, sizeof(bd->bd_vendor));
3252
3253	/* XXX find a way to retrieve serial nr from drive */
3254	/* XXX find a way to get bd_procdev */
3255
3256	mfp = &pd->mpd_progress;
3257	if (mfp->mfp_in_prog & MFI_PD_PROG_PR) {
3258		mp = &mfp->mfp_patrol_read;
3259		bd->bd_patrol.bdp_percent = (mp->mp_progress * 100) / 0xffff;
3260		bd->bd_patrol.bdp_seconds = mp->mp_elapsed_seconds;
3261	}
3262
3263	rv = 0;
3264freeme:
3265	free(pd, M_DEVBUF, sizeof *pd);
3266	free(pl, M_DEVBUF, sizeof *pl);
3267
3268	return (rv);
3269}
3270
3271int
3272mfii_ioctl_alarm(struct mfii_softc *sc, struct bioc_alarm *ba)
3273{
3274	uint32_t		opc, flags = 0;
3275	int			rv = 0;
3276	int8_t			ret;
3277
3278	switch(ba->ba_opcode) {
3279	case BIOC_SADISABLE:
3280		opc = MR_DCMD_SPEAKER_DISABLE;
3281		break;
3282
3283	case BIOC_SAENABLE:
3284		opc = MR_DCMD_SPEAKER_ENABLE;
3285		break;
3286
3287	case BIOC_SASILENCE:
3288		opc = MR_DCMD_SPEAKER_SILENCE;
3289		break;
3290
3291	case BIOC_GASTATUS:
3292		opc = MR_DCMD_SPEAKER_GET;
3293		flags = SCSI_DATA_IN;
3294		break;
3295
3296	case BIOC_SATEST:
3297		opc = MR_DCMD_SPEAKER_TEST;
3298		break;
3299
3300	default:
3301		DNPRINTF(MFII_D_IOCTL, "%s: mfii_ioctl_alarm biocalarm invalid "
3302		    "opcode %x\n", DEVNAME(sc), ba->ba_opcode);
3303		return (EINVAL);
3304	}
3305
3306	if (mfii_mgmt(sc, opc, NULL, &ret, sizeof(ret), flags))
3307		rv = EINVAL;
3308	else
3309		if (ba->ba_opcode == BIOC_GASTATUS)
3310			ba->ba_status = ret;
3311		else
3312			ba->ba_status = 0;
3313
3314	return (rv);
3315}
3316
3317int
3318mfii_ioctl_blink(struct mfii_softc *sc, struct bioc_blink *bb)
3319{
3320	int			i, found, rv = EINVAL;
3321	union mfi_mbox		mbox;
3322	uint32_t		cmd;
3323	struct mfi_pd_list	*pd;
3324
3325	DNPRINTF(MFII_D_IOCTL, "%s: mfii_ioctl_blink %x\n", DEVNAME(sc),
3326	    bb->bb_status);
3327
3328	/* channel 0 means not in an enclosure so can't be blinked */
3329	if (bb->bb_channel == 0)
3330		return (EINVAL);
3331
3332	pd = malloc(sizeof(*pd), M_DEVBUF, M_WAITOK);
3333
3334	if (mfii_mgmt(sc, MR_DCMD_PD_GET_LIST, NULL, pd, sizeof(*pd), SCSI_DATA_IN))
3335		goto done;
3336
3337	for (i = 0, found = 0; i < pd->mpl_no_pd; i++)
3338		if (bb->bb_channel == pd->mpl_address[i].mpa_enc_index &&
3339		    bb->bb_target == pd->mpl_address[i].mpa_enc_slot) {
3340			found = 1;
3341			break;
3342		}
3343
3344	if (!found)
3345		goto done;
3346
3347	memset(&mbox, 0, sizeof(mbox));
3348	mbox.s[0] = pd->mpl_address[i].mpa_pd_id;
3349
3350	switch (bb->bb_status) {
3351	case BIOC_SBUNBLINK:
3352		cmd = MR_DCMD_PD_UNBLINK;
3353		break;
3354
3355	case BIOC_SBBLINK:
3356		cmd = MR_DCMD_PD_BLINK;
3357		break;
3358
3359	case BIOC_SBALARM:
3360	default:
3361		DNPRINTF(MFII_D_IOCTL, "%s: mfii_ioctl_blink biocblink invalid "
3362		    "opcode %x\n", DEVNAME(sc), bb->bb_status);
3363		goto done;
3364	}
3365
3366
3367	if (mfii_mgmt(sc, cmd, &mbox, NULL, 0, 0) == 0)
3368		rv = 0;
3369
3370done:
3371	free(pd, M_DEVBUF, sizeof *pd);
3372	return (rv);
3373}
3374
3375static int
3376mfii_makegood(struct mfii_softc *sc, uint16_t pd_id)
3377{
3378	struct mfii_foreign_scan_info *fsi;
3379	struct mfi_pd_details	*pd;
3380	union mfi_mbox		mbox;
3381	int			rv;
3382
3383	fsi = malloc(sizeof *fsi, M_DEVBUF, M_WAITOK);
3384	pd = malloc(sizeof *pd, M_DEVBUF, M_WAITOK);
3385
3386	memset(&mbox, 0, sizeof mbox);
3387	mbox.s[0] = pd_id;
3388	rv = mfii_mgmt(sc, MR_DCMD_PD_GET_INFO, &mbox, pd, sizeof(*pd), SCSI_DATA_IN);
3389	if (rv != 0)
3390		goto done;
3391
3392	if (pd->mpd_fw_state == MFI_PD_UNCONFIG_BAD) {
3393		mbox.s[0] = pd_id;
3394		mbox.s[1] = pd->mpd_pd.mfp_seq;
3395		mbox.b[4] = MFI_PD_UNCONFIG_GOOD;
3396		rv = mfii_mgmt(sc, MR_DCMD_PD_SET_STATE, &mbox, NULL, 0, 0);
3397		if (rv != 0)
3398			goto done;
3399	}
3400
3401	memset(&mbox, 0, sizeof mbox);
3402	mbox.s[0] = pd_id;
3403	rv = mfii_mgmt(sc, MR_DCMD_PD_GET_INFO, &mbox, pd, sizeof(*pd), SCSI_DATA_IN);
3404	if (rv != 0)
3405		goto done;
3406
3407	if (pd->mpd_ddf_state & MFI_DDF_FOREIGN) {
3408		rv = mfii_mgmt(sc, MR_DCMD_CFG_FOREIGN_SCAN, NULL, fsi, sizeof(*fsi),
3409		    SCSI_DATA_IN);
3410		if (rv != 0)
3411			goto done;
3412
3413		if (fsi->count > 0) {
3414			rv = mfii_mgmt(sc, MR_DCMD_CFG_FOREIGN_CLEAR, NULL, NULL, 0, 0);
3415			if (rv != 0)
3416				goto done;
3417		}
3418	}
3419
3420	memset(&mbox, 0, sizeof mbox);
3421	mbox.s[0] = pd_id;
3422	rv = mfii_mgmt(sc, MR_DCMD_PD_GET_INFO, &mbox, pd, sizeof(*pd), SCSI_DATA_IN);
3423	if (rv != 0)
3424		goto done;
3425
3426	if (pd->mpd_fw_state != MFI_PD_UNCONFIG_GOOD ||
3427	    pd->mpd_ddf_state & MFI_DDF_FOREIGN)
3428		rv = ENXIO;
3429
3430done:
3431	free(fsi, M_DEVBUF, sizeof *fsi);
3432	free(pd, M_DEVBUF, sizeof *pd);
3433
3434	return (rv);
3435}
3436
3437static int
3438mfii_makespare(struct mfii_softc *sc, uint16_t pd_id)
3439{
3440	struct mfi_hotspare	*hs;
3441	struct mfi_pd_details	*pd;
3442	union mfi_mbox		mbox;
3443	size_t			size;
3444	int			rv = EINVAL;
3445
3446	/* we really could skip and expect that inq took care of it */
3447	if (mfii_bio_getitall(sc)) {
3448		DNPRINTF(MFII_D_IOCTL, "%s: mfii_bio_getitall failed\n",
3449		    DEVNAME(sc));
3450		return (rv);
3451	}
3452	size = sizeof *hs + sizeof(uint16_t) * sc->sc_cfg->mfc_no_array;
3453
3454	hs = malloc(size, M_DEVBUF, M_WAITOK);
3455	pd = malloc(sizeof *pd, M_DEVBUF, M_WAITOK);
3456
3457	memset(&mbox, 0, sizeof mbox);
3458	mbox.s[0] = pd_id;
3459	rv = mfii_mgmt(sc, MR_DCMD_PD_GET_INFO, &mbox, pd, sizeof(*pd),
3460	    SCSI_DATA_IN);
3461	if (rv != 0)
3462		goto done;
3463
3464	memset(hs, 0, size);
3465	hs->mhs_pd.mfp_id = pd->mpd_pd.mfp_id;
3466	hs->mhs_pd.mfp_seq = pd->mpd_pd.mfp_seq;
3467	rv = mfii_mgmt(sc, MR_DCMD_CFG_MAKE_SPARE, NULL, hs, size, SCSI_DATA_OUT);
3468
3469done:
3470	free(hs, M_DEVBUF, size);
3471	free(pd, M_DEVBUF, sizeof *pd);
3472
3473	return (rv);
3474}
3475
3476int
3477mfii_ioctl_setstate(struct mfii_softc *sc, struct bioc_setstate *bs)
3478{
3479	struct mfi_pd_details	*pd;
3480	struct mfi_pd_list	*pl;
3481	int			i, found, rv = EINVAL;
3482	union mfi_mbox		mbox;
3483
3484	DNPRINTF(MFII_D_IOCTL, "%s: mfii_ioctl_setstate %x\n", DEVNAME(sc),
3485	    bs->bs_status);
3486
3487	pd = malloc(sizeof *pd, M_DEVBUF, M_WAITOK);
3488	pl = malloc(sizeof *pl, M_DEVBUF, M_WAITOK);
3489
3490	if (mfii_mgmt(sc, MR_DCMD_PD_GET_LIST, NULL, pl, sizeof(*pl), SCSI_DATA_IN))
3491		goto done;
3492
3493	for (i = 0, found = 0; i < pl->mpl_no_pd; i++)
3494		if (bs->bs_channel == pl->mpl_address[i].mpa_enc_index &&
3495		    bs->bs_target == pl->mpl_address[i].mpa_enc_slot) {
3496			found = 1;
3497			break;
3498		}
3499
3500	if (!found)
3501		goto done;
3502
3503	memset(&mbox, 0, sizeof(mbox));
3504	mbox.s[0] = pl->mpl_address[i].mpa_pd_id;
3505
3506	if (mfii_mgmt(sc, MR_DCMD_PD_GET_INFO, &mbox, pd, sizeof(*pd), SCSI_DATA_IN))
3507		goto done;
3508
3509	mbox.s[0] = pl->mpl_address[i].mpa_pd_id;
3510	mbox.s[1] = pd->mpd_pd.mfp_seq;
3511
3512	switch (bs->bs_status) {
3513	case BIOC_SSONLINE:
3514		mbox.b[4] = MFI_PD_ONLINE;
3515		break;
3516
3517	case BIOC_SSOFFLINE:
3518		mbox.b[4] = MFI_PD_OFFLINE;
3519		break;
3520
3521	case BIOC_SSHOTSPARE:
3522		mbox.b[4] = MFI_PD_HOTSPARE;
3523		break;
3524
3525	case BIOC_SSREBUILD:
3526		if (pd->mpd_fw_state != MFI_PD_OFFLINE) {
3527			if ((rv = mfii_makegood(sc,
3528			    pl->mpl_address[i].mpa_pd_id)))
3529				goto done;
3530
3531			if ((rv = mfii_makespare(sc,
3532			    pl->mpl_address[i].mpa_pd_id)))
3533				goto done;
3534
3535			memset(&mbox, 0, sizeof(mbox));
3536			mbox.s[0] = pl->mpl_address[i].mpa_pd_id;
3537			rv = mfii_mgmt(sc, MR_DCMD_PD_GET_INFO, &mbox, pd, sizeof(*pd),
3538			    SCSI_DATA_IN);
3539			if (rv != 0)
3540				goto done;
3541
3542			/* rebuilding might be started by mfii_makespare() */
3543			if (pd->mpd_fw_state == MFI_PD_REBUILD) {
3544				rv = 0;
3545				goto done;
3546			}
3547
3548			mbox.s[0] = pl->mpl_address[i].mpa_pd_id;
3549			mbox.s[1] = pd->mpd_pd.mfp_seq;
3550		}
3551		mbox.b[4] = MFI_PD_REBUILD;
3552		break;
3553
3554	default:
3555		DNPRINTF(MFII_D_IOCTL, "%s: mfii_ioctl_setstate invalid "
3556		    "opcode %x\n", DEVNAME(sc), bs->bs_status);
3557		goto done;
3558	}
3559
3560
3561	rv = mfii_mgmt(sc, MR_DCMD_PD_SET_STATE, &mbox, NULL, 0, 0);
3562done:
3563	free(pd, M_DEVBUF, sizeof *pd);
3564	free(pl, M_DEVBUF, sizeof *pl);
3565	return (rv);
3566}
3567
3568int
3569mfii_ioctl_patrol(struct mfii_softc *sc, struct bioc_patrol *bp)
3570{
3571	uint32_t		opc;
3572	int			rv = 0;
3573	struct mfi_pr_properties prop;
3574	struct mfi_pr_status	status;
3575	uint32_t		time, exec_freq;
3576
3577	switch (bp->bp_opcode) {
3578	case BIOC_SPSTOP:
3579	case BIOC_SPSTART:
3580		if (bp->bp_opcode == BIOC_SPSTART)
3581			opc = MR_DCMD_PR_START;
3582		else
3583			opc = MR_DCMD_PR_STOP;
3584		if (mfii_mgmt(sc, opc, NULL, NULL, 0, SCSI_DATA_IN))
3585			return (EINVAL);
3586		break;
3587
3588	case BIOC_SPMANUAL:
3589	case BIOC_SPDISABLE:
3590	case BIOC_SPAUTO:
3591		/* Get device's time. */
3592		opc = MR_DCMD_TIME_SECS_GET;
3593		if (mfii_mgmt(sc, opc, NULL, &time, sizeof(time), SCSI_DATA_IN))
3594			return (EINVAL);
3595
3596		opc = MR_DCMD_PR_GET_PROPERTIES;
3597		if (mfii_mgmt(sc, opc, NULL, &prop, sizeof(prop), SCSI_DATA_IN))
3598			return (EINVAL);
3599
3600		switch (bp->bp_opcode) {
3601		case BIOC_SPMANUAL:
3602			prop.op_mode = MFI_PR_OPMODE_MANUAL;
3603			break;
3604		case BIOC_SPDISABLE:
3605			prop.op_mode = MFI_PR_OPMODE_DISABLED;
3606			break;
3607		case BIOC_SPAUTO:
3608			if (bp->bp_autoival != 0) {
3609				if (bp->bp_autoival == -1)
3610					/* continuously */
3611					exec_freq = 0xffffffffU;
3612				else if (bp->bp_autoival > 0)
3613					exec_freq = bp->bp_autoival;
3614				else
3615					return (EINVAL);
3616				prop.exec_freq = exec_freq;
3617			}
3618			if (bp->bp_autonext != 0) {
3619				if (bp->bp_autonext < 0)
3620					return (EINVAL);
3621				else
3622					prop.next_exec = time + bp->bp_autonext;
3623			}
3624			prop.op_mode = MFI_PR_OPMODE_AUTO;
3625			break;
3626		}
3627
3628		opc = MR_DCMD_PR_SET_PROPERTIES;
3629		if (mfii_mgmt(sc, opc, NULL, &prop, sizeof(prop), SCSI_DATA_OUT))
3630			return (EINVAL);
3631
3632		break;
3633
3634	case BIOC_GPSTATUS:
3635		opc = MR_DCMD_PR_GET_PROPERTIES;
3636		if (mfii_mgmt(sc, opc, NULL, &prop, sizeof(prop), SCSI_DATA_IN))
3637			return (EINVAL);
3638
3639		opc = MR_DCMD_PR_GET_STATUS;
3640		if (mfii_mgmt(sc, opc, NULL, &status, sizeof(status), SCSI_DATA_IN))
3641			return (EINVAL);
3642
3643		/* Get device's time. */
3644		opc = MR_DCMD_TIME_SECS_GET;
3645		if (mfii_mgmt(sc, opc, NULL, &time, sizeof(time), SCSI_DATA_IN))
3646			return (EINVAL);
3647
3648		switch (prop.op_mode) {
3649		case MFI_PR_OPMODE_AUTO:
3650			bp->bp_mode = BIOC_SPMAUTO;
3651			bp->bp_autoival = prop.exec_freq;
3652			bp->bp_autonext = prop.next_exec;
3653			bp->bp_autonow = time;
3654			break;
3655		case MFI_PR_OPMODE_MANUAL:
3656			bp->bp_mode = BIOC_SPMMANUAL;
3657			break;
3658		case MFI_PR_OPMODE_DISABLED:
3659			bp->bp_mode = BIOC_SPMDISABLED;
3660			break;
3661		default:
3662			printf("%s: unknown patrol mode %d\n",
3663			    DEVNAME(sc), prop.op_mode);
3664			break;
3665		}
3666
3667		switch (status.state) {
3668		case MFI_PR_STATE_STOPPED:
3669			bp->bp_status = BIOC_SPSSTOPPED;
3670			break;
3671		case MFI_PR_STATE_READY:
3672			bp->bp_status = BIOC_SPSREADY;
3673			break;
3674		case MFI_PR_STATE_ACTIVE:
3675			bp->bp_status = BIOC_SPSACTIVE;
3676			break;
3677		case MFI_PR_STATE_ABORTED:
3678			bp->bp_status = BIOC_SPSABORTED;
3679			break;
3680		default:
3681			printf("%s: unknown patrol state %d\n",
3682			    DEVNAME(sc), status.state);
3683			break;
3684		}
3685
3686		break;
3687
3688	default:
3689		DNPRINTF(MFII_D_IOCTL, "%s: mfii_ioctl_patrol biocpatrol invalid "
3690		    "opcode %x\n", DEVNAME(sc), bp->bp_opcode);
3691		return (EINVAL);
3692	}
3693
3694	return (rv);
3695}
3696
3697int
3698mfii_bio_hs(struct mfii_softc *sc, int volid, int type, void *bio_hs)
3699{
3700	struct mfi_conf		*cfg;
3701	struct mfi_hotspare	*hs;
3702	struct mfi_pd_details	*pd;
3703	struct bioc_disk	*sdhs;
3704	struct bioc_vol		*vdhs;
3705	struct scsi_inquiry_data *inqbuf;
3706	char			vend[8+16+4+1], *vendp;
3707	int			i, rv = EINVAL;
3708	uint32_t		size;
3709	union mfi_mbox		mbox;
3710
3711	DNPRINTF(MFII_D_IOCTL, "%s: mfii_vol_hs %d\n", DEVNAME(sc), volid);
3712
3713	if (!bio_hs)
3714		return (EINVAL);
3715
3716	pd = malloc(sizeof *pd, M_DEVBUF, M_WAITOK);
3717
3718	/* send single element command to retrieve size for full structure */
3719	cfg = malloc(sizeof *cfg, M_DEVBUF, M_WAITOK);
3720	if (mfii_mgmt(sc, MR_DCMD_CONF_GET, NULL, cfg, sizeof(*cfg), SCSI_DATA_IN))
3721		goto freeme;
3722
3723	size = cfg->mfc_size;
3724	free(cfg, M_DEVBUF, sizeof *cfg);
3725
3726	/* memory for read config */
3727	cfg = malloc(size, M_DEVBUF, M_WAITOK|M_ZERO);
3728	if (mfii_mgmt(sc, MR_DCMD_CONF_GET, NULL, cfg, size, SCSI_DATA_IN))
3729		goto freeme;
3730
3731	/* calculate offset to hs structure */
3732	hs = (struct mfi_hotspare *)(
3733	    ((uint8_t *)cfg) + offsetof(struct mfi_conf, mfc_array) +
3734	    cfg->mfc_array_size * cfg->mfc_no_array +
3735	    cfg->mfc_ld_size * cfg->mfc_no_ld);
3736
3737	if (volid < cfg->mfc_no_ld)
3738		goto freeme; /* not a hotspare */
3739
3740	if (volid > (cfg->mfc_no_ld + cfg->mfc_no_hs))
3741		goto freeme; /* not a hotspare */
3742
3743	/* offset into hotspare structure */
3744	i = volid - cfg->mfc_no_ld;
3745
3746	DNPRINTF(MFII_D_IOCTL, "%s: mfii_vol_hs i %d volid %d no_ld %d no_hs %d "
3747	    "hs %p cfg %p id %02x\n", DEVNAME(sc), i, volid, cfg->mfc_no_ld,
3748	    cfg->mfc_no_hs, hs, cfg, hs[i].mhs_pd.mfp_id);
3749
3750	/* get pd fields */
3751	memset(&mbox, 0, sizeof(mbox));
3752	mbox.s[0] = hs[i].mhs_pd.mfp_id;
3753	if (mfii_mgmt(sc, MR_DCMD_PD_GET_INFO, &mbox, pd, sizeof(*pd),
3754	    SCSI_DATA_IN)) {
3755		DNPRINTF(MFII_D_IOCTL, "%s: mfii_vol_hs illegal PD\n",
3756		    DEVNAME(sc));
3757		goto freeme;
3758	}
3759
3760	switch (type) {
3761	case MFI_MGMT_VD:
3762		vdhs = bio_hs;
3763		vdhs->bv_status = BIOC_SVONLINE;
3764		vdhs->bv_size = pd->mpd_size / 2 * 1024; /* XXX why? */
3765		vdhs->bv_level = -1; /* hotspare */
3766		vdhs->bv_nodisk = 1;
3767		break;
3768
3769	case MFI_MGMT_SD:
3770		sdhs = bio_hs;
3771		sdhs->bd_status = BIOC_SDHOTSPARE;
3772		sdhs->bd_size = pd->mpd_size / 2 * 1024; /* XXX why? */
3773		sdhs->bd_channel = pd->mpd_enc_idx;
3774		sdhs->bd_target = pd->mpd_enc_slot;
3775		inqbuf = (struct scsi_inquiry_data *)&pd->mpd_inq_data;
3776		vendp = inqbuf->vendor;
3777		memcpy(vend, vendp, sizeof vend - 1);
3778		vend[sizeof vend - 1] = '\0';
3779		strlcpy(sdhs->bd_vendor, vend, sizeof(sdhs->bd_vendor));
3780		break;
3781
3782	default:
3783		goto freeme;
3784	}
3785
3786	DNPRINTF(MFII_D_IOCTL, "%s: mfii_vol_hs 6\n", DEVNAME(sc));
3787	rv = 0;
3788freeme:
3789	free(pd, M_DEVBUF, sizeof *pd);
3790	free(cfg, M_DEVBUF, 0);
3791
3792	return (rv);
3793}
3794
3795#ifndef SMALL_KERNEL
3796
3797#define MFI_BBU_SENSORS 4
3798
3799void
3800mfii_bbu(struct mfii_softc *sc)
3801{
3802	struct mfi_bbu_status bbu;
3803	u_int32_t status;
3804	u_int32_t mask;
3805	u_int32_t soh_bad;
3806	int i;
3807
3808	if (mfii_mgmt(sc, MR_DCMD_BBU_GET_STATUS, NULL, &bbu,
3809	    sizeof(bbu), SCSI_DATA_IN) != 0) {
3810		for (i = 0; i < MFI_BBU_SENSORS; i++) {
3811			sc->sc_bbu[i].value = 0;
3812			sc->sc_bbu[i].status = SENSOR_S_UNKNOWN;
3813		}
3814		for (i = 0; i < nitems(mfi_bbu_indicators); i++) {
3815			sc->sc_bbu_status[i].value = 0;
3816			sc->sc_bbu_status[i].status = SENSOR_S_UNKNOWN;
3817		}
3818		return;
3819	}
3820
3821	switch (bbu.battery_type) {
3822	case MFI_BBU_TYPE_IBBU:
3823		mask = MFI_BBU_STATE_BAD_IBBU;
3824		soh_bad = 0;
3825		break;
3826	case MFI_BBU_TYPE_BBU:
3827		mask = MFI_BBU_STATE_BAD_BBU;
3828		soh_bad = (bbu.detail.bbu.is_SOH_good == 0);
3829		break;
3830
3831	case MFI_BBU_TYPE_NONE:
3832	default:
3833		sc->sc_bbu[0].value = 0;
3834		sc->sc_bbu[0].status = SENSOR_S_CRIT;
3835		for (i = 1; i < MFI_BBU_SENSORS; i++) {
3836			sc->sc_bbu[i].value = 0;
3837			sc->sc_bbu[i].status = SENSOR_S_UNKNOWN;
3838		}
3839		for (i = 0; i < nitems(mfi_bbu_indicators); i++) {
3840			sc->sc_bbu_status[i].value = 0;
3841			sc->sc_bbu_status[i].status = SENSOR_S_UNKNOWN;
3842		}
3843		return;
3844	}
3845
3846	status = letoh32(bbu.fw_status);
3847
3848	sc->sc_bbu[0].value = ((status & mask) || soh_bad) ? 0 : 1;
3849	sc->sc_bbu[0].status = ((status & mask) || soh_bad) ? SENSOR_S_CRIT :
3850	    SENSOR_S_OK;
3851
3852	sc->sc_bbu[1].value = letoh16(bbu.voltage) * 1000;
3853	sc->sc_bbu[2].value = (int16_t)letoh16(bbu.current) * 1000;
3854	sc->sc_bbu[3].value = letoh16(bbu.temperature) * 1000000 + 273150000;
3855	for (i = 1; i < MFI_BBU_SENSORS; i++)
3856		sc->sc_bbu[i].status = SENSOR_S_UNSPEC;
3857
3858	for (i = 0; i < nitems(mfi_bbu_indicators); i++) {
3859		sc->sc_bbu_status[i].value = (status & (1 << i)) ? 1 : 0;
3860		sc->sc_bbu_status[i].status = SENSOR_S_UNSPEC;
3861	}
3862}
3863
3864void
3865mfii_refresh_ld_sensor(struct mfii_softc *sc, int ld)
3866{
3867	struct ksensor *sensor;
3868	int target;
3869
3870	target = sc->sc_ld_list.mll_list[ld].mll_ld.mld_target;
3871	sensor = &sc->sc_sensors[target];
3872
3873	switch(sc->sc_ld_list.mll_list[ld].mll_state) {
3874	case MFI_LD_OFFLINE:
3875		sensor->value = SENSOR_DRIVE_FAIL;
3876		sensor->status = SENSOR_S_CRIT;
3877		break;
3878
3879	case MFI_LD_PART_DEGRADED:
3880	case MFI_LD_DEGRADED:
3881		sensor->value = SENSOR_DRIVE_PFAIL;
3882		sensor->status = SENSOR_S_WARN;
3883		break;
3884
3885	case MFI_LD_ONLINE:
3886		sensor->value = SENSOR_DRIVE_ONLINE;
3887		sensor->status = SENSOR_S_OK;
3888		break;
3889
3890	default:
3891		sensor->value = 0; /* unknown */
3892		sensor->status = SENSOR_S_UNKNOWN;
3893		break;
3894	}
3895}
3896
3897void
3898mfii_init_ld_sensor(struct mfii_softc *sc, int ld)
3899{
3900	struct device		*dev;
3901	struct scsi_link	*link;
3902	struct ksensor		*sensor;
3903	int			target;
3904
3905	target = sc->sc_ld_list.mll_list[ld].mll_ld.mld_target;
3906	sensor = &sc->sc_sensors[target];
3907
3908	link = scsi_get_link(sc->sc_scsibus, target, 0);
3909	if (link == NULL) {
3910		strlcpy(sensor->desc, "cache", sizeof(sensor->desc));
3911	} else {
3912		dev = link->device_softc;
3913		if (dev != NULL)
3914			strlcpy(sensor->desc, dev->dv_xname,
3915			    sizeof(sensor->desc));
3916	}
3917	sensor->type = SENSOR_DRIVE;
3918	mfii_refresh_ld_sensor(sc, ld);
3919}
3920
3921int
3922mfii_create_sensors(struct mfii_softc *sc)
3923{
3924	int			i, target;
3925
3926	strlcpy(sc->sc_sensordev.xname, DEVNAME(sc),
3927	    sizeof(sc->sc_sensordev.xname));
3928
3929	if (ISSET(letoh32(sc->sc_info.mci_hw_present), MFI_INFO_HW_BBU)) {
3930		sc->sc_bbu = mallocarray(4, sizeof(*sc->sc_bbu),
3931		    M_DEVBUF, M_WAITOK | M_ZERO);
3932
3933		sc->sc_bbu[0].type = SENSOR_INDICATOR;
3934		sc->sc_bbu[0].status = SENSOR_S_UNKNOWN;
3935		strlcpy(sc->sc_bbu[0].desc, "bbu ok",
3936		    sizeof(sc->sc_bbu[0].desc));
3937		sensor_attach(&sc->sc_sensordev, &sc->sc_bbu[0]);
3938
3939		sc->sc_bbu[1].type = SENSOR_VOLTS_DC;
3940		sc->sc_bbu[1].status = SENSOR_S_UNSPEC;
3941		sc->sc_bbu[2].type = SENSOR_AMPS;
3942		sc->sc_bbu[2].status = SENSOR_S_UNSPEC;
3943		sc->sc_bbu[3].type = SENSOR_TEMP;
3944		sc->sc_bbu[3].status = SENSOR_S_UNSPEC;
3945		for (i = 1; i < MFI_BBU_SENSORS; i++) {
3946			strlcpy(sc->sc_bbu[i].desc, "bbu",
3947			    sizeof(sc->sc_bbu[i].desc));
3948			sensor_attach(&sc->sc_sensordev, &sc->sc_bbu[i]);
3949		}
3950
3951		sc->sc_bbu_status = malloc(sizeof(*sc->sc_bbu_status) *
3952		    sizeof(mfi_bbu_indicators), M_DEVBUF, M_WAITOK | M_ZERO);
3953
3954		for (i = 0; i < nitems(mfi_bbu_indicators); i++) {
3955			sc->sc_bbu_status[i].type = SENSOR_INDICATOR;
3956			sc->sc_bbu_status[i].status = SENSOR_S_UNSPEC;
3957			strlcpy(sc->sc_bbu_status[i].desc,
3958			    mfi_bbu_indicators[i],
3959			    sizeof(sc->sc_bbu_status[i].desc));
3960
3961			sensor_attach(&sc->sc_sensordev, &sc->sc_bbu_status[i]);
3962		}
3963	}
3964
3965	sc->sc_sensors = mallocarray(MFI_MAX_LD, sizeof(struct ksensor),
3966	    M_DEVBUF, M_NOWAIT | M_ZERO);
3967	if (sc->sc_sensors == NULL)
3968		return (1);
3969
3970	for (i = 0; i < sc->sc_ld_list.mll_no_ld; i++) {
3971		mfii_init_ld_sensor(sc, i);
3972		target = sc->sc_ld_list.mll_list[i].mll_ld.mld_target;
3973		sensor_attach(&sc->sc_sensordev, &sc->sc_sensors[target]);
3974	}
3975
3976	if (sensor_task_register(sc, mfii_refresh_sensors, 10) == NULL)
3977		goto bad;
3978
3979	sensordev_install(&sc->sc_sensordev);
3980
3981	return (0);
3982
3983bad:
3984	free(sc->sc_sensors, M_DEVBUF,
3985	    MFI_MAX_LD * sizeof(struct ksensor));
3986
3987	return (1);
3988}
3989
3990void
3991mfii_refresh_sensors(void *arg)
3992{
3993	struct mfii_softc	*sc = arg;
3994	int			i;
3995
3996	rw_enter_write(&sc->sc_lock);
3997	if (sc->sc_bbu != NULL)
3998		mfii_bbu(sc);
3999
4000	mfii_bio_getitall(sc);
4001	rw_exit_write(&sc->sc_lock);
4002
4003	for (i = 0; i < sc->sc_ld_list.mll_no_ld; i++)
4004		mfii_refresh_ld_sensor(sc, i);
4005}
4006#endif /* SMALL_KERNEL */
4007#endif /* NBIO > 0 */
4008