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