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