/* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #ifndef _FCSM_H #define _FCSM_H #ifdef __cplusplus extern "C" { #endif #ifdef _KERNEL /* * Message printing flags */ #define SM_LOG 1 #define SM_CONSOLE 2 #define SM_LOG_AND_CONSOLE 3 /* * Debug levels */ #define SMDL_TRACE 0x0001 #define SMDL_IO 0x0002 #define SMDL_ERR 0x0004 #define SMDL_INFO 0x0008 #ifdef DEBUG #define FCSM_DEBUG(level, args) \ if (fcsm_debug & (level)) fcsm_display args extern uint32_t fcsm_debug; #else /* DEBUG */ #define FCSM_DEBUG(level, args) #endif /* DEBUG */ #define FCSM_INIT_INSTANCES 8 /* # of instances for soft_state_init */ /* * Open flags */ #define FCSM_IDLE 0x00 #define FCSM_OPEN 0x01 #define FCSM_EXCL 0x02 #define FCSM_ELS_TIMEOUT (20) /* secs */ #define FCSM_MS_TIMEOUT (20) /* secs */ #define FCSM_OFFLINE_TICKER (120) /* secs */ /* Definitions for command retries */ #define FCSM_MAX_CMD_RETRIES 5 /* Max retries in case of failure */ #define FCSM_RETRY_INTERVAL 3 /* Retry interval in seconds */ #define FCSM_RETRY_TICKER 1 /* Retry thread execution interval */ #define FCSM_MAX_JOB_RETRIES 3 /* Max retries in case of job failure */ /* * fcsm_job - Job structure to issue commands using command thread */ typedef struct fcsm_job { uint32_t job_code; /* Command code */ uint32_t job_flags; /* Command Flags */ int job_port_instance; /* port driver instance */ int job_result; /* job completion result */ opaque_t job_arg; /* Command Arguments */ opaque_t job_caller_priv; /* Caller private */ void (*job_comp)(opaque_t, struct fcsm_job *, int); /* completion func */ opaque_t job_comp_arg; /* Arg for completion func */ kmutex_t job_mutex; /* per command mutex */ ksema_t job_sema; /* To wait for completion */ struct fcsm_job *job_next; /* for linked list */ int job_retry_count; /* Retry count */ void *job_priv; /* for fcsm private use */ uint32_t job_priv_flags; /* fcsm private flags */ } fcsm_job_t; /* * fcsm_t - FCSM Structure for per port information */ typedef struct fcsm { kmutex_t sm_mutex; /* mutex for protection */ struct fcsm *sm_next; /* for global linked list */ int sm_sid; /* FCA Port ID */ int sm_instance; /* fc port instance number */ uint32_t sm_port_state; /* FCA port state */ uint32_t sm_port_top; /* Port topology */ uint32_t sm_state; /* San Mgmt State information */ uint32_t sm_flags; /* San Mgmt Flags (see below) */ int sm_ncmds; /* # of pending commands */ int sm_cb_count; /* # callbacks in progress */ fc_ulp_port_info_t sm_port_info; /* FCA Port Information */ fcsm_job_t *sm_job_head; /* port's job queue head */ fcsm_job_t *sm_job_tail; /* port's job queue tail */ struct fcsm_cmd *sm_retry_head; /* cmd retry queue head */ struct fcsm_cmd *sm_retry_tail; /* cmd retry queue tail */ timeout_id_t sm_retry_tid; /* retry timer */ timeout_id_t sm_offline_tid; /* offline timer */ kcondvar_t sm_job_cv; /* cv for job processing */ uint32_t sm_dev_count; /* # of devices discovered */ fc_portmap_t *sm_portmap; /* device map */ kthread_t *sm_thread; /* per port job thread */ kmem_cache_t *sm_cmd_cache; /* per port fc packet cache */ la_els_logi_t sm_ms_service_params; /* Mgmt Server Login Params */ callb_cpr_t sm_cpr_info; /* CPR info */ } fcsm_t; typedef struct fcsm_cmd { fc_packet_t *cmd_fp_pkt; fcsm_job_t *cmd_job; fcsm_t *cmd_fcsm; int cmd_retry_count; int cmd_retry_interval; int cmd_max_retries; struct fcsm_cmd *cmd_next; void (*cmd_comp)(struct fcsm_cmd *); int (*cmd_transport)(opaque_t, fc_packet_t *); uint32_t cmd_dma_flags; fc_packet_t cmd_fc_packet; } fcsm_cmd_t; /* * sm_flags in the per port FCSM Structure */ #define FCSM_ATTACHING 0x0001 #define FCSM_ATTACHED 0x0002 #define FCSM_DETACHING 0x0004 #define FCSM_DETACHED 0x0008 #define FCSM_SUSPENDED 0x0010 #define FCSM_POWER_DOWN 0x0020 #define FCSM_RESTORE_RETRY_TIMEOUT 0x0040 #define FCSM_RESTORE_OFFLINE_TIMEOUT 0x0080 #define FCSM_RETRY_TIMER_ACTIVE 0x0100 #define FCSM_SERIALIZE_JOBTHREAD 0x0200 #define FCSM_CMD_RETRY_Q_SUSPENDED 0x0400 #define FCSM_PORT_OFFLINE 0x0800 #define FCSM_LINK_DOWN 0x1000 #define FCSM_MGMT_SERVER_LOGGED_IN 0x2000 #define FCSM_MGMT_SERVER_LOGIN_IN_PROG 0x4000 /* Command flags for Job structure */ #define FCSM_JOBFLAG_SYNC 0x01 #define FCSM_JOBFLAG_ASYNC 0x02 #define FCSM_JOBFLAG_SERIALIZE 0x04 #define FCSM_JOBFLAG_CTHEADER_BE 0X08 /* Command codes */ #define FCSM_JOB_NONE 0x00 #define FCSM_JOB_THREAD_SHUTDOWN 0x01 #define FCSM_JOB_LOGIN_NAME_SERVER 0x02 #define FCSM_JOB_LOGIN_MGMT_SERVER 0x03 #define FCSM_JOB_CT_PASSTHRU 0x04 /* Private flags for command */ #define FCSM_JOB_PRIV_WAIT_FOR_LOGIN 0x01 #define FCSM_JOB_PRIV_LOGIN_IN_PROG 0x02 /* Command DMA Flags */ #define FCSM_CF_CMD_VALID_DMA_MEM 0x01 #define FCSM_CF_CMD_VALID_DMA_BIND 0x02 #define FCSM_CF_RESP_VALID_DMA_MEM 0x04 #define FCSM_CF_RESP_VALID_DMA_BIND 0x08 #define FCSM_INIT_CMD(cmd, job, tran_flags, tran_type, max_retries, func) { \ (cmd)->cmd_job = (job); \ (cmd)->cmd_fc_packet.pkt_tran_flags = (tran_flags); \ (cmd)->cmd_fc_packet.pkt_tran_type = (tran_type); \ (cmd)->cmd_max_retries = max_retries; \ (cmd)->cmd_comp = func; \ } /* * Macros to address endian issues */ #define FCSM_RD8(acchandle, addr) \ ddi_get8((acchandle), (uint8_t *)(addr)) #define FCSM_RD16(acchandle, addr) \ ddi_get16((acchandle), (uint16_t *)(addr)) #define FCSM_RD32(acchandle, addr) \ ddi_get32((acchandle), (uint32_t *)(addr)) #define FCSM_RD64(acchandle, addr) \ ddi_get64((acchandle), (uint64_t *)(addr)) #define FCSM_WR8(acchandle, addr, val) \ ddi_put8((acchandle), (uint8_t *)(addr), (uint8_t)(val)) #define FCSM_WR16(acchandle, addr, val) \ ddi_put16((acchandle), (uint16_t *)(addr), (uint16_t)(val)) #define FCSM_WR32(acchandle, addr, val) \ ddi_put32((acchandle), (uint32_t *)(addr), (uint32_t)(val)) #define FCSM_WR64(acchandle, addr, val) \ ddi_put64((acchandle), (uint64_t *)(addr), (uint64_t)(val)) #define FCSM_REP_RD(acchandle, hostaddr, devaddr, cnt) \ ddi_rep_get8((acchandle), (uint8_t *)(hostaddr), (uint8_t *)(devaddr),\ (size_t)(cnt), DDI_DEV_AUTOINCR) #define FCSM_REP_RD32(acchandle, hostaddr, devaddr, cnt) \ ddi_rep_get32((acchandle), (uint32_t *)(hostaddr), \ (uint32_t *)(devaddr), ((size_t)(cnt)) >> 2, DDI_DEV_AUTOINCR) #define FCSM_REP_WR(acchandle, hostaddr, devaddr, cnt) \ ddi_rep_put8((acchandle), (uint8_t *)(hostaddr), (uint8_t *)(devaddr),\ (size_t)(cnt), DDI_DEV_AUTOINCR) #define FCSM_REP_WR32(acchandle, hostaddr, devaddr, cnt) \ ddi_rep_put32((acchandle), (uint32_t *)(hostaddr),\ (uint32_t *)(devaddr), ((size_t)(cnt)) >> 2, DDI_DEV_AUTOINCR) /* * Macros to perform DMA Sync */ #define FCSM_SYNC_FOR_DEV(dmahandle, offset, length) \ (void) ddi_dma_sync((dmahandle), (offset),\ (size_t)(length), DDI_DMA_SYNC_FORDEV) #define FCSM_SYNC_FOR_KERNEL(dmahandle, offset, length) \ (void) ddi_dma_sync((acchandle), (offset),\ (length), DDI_DMA_SYNC_FORKERNEL) #endif /* _KERNEL */ /* * IOCTL Definitions */ typedef struct fc_ct_aiu { fc_ct_header_t aiu_header; char aiu_payload[1]; /* aiu_payload can be up to 'm' bytes (arbitrary length) */ } fc_ct_aiu_t; #define FCSMIO ('S' << 8) #define FCSMIO_CMD (FCSMIO | 2000) #define FCSMIO_SUB_CMD ('Y' << 8) #define FCSMIO_CT_CMD (FCSMIO_SUB_CMD + 0x01) #define FCSMIO_ADAPTER_LIST (FCSMIO_SUB_CMD + 0x02) #define FCSMIO_FIND_ADAPTER (FCSMIO_SUB_CMD + 0x03) #define FCSM_MAX_CT_SIZE (65536) /* 64K */ /* Management Server - Fabric Configuration Server Commands */ #define MS_CS_GTIN 0x0100 /* Get Topology Information */ #define MS_CS_GIEL 0x0101 /* Get Interconnect Element List */ #define MS_CS_GIET 0x0111 /* Get Interconnect Element Type */ #define MS_CS_GDID 0x0112 /* Get Domain Identifier */ #define MS_CS_GMID 0x0113 /* Get Management Identifier */ #define MS_CS_GFN 0x0114 /* Get Fabric Name */ #define MS_CS_GIELN 0x0115 /* Get Interconnect Element Logical Name */ #define MS_CS_GMAL 0x0116 /* Get Management Address List */ #define MS_CS_GIEIL 0x0117 /* Get Interconnect Element Information List */ #define MS_CS_GPL 0x0118 /* Get Port List */ #define MS_CS_GPT 0x0121 /* Get Port Type */ #define MS_CS_GPPN 0x0122 /* Get Physical Port Number */ #define MS_CS_GAPNL 0x0124 /* Get Attached Port Name List */ #define MS_CS_GPS 0x0126 /* Get Port State */ #define MS_CS_GATIN 0x0128 /* Get Attached Topology Information */ #define MS_CS_GPLNL 0x0191 /* Get Platform Node Name List */ #define MS_CS_GPLT 0x0192 /* Get Platform Type */ #define MS_CS_GPLML 0x0193 /* Get Platform Management Address List */ #define MS_CS_GNPL 0x01a1 /* Get Platform Name - Node Name */ #define MS_CS_GPNL 0x01a2 /* Get Platform Name List */ #define MS_CS_GNID 0x01b1 /* Get Node Identification Data - Node Name */ #define MS_CS_RIELN 0x0215 /* Register Interconnect Element Logical Name */ #define MS_CS_RPL 0x0280 /* Register Platform */ #define MS_CS_RPLN 0x0291 /* Register Platform Name */ #define MS_CS_RPLT 0x0292 /* Register Platform Type */ #define MS_CS_RPLM 0x0293 /* Register Platform Management Address */ #define MS_CS_DPL 0x0380 /* Deregister Platform */ #define MS_CS_DPLN 0x0391 /* Deregister Platform Node Name */ #define MS_CS_DPLML 0x0393 /* Deregister Platform Management Addr List */ #ifdef _KERNEL /* * Driver entry point functions */ static int fcsm_attach(dev_info_t *, ddi_attach_cmd_t); static int fcsm_detach(dev_info_t *, ddi_detach_cmd_t); static int fcsm_getinfo(dev_info_t *, ddi_info_cmd_t, void *, void **); static int fcsm_open(dev_t *, int, int, cred_t *); static int fcsm_close(dev_t, int, int, cred_t *); static int fcsm_ioctl(dev_t, int, intptr_t, int, cred_t *, int *); /* * FC Transport functions */ static int fcsm_port_attach(opaque_t, fc_ulp_port_info_t *, fc_attach_cmd_t, uint32_t); static int fcsm_port_detach(opaque_t, fc_ulp_port_info_t *, fc_detach_cmd_t); static int fcsm_port_ioctl(opaque_t, opaque_t, dev_t, int, intptr_t, int, cred_t *, int *, uint32_t); static void fcsm_statec_cb(opaque_t, opaque_t, uint32_t, uint32_t, fc_portmap_t *, uint32_t, uint32_t); static int fcsm_els_cb(opaque_t, opaque_t, fc_unsol_buf_t *, uint32_t); static int fcsm_data_cb(opaque_t, opaque_t, fc_unsol_buf_t *, uint32_t); /* * Internal functions */ static int fcsm_handle_port_attach(fc_ulp_port_info_t *, uint32_t, int); static int fcsm_handle_port_resume(opaque_t, fc_ulp_port_info_t *, fc_attach_cmd_t, uint32_t, fcsm_t *); static int fcsm_handle_port_detach(fc_ulp_port_info_t *, fcsm_t *, fc_detach_cmd_t); static void fcsm_suspend_port(fcsm_t *); static void fcsm_resume_port(fcsm_t *); static void fcsm_cleanup_port(fcsm_t *); static void fcsm_offline_timeout(void *); static int fcsm_fciocmd(intptr_t, int, cred_t *, fcio_t *); static int fcsm_fcio_copyout(fcio_t *, intptr_t, int); static int fcsm_job_cache_constructor(void *, void *, int); static void fcsm_job_cache_destructor(void *, void *); static fcsm_job_t *fcsm_alloc_job(int); static void fcsm_dealloc_job(fcsm_job_t *); static void fcsm_init_job(fcsm_job_t *, int, uint32_t, uint32_t, opaque_t, opaque_t, void (*comp)(opaque_t, fcsm_job_t *, int), opaque_t); static int fcsm_process_job(fcsm_job_t *, int); static void fcsm_enque_job(fcsm_t *, fcsm_job_t *, int); static fcsm_job_t *fcsm_deque_job(fcsm_t *); static int fcsm_cmd_cache_constructor(void *, void *, int); static void fcsm_cmd_cache_destructor(void *, void *); static fcsm_cmd_t *fcsm_alloc_cmd(fcsm_t *, uint32_t, uint32_t, int); static void fcsm_free_cmd_dma(fcsm_cmd_t *); static void fcsm_job_thread(fcsm_t *); static int fcsm_retry_job(fcsm_t *fcsm, fcsm_job_t *job); static void fcsm_jobdone(fcsm_job_t *); static void fcsm_ct_init(fcsm_t *, fcsm_cmd_t *, fc_ct_aiu_t *, size_t, void (*comp_func)()); static void fcsm_ct_intr(fcsm_cmd_t *); static void fcsm_job_ct_passthru(fcsm_job_t *); static int fcsm_login_and_process_job(fcsm_t *, fcsm_job_t *); static void fcsm_login_ms_comp(opaque_t, fcsm_job_t *, int); static void fcsm_els_init(fcsm_cmd_t *, uint32_t); static int fcsm_xlogi_init(fcsm_t *, fcsm_cmd_t *, uint32_t, void (*comp_func)(), uchar_t); static void fcsm_xlogi_intr(fcsm_cmd_t *); static void fcsm_job_login_mgmt_server(fcsm_job_t *); int fcsm_ct_passthru(int, fcio_t *, int, int, void (*func)(fcio_t *)); static void fcsm_ct_passthru_comp(opaque_t, fcsm_job_t *, int); static void fcsm_pkt_common_intr(fc_packet_t *); static int fcsm_issue_cmd(fcsm_cmd_t *); static int fcsm_retry_cmd(fcsm_cmd_t *); static void fcsm_enque_cmd(fcsm_t *, fcsm_cmd_t *); static fcsm_cmd_t *fcsm_deque_cmd(fcsm_t *); static void fcsm_retry_timeout(void *); static void fcsm_force_port_detach_all(void); /* * Utility functions */ static void fcsm_disp_devlist(fcsm_t *, fc_portmap_t *, uint32_t); static void fcsm_display(int, int, fcsm_t *, fc_packet_t *, const char *, ...); int fcsm_pkt_state_to_rval(uchar_t, uint32_t); caddr_t fcsm_port_state_to_str(uint32_t); caddr_t fcsm_topology_to_str(uint32_t); static caddr_t fcsm_dev_type_to_str(uint32_t); #endif /* _KERNEL */ #ifdef __cplusplus } #endif #endif /* _FCSM_H */