/* * This file and its contents are supplied under the terms of the * Common Development and Distribution License ("CDDL"), version 1.0. * You may only use this file in accordance with the terms of version * 1.0 of the CDDL. * * A full copy of the text of the CDDL should have accompanied this * source. A copy of the CDDL is also available via the Internet at * http://www.illumos.org/license/CDDL. */ /* * Copyright (C) 2013 Hewlett-Packard Development Company, L.P. */ #ifndef _CPQARY3_H #define _CPQARY3_H #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef __cplusplus extern "C" { #endif /* * Ioctl Commands */ #define CPQARY3_IOCTL_CMD ('c' << 4) #define CPQARY3_IOCTL_DRIVER_INFO CPQARY3_IOCTL_CMD | 0x01 #define CPQARY3_IOCTL_CTLR_INFO CPQARY3_IOCTL_CMD | 0x02 #define CPQARY3_IOCTL_BMIC_PASS CPQARY3_IOCTL_CMD | 0x04 #define CPQARY3_IOCTL_SCSI_PASS CPQARY3_IOCTL_CMD | 0x08 /* Driver Revision : Used in Ioctl */ #define CPQARY3_MINOR_REV_NO 00 #define CPQARY3_MAJOR_REV_NO 01 #define CPQARY3_REV_DATE 05 #define CPQARY3_REV_MONTH 04 #define CPQARY3_REV_YEAR 2001 /* Some Useful definations */ #define CPQARY3_FAILURE 0 #define CPQARY3_SUCCESS 1 #define CPQARY3_SENT 2 #define CPQARY3_SUBMITTED 3 #define CPQARY3_NO_SIG 4 #define CPQARY3_TRUE 1 #define CPQARY3_FALSE 0 #define CTLR_SCSI_ID 7 #define CPQARY3_LD_FAILED 1 /* * Defines for cleanup in cpqary3_attach and cpqary3_detach. */ #define CPQARY3_HBA_TRAN_ALLOC_DONE 0x0001 #define CPQARY3_HBA_TRAN_ATTACH_DONE 0x0002 #define CPQARY3_CTLR_CONFIG_DONE 0x0004 #define CPQARY3_INTR_HDLR_SET 0x0008 #define CPQARY3_CREATE_MINOR_NODE 0x0010 #define CPQARY3_SOFTSTATE_ALLOC_DONE 0x0020 #define CPQARY3_MUTEX_INIT_DONE 0x0040 #define CPQARY3_TICK_TMOUT_REGD 0x0080 #define CPQARY3_MEM_MAPPED 0x0100 #define CPQARY3_SW_INTR_HDLR_SET 0x0200 #define CPQARY3_SW_MUTEX_INIT_DONE 0x0400 #define CPQARY3_NOE_INIT_DONE 0x0800 #define CPQARY3_CLEAN_ALL 0x0FFF #define CPQARY3_TICKTMOUT_VALUE 180000000 /* 180 seconds */ /* * Defines for Maximum and Default Settings. */ #define MAX_LOGDRV 64 /* Max supported Logical Drivers */ #define MAX_CTLRS 8 /* Max supported Controllers */ #define MAX_TAPE 28 /* * NOTE: When changing the below two entries, Max SG count in cpqary3_ciss.h * should also be changed. */ /* SG */ #define MAX_PERF_SG_CNT 64 /* Maximum S/G in performant mode */ #define CPQARY3_SG_CNT 30 /* minimum S/G in simple mode */ #define CPQARY3_PERF_SG_CNT 31 /* minimum S/G for performant mode */ /* SG */ #define CPQARY3_MAX_TGT (MAX_LOGDRV + MAX_TAPE + 1) /* * SCSI Capabilities Related IDs */ #define CPQARY3_CAP_DISCON_ENABLED 0x01 #define CPQARY3_CAP_SYNC_ENABLED 0x02 #define CPQARY3_CAP_WIDE_XFER_ENABLED 0x04 #define CPQARY3_CAP_ARQ_ENABLED 0x08 #define CPQARY3_CAP_TAG_QING_ENABLED 0x10 #define CPQARY3_CAP_TAG_QING_SUPP 0x20 #define CPQARY3_CAP_UNTAG_DRV_QING_ENABLED 0x40 /* * Defines for HBA */ #define CAP_NOT_DEFINED -1 #define CAP_CHG_NOT_ALLOWED 0 #define CAP_CHG_SUCCESS 1 /* * Macros for Data Access */ /* SCSI Addr to Per Controller */ #define SA2CTLR(saddr) ((cpqary3_t *)((saddr)->a_hba_tran->tran_hba_private)) #define SA2TGT(sa) (sa)->a_target /* SCSI Addr to Target ID */ #define SD2TGT(sd) (sd)->sd_address.a_target /* SCSI Dev to Target ID */ #define SD2LUN(sd) (sd)->sd_address.a_lun /* SCSI Dev to Lun */ #define SD2SA(sd) ((sd)->sd_address) /* SCSI Dev to SCSI Addr */ /* SCSI Dev to Per Controller */ #define SD2CTLR(sd) \ ((cpqary3_t *)sd->sd_address.a_hba_tran->tran_hba_private) #define PKT2PVTPKT(sp) ((cpqary3_pkt_t *)((sp)->pkt_ha_private)) #define PVTPKT2MEM(p) ((cpqary3_cmdpvt_t *)p->memp) #define MEM2CMD(m) ((CommandList_t *)m->cmdlist_memaddr) #define SP2CMD(sp) MEM2CMD(PVTPKT2MEM(PKT2PVTPKT(sp))) #define CTLR2MEMLISTP(ctlr) ((cpqary3_cmdmemlist_t *)ctlr->cmdmemlistp) #define MEM2PVTPKT(m) ((cpqary3_pkt_t *)m->pvt_pkt) #define MEM2DRVPVT(m) ((cpqary3_private_t *)m->driverdata) #define TAG2MEM(ctlr, tag) \ ((cpqary3_cmdpvt_t *)(CTLR2MEMLISTP(ctlr)->pool[tag])) /* MACROS */ #define CPQARY3_MIN(x, y) (x < y ? x : y) #define CPQARY3_SWAP(val) ((val >> 8) | ((val & 0xff) << 8)) #define RETURN_VOID_IF_NULL(x) if (NULL == x) return #define RETURN_NULL_IF_NULL(x) if (NULL == x) return (NULL) #define RETURN_FAILURE_IF_NULL(x) if (NULL == x) return (CPQARY3_FAILURE) /* * Macros for memory allocation/deallocations */ #define MEM_ZALLOC(x) kmem_zalloc(x, KM_NOSLEEP) #define MEM_SFREE(x, y) if (x) kmem_free((void*)x, y) /* * Convenient macros for reading/writing Configuration table registers */ #define DDI_GET8(ctlr, regp) \ ddi_get8((ctlr)->ct_handle, (uint8_t *)(regp)) #define DDI_PUT8(ctlr, regp, value) \ ddi_put8((ctlr)->ct_handle, (uint8_t *)(regp), (value)) #define DDI_GET16(ctlr, regp) \ ddi_get16((ctlr)->ct_handle, (uint16_t *)(regp)) #define DDI_PUT16(ctlr, regp, value) \ ddi_put16((ctlr)->ct_handle, (uint16_t *)(regp), (value)) #define DDI_GET32(ctlr, regp) \ ddi_get32((ctlr)->ct_handle, (uint32_t *)(regp)) #define DDI_PUT32(ctlr, regp, value) \ ddi_put32((ctlr)->ct_handle, (uint32_t *)(regp), (value)) /* PERF */ #define DDI_PUT32_CP(ctlr, regp, value) \ ddi_put32((ctlr)->cp_handle, (uint32_t *)(regp), (value)) /* PERF */ #define CPQARY3_BUFFER_ERROR_CLEAR 0x0 /* to be used with bioerror */ #define CPQARY3_DMA_NO_CALLBACK 0x0 /* to be used with DMA calls */ #define CPQARY3_DMA_ALLOC_HANDLE_DONE 0x01 #define CPQARY3_DMA_ALLOC_MEM_DONE 0x02 #define CPQARY3_DMA_BIND_ADDR_DONE 0x04 #define CPQARY3_FREE_PHYCTG_MEM 0x07 #define CPQARY3_SYNCCMD_SEND_WAITSIG (0x0001) /* * Include the driver specific relevant header files here. */ #include "cpqary3_ciss.h" #include "cpqary3_q_mem.h" #include "cpqary3_noe.h" #include "cpqary3_scsi.h" #include "cpqary3_ioctl.h" /* * Per Target Structure */ typedef struct cpqary3_target { uint32_t logical_id : 30; /* at most 64 : 63 drives + 1 CTLR */ uint32_t type : 2; /* NONE, CTLR, LOGICAL DRIVE, TAPE */ PhysDevAddr_t PhysID; union { struct { uint8_t id; uint8_t bus; } scsi; /* To support tapes */ struct { uint8_t heads; uint8_t sectors; } drive; /* Logical drives */ } properties; uint32_t ctlr_flags; dev_info_t *tgt_dip; ddi_dma_attr_t dma_attrs; } cpqary3_tgt_t; /* * Values for the type field in the Per Target Structure (above) */ #define CPQARY3_TARGET_NONE 0 /* No Device */ #define CPQARY3_TARGET_CTLR 1 /* Controller */ #define CPQARY3_TARGET_LOG_VOL 2 /* Logical Volume */ #define CPQARY3_TARGET_TAPE 3 /* SCSI Device - Tape */ /* * Index into PCI Configuration Registers for Base Address Registers(BAR) * Currently, only index for BAR 0 and BAR 1 are defined */ #define INDEX_PCI_BASE0 1 /* offset 0x10 */ #define INDEX_PCI_BASE1 2 /* offset 0x14 */ /* Offset Values for IO interface from BAR 0 */ #define INBOUND_DOORBELL 0x20 #define OUTBOUND_LIST_STATUS 0x30 #define OUTBOUND_INTERRUPT_MASK 0x34 #define INBOUND_QUEUE 0x40 #define OUTBOUND_QUEUE 0x44 /* Offset Values for IO interface from BAR 1 */ #define CONFIGURATION_TABLE 0x00 #define INTR_DISABLE_5300_MASK 0x00000008l #define INTR_DISABLE_5I_MASK 0x00000004l #define OUTBOUND_LIST_5300_EXISTS 0x00000008l #define OUTBOUND_LIST_5I_EXISTS 0x00000004l #define INTR_PERF_MASK 0x00000001l #define INTR_PERF_LOCKUP_MASK 0x00000004l #define INTR_E200_PERF_MASK 0x00000004l #define INTR_SIMPLE_MASK 0x00000008l #define INTR_SIMPLE_LOCKUP_MASK 0x0000000cl #define INTR_SIMPLE_5I_MASK 0x00000004l #define INTR_SIMPLE_5I_LOCKUP_MASK 0x0000000cl typedef struct cpqary3_per_controller CTLR; /* * Per Controller Structure */ typedef struct cpqary3_per_controller { /* System Dependent Entities */ uint8_t bus; uint8_t dev : 5; uint8_t fun : 3; uint32_t instance; dev_info_t *dip; /* Controller Specific Information */ int8_t hba_name[38]; ulong_t num_of_targets; uint32_t heartbeat; uint32_t board_id; cpqary3_bd_t *bddef; /* Condition Variables used */ kcondvar_t cv_immediate_wait; kcondvar_t cv_noe_wait; kcondvar_t cv_flushcache_wait; kcondvar_t cv_abort_wait; kcondvar_t cv_ioctl_wait; /* Variable for ioctls */ /* * CPQary3 driver related entities related to : * Hardware & Software Interrupts, Cookies & Mutex. * Timeout Handler * Driver Transport Layer/Structure * Database for the per-controller Command Memory Pool * Target List for the per-controller */ uint8_t irq; /* h/w IRQ */ ddi_iblock_cookie_t hw_iblock_cookie; /* cookie for h/w intr */ kmutex_t hw_mutex; /* h/w mutex */ ddi_iblock_cookie_t sw_iblock_cookie; /* cookie for s/w intr */ kmutex_t sw_mutex; /* s/w mutex */ ddi_softintr_t cpqary3_softintr_id; /* s/w intr identifier */ uint8_t swintr_flag; timeout_id_t tick_tmout_id; /* timeout identifier */ uint8_t cpqary3_tick_hdlr; scsi_hba_tran_t *hba_tran; /* transport structure */ cpqary3_cmdmemlist_t *cmdmemlistp; /* database - Memory Pool */ cpqary3_tgt_t *cpqary3_tgtp[CPQARY3_MAX_TGT]; cpqary3_drvr_replyq_t *drvr_replyq; uint8_t (*check_ctlr_intr)(CTLR *); /* * PCI Configuration Registers * 0x10 Primary I2O Memory BAR - for Host Interface * 0x14 Primary DRAM 1 BAR - for Transport Configuration Table * * Host Interface Registers * Offset from Primary I2O Memory BAR * 0x20 Inbound Doorbell - for interrupting controller * 0x30 Outbound List Status - for signalling status of Reply Q * 0x34 Outbound Interrupt Mask - for masking Interrupts to host * 0x40 Host Inbound Queue - Request Q * 0x44 Host Outbound Queue - reply Q * * Offset from Primary DRAM 1 BAR * 0x00 Configuration Table - for Controller Transport Layer */ uint32_t *idr; ddi_acc_handle_t idr_handle; /* LOCKUP CODE */ uint32_t *spr0; ddi_acc_handle_t spr0_handle; /* LOCKUP CODE */ uint32_t *odr; ddi_acc_handle_t odr_handle; uint32_t *odr_cl; ddi_acc_handle_t odr_cl_handle; uint32_t *isr; ddi_acc_handle_t isr_handle; uint32_t *imr; ddi_acc_handle_t imr_handle; uint32_t *ipq; ddi_acc_handle_t ipq_handle; uint32_t *opq; ddi_acc_handle_t opq_handle; CfgTable_t *ct; ddi_acc_handle_t ct_handle; CfgTrans_Perf_t *cp; ddi_acc_handle_t cp_handle; uint32_t legacy_mapping; uint32_t noe_support; /* SG */ uint32_t sg_cnt; /* SG */ uint32_t ctlr_maxcmds; uint32_t host_support; uint8_t controller_lockup; uint8_t lockup_logged; uint32_t poll_flag; } cpqary3_t; /* * Private Structure for Self Issued Commands */ typedef struct cpqary3_driver_private { void *sg; cpqary3_phyctg_t *phyctgp; }cpqary3_private_t; /* cmd_flags */ #define CFLAG_DMASEND 0x01 #define CFLAG_CMDIOPB 0x02 #define CFLAG_DMAVALID 0x04 /* * Driver Private Packet */ typedef struct cpqary3_pkt { struct scsi_pkt *scsi_cmd_pkt; ddi_dma_win_t prev_winp; ddi_dma_seg_t prev_segp; clock_t cmd_start_time; /* SG */ ddi_dma_cookie_t cmd_dmacookies[MAX_PERF_SG_CNT]; /* SG */ uint32_t cmd_ncookies; uint32_t cmd_cookie; uint32_t cmd_cookiecnt; uint32_t cmd_nwin; uint32_t cmd_curwin; off_t cmd_dma_offset; size_t cmd_dma_len; size_t cmd_dmacount; struct buf *bf; ddi_dma_handle_t cmd_dmahandle; uint32_t bytes; uint32_t cmd_flags; uint32_t cdb_len; uint32_t scb_len; cpqary3_cmdpvt_t *memp; } cpqary3_pkt_t; #pragma pack(1) typedef struct cpqary3_ioctlresp { /* Driver Revision */ struct cpqary3_revision { uint8_t minor; /* Version */ uint8_t major; uint8_t mm; /* Revision Date */ uint8_t dd; uint16_t yyyy; } cpqary3_drvrev; /* HBA Info */ struct cpqary3_ctlr { uint8_t num_of_tgts; /* No of Logical Drive */ uint8_t *name; } cpqary3_ctlr; } cpqary3_ioctlresp_t; typedef struct cpqary3_ioctlreq { cpqary3_ioctlresp_t *cpqary3_ioctlrespp; } cpqary3_ioctlreq_t; #pragma pack() /* Driver function definitions */ void cpqary3_init_hbatran(cpqary3_t *); void cpqary3_read_conf_file(dev_info_t *, cpqary3_t *); void cpqary3_tick_hdlr(void *); void cpqary3_flush_cache(cpqary3_t *); void cpqary3_intr_onoff(cpqary3_t *, uint8_t); void cpqary3_lockup_intr_onoff(cpqary3_t *, uint8_t); uint8_t cpqary3_disable_NOE_command(cpqary3_t *); uint8_t cpqary3_send_NOE_command(cpqary3_t *, cpqary3_cmdpvt_t *, uint8_t); uint16_t cpqary3_init_ctlr_resource(cpqary3_t *); uint32_t cpqary3_hw_isr(caddr_t); uint32_t cpqary3_sw_isr(caddr_t); int32_t cpqary3_ioctl_driver_info(uintptr_t, int); int32_t cpqary3_ioctl_ctlr_info(uintptr_t, cpqary3_t *, int); int32_t cpqary3_ioctl_bmic_pass(uintptr_t, cpqary3_t *, int); int32_t cpqary3_ioctl_scsi_pass(uintptr_t, cpqary3_t *, int); uint8_t cpqary3_probe4targets(cpqary3_t *); void cpqary3_cmdlist_release(cpqary3_cmdpvt_t *, uint8_t); int32_t cpqary3_submit(cpqary3_t *, uint32_t); void cpqary3_free_phyctgs_mem(cpqary3_phyctg_t *, uint8_t); caddr_t cpqary3_alloc_phyctgs_mem(cpqary3_t *, size_t, uint32_t *, cpqary3_phyctg_t *); cpqary3_cmdpvt_t *cpqary3_cmdlist_occupy(cpqary3_t *); void cpqary3_synccmd_complete(cpqary3_cmdpvt_t *); void cpqary3_NOE_handler(cpqary3_cmdpvt_t *); uint8_t cpqary3_retrieve(cpqary3_t *); void cpqary3_synccmd_cleanup(cpqary3_cmdpvt_t *); int cpqary3_target_geometry(struct scsi_address *); uint8_t cpqary3_send_abortcmd(cpqary3_t *, uint16_t, CommandList_t *); void cpqary3_memfini(cpqary3_t *, uint8_t); uint8_t cpqary3_init_ctlr(cpqary3_t *); int16_t cpqary3_meminit(cpqary3_t *); void cpqary3_noe_complete(cpqary3_cmdpvt_t *cpqary3_cmdpvtp); cpqary3_cmdpvt_t *cpqary3_synccmd_alloc(cpqary3_t *, size_t); void cpqary3_synccmd_free(cpqary3_t *, cpqary3_cmdpvt_t *); int cpqary3_synccmd_send(cpqary3_t *, cpqary3_cmdpvt_t *, clock_t, int); uint8_t cpqary3_poll_retrieve(cpqary3_t *cpqary3p, uint32_t poll_tag); uint8_t cpqary3_build_cmdlist(cpqary3_cmdpvt_t *cpqary3_cmdpvtp, uint32_t tid); #ifdef __cplusplus } #endif #endif /* _CPQARY3_H */