/* * 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 _SYS_1394_ADAPTERS_HCI1394_H #define _SYS_1394_ADAPTERS_HCI1394_H /* * hci1394.h * This file contains general defines and function prototypes for things * that did not warrant separate header files. */ #ifdef __cplusplus extern "C" { #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* Number of initial states to setup. Used in call to ddi_soft_state_init() */ #define HCI1394_INITIAL_STATES 3 /* * Size of the Address Map Array passed to the Service Layer. There are 4 * sections in the OpenHCI address space. They are Physical, Posted Write, * Normal, and CSR space. */ #define HCI1394_ADDR_MAP_SIZE 4 /* Macro to align address on a quadlet boundry */ #define HCI1394_ALIGN_QUAD(addr) (((addr) + 3) & 0xFFFFFFFC) /* These functions can be found in hci1394_attach.c */ int hci1394_attach(dev_info_t *dip, ddi_attach_cmd_t cmd); /* These functions can be found in hci1394_detach.c */ int hci1394_detach(dev_info_t *dip, ddi_detach_cmd_t cmd); void hci1394_detach_hardware(hci1394_state_t *soft_state); void hci1394_pci_fini(hci1394_state_t *soft_state); void hci1394_soft_state_fini(hci1394_state_t *soft_state); int hci1394_quiesce(dev_info_t *dip); /* These functions can be found in hci1394_misc.c */ hci1394_statevar_t hci1394_state(hci1394_drvinfo_t *drvinfo); int hci1394_state_set(hci1394_drvinfo_t *drvinfo, hci1394_statevar_t state); int hci1394_open(dev_t *devp, int flag, int otyp, cred_t *credp); int hci1394_close(dev_t dev, int flag, int otyp, cred_t *credp); void hci1394_shutdown(dev_info_t *dip); int hci1394_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg, void **result); /* These functions can be found in hci1394_ioctl.c */ int hci1394_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *credp, int *rvalp); /* These functions can be found in hci1394_isr.c */ int hci1394_isr_init(hci1394_state_t *soft_state); void hci1394_isr_fini(hci1394_state_t *soft_state); int hci1394_isr_handler_init(hci1394_state_t *soft_state); void hci1394_isr_handler_fini(hci1394_state_t *soft_state); void hci1394_isr_mask_setup(hci1394_state_t *soft_state); #ifdef __cplusplus } #endif #endif /* _SYS_1394_ADAPTERS_HCI1394_H */ /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License, Version 1.0 only * (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 (c) 1999-2000 by Sun Microsystems, Inc. * All rights reserved. */ #ifndef _SYS_1394_ADAPTERS_HCI1394_ASYNC_H #define _SYS_1394_ADAPTERS_HCI1394_ASYNC_H /* * hci1394_async.h * These routines the 1394 asynchronous dma engines. These include incoming * and outgoing reads, writes, and lock and their associated responses. */ #ifdef __cplusplus extern "C" { #endif #include #include #include #include #include #include #include #include /* * Async descriptor and data buffer sizes. The AR descriptor buffers do not need * to be very big. There will be 1 16 byte IM for every AR data buffer. If we * alloc a 16KByte ARRESP data buffer on X86, we could get 4 4KByte cookies. * This would use up 64 bytes in the descriptor buffer. We will never need more * space than that. A 256 byte descriptor should handle a 64K buffer on x86 * if it is broken into 16 cookies. */ #define ASYNC_ATREQ_DESC_SIZE 16384 #define ASYNC_ATREQ_DATA_SIZE 16384 #define ASYNC_ARRESP_DESC_SIZE 256 #define ASYNC_ARRESP_DATA_SIZE 16384 #define ASYNC_ARREQ_DESC_SIZE 256 #define ASYNC_ARREQ_DATA_SIZE 16384 #define ASYNC_ATRESP_DESC_SIZE 16384 #define ASYNC_ATRESP_DATA_SIZE 16384 /* handle passed back from init() and used for rest of functions */ typedef struct hci1394_async_s *hci1394_async_handle_t; /* * Async Command State. This state is used to catch a race condition between * the ATREQ complete interrupt handler and the ARRESP interrupt handler. The * ATREQ will always complete before the ARRESP arrives, but SW may not see it * that way. See hci1394_async_atreq_process() for more information on this. */ typedef enum { HCI1394_CMD_STATE_IN_PROGRESS, HCI1394_CMD_STATE_PENDING, HCI1394_CMD_STATE_COMPLETED } hci1394_async_cstate_t; typedef struct hci1394_async_cmd_s { /* Pointer to framework command allocted by services layer */ cmd1394_cmd_t *ac_cmd; /* * Pointer to HAL/SL private area in the command. This is private info * shared between the HAL and Services Layer on a per command basis. */ h1394_cmd_priv_t *ac_priv; /* * Status on if we allocated a tlabel for an ATREQ. Normally we will * allocate a tlabel with every ATREQ. But, we will not allocate a * tlabel for a PHY packet. When we initialize the command, we will * assume that we are going to allocate a tlabel. The async phy command * will "override" this setting and set ac_tlabel_alloc to b_false. */ boolean_t ac_tlabel_alloc; /* handle for tlabel logic */ hci1394_tlabel_info_t ac_tlabel; /* * This is used for ARREQs. When we get a block read or write request, * we allocate a mblk to put the data into. After the ATRESP has been * sent out and has completed, hci1394_async_response_complete() is * called to free up the ARREQ resources which were allocated. This * routine will free the mblk if we allocated it in ARREQ. If an ARREQ * block write is received and the target driver wishes to keep the * mblk w/ the data (to pass it up a stream), but releases the command, * it can set the mblk pointer in the command to null. We will check * for mblk being == to NULL even if ac_mblk_alloc is set to true. */ boolean_t ac_mblk_alloc; /* * ac_status contains the 1394 RESP for an ARRESP or the ACK for ARREQ. * This status is set in either hci1394_async_arresp_read() or * hci1394_arreq_read() */ int ac_status; /* * Destination packet was sent to. This is used to determine if the * packet was broadcast or not in hci1394_async_arreq_read(). */ uint_t ac_dest; /* * Async command state. See comments above for more information. Other * than initialization, this field is only accessed in the ISR. State * is only used in ATREQ/ARRESP processing. */ hci1394_async_cstate_t ac_state; /* * Pointer back to the Async private state. This allows us to access * the async state structures if all we have is a pointer to the async * command. */ struct hci1394_async_s *ac_async; /* * pending list node structure. If a command is pended, this node is * what's passed to the tlist code to add the node to the pending list. * It contains all the pointers the linked list needs so that we do not * need to allocate any space every time we add something to the list. */ hci1394_tlist_node_t ac_plist_node; /* * hci1394_q information about this command. This is used for AT * commands. It contains information passed down to the hci1394_q_at*() * routines like qc_timestamp which is used to tell the HW when an * ATRESP has timed out out. The status of the AT command is returned * in qc_status after calling hci1394_q_at_next(). The rest of the * structure members are private members used to track the descriptor * and data buffer usage. */ hci1394_q_cmd_t ac_qcmd; } hci1394_async_cmd_t; _NOTE(SCHEME_PROTECTS_DATA("Used only by one thread", hci1394_async_cmd_s \ hci1394_async_cmd_s::ac_qcmd.qc_arg \ hci1394_async_cmd_s::ac_qcmd.qc_generation \ hci1394_async_cmd_s::ac_qcmd.qc_timestamp \ hci1394_async_cmd_s::ac_tlabel_alloc \ hci1394_async_cmd_s::ac_tlabel.tbi_destination \ hci1394_async_cmd_s::ac_tlabel.tbi_tlabel)) /* * async private state information. It contains handles for the various modules * that async uses. */ typedef struct hci1394_async_s { hci1394_tlist_handle_t as_pending_list; hci1394_ohci_handle_t as_ohci; hci1394_tlabel_handle_t as_tlabel; hci1394_csr_handle_t as_csr; hci1394_q_handle_t as_atreq_q; hci1394_q_handle_t as_arresp_q; hci1394_q_handle_t as_arreq_q; hci1394_q_handle_t as_atresp_q; hci1394_drvinfo_t *as_drvinfo; /* * as_flushing_arreq is used in bus reset processing. It is set by * hci1394_async_arreq_flush() and tells hci1394_async_arreq_process() * not to send the ARREQ up to the Services Layer. It will be set to * FALSE by hci1394_async_arreq_read_phy() when a bus reset token with * the current bus generation is found. as_phy_reset is used to store * the last PHY packet generation seen in the ARREQ Q. The HW puts a * token in the ARREQ Q so that the SW can flush the Q up to and * including the token. */ boolean_t as_flushing_arreq; uint_t as_phy_reset; /* * as_atomic_lookup is used to protect the cmd from a race condition * between the ARRESP and the Pending Timeout callback. This is * explained in more detail in hci1394_async_atreq_process(). */ kmutex_t as_atomic_lookup; } hci1394_async_t; _NOTE(SCHEME_PROTECTS_DATA("Used only by one thread", \ hci1394_async_s::as_flushing_arreq hci1394_async_s::as_phy_reset)) int hci1394_async_init(hci1394_drvinfo_t *drvinfo, hci1394_ohci_handle_t ohci_handle, hci1394_csr_handle_t csr_handle, hci1394_async_handle_t *async_handle); void hci1394_async_fini(hci1394_async_handle_t *async_handle); void hci1394_async_suspend(hci1394_async_handle_t async_handle); int hci1394_async_resume(hci1394_async_handle_t async_handle); uint_t hci1394_async_cmd_overhead(); void hci1394_async_flush(hci1394_async_handle_t async_handle); void hci1394_async_atreq_reset(hci1394_async_handle_t async_handle); void hci1394_async_atresp_reset(hci1394_async_handle_t async_handle); void hci1394_async_pending_timeout_update(hci1394_async_handle_t async_handle, hrtime_t timeout); int hci1394_async_atreq_process(hci1394_async_handle_t async_handle, boolean_t flush_q, boolean_t *request_available); int hci1394_async_arresp_process(hci1394_async_handle_t async_handle, boolean_t *response_available); int hci1394_async_arreq_process(hci1394_async_handle_t async_handle, boolean_t *request_available); int hci1394_async_atresp_process(hci1394_async_handle_t async_handle, boolean_t flush_q, boolean_t *response_available); int hci1394_async_phy(hci1394_async_handle_t async_handle, cmd1394_cmd_t *cmd, h1394_cmd_priv_t *cmd_priv, int *result); int hci1394_async_write(hci1394_async_handle_t async_handle, cmd1394_cmd_t *cmd, h1394_cmd_priv_t *cmd_priv, int *result); int hci1394_async_read(hci1394_async_handle_t async_handle, cmd1394_cmd_t *cmd, h1394_cmd_priv_t *cmd_priv, int *result); int hci1394_async_lock(hci1394_async_handle_t async_handle, cmd1394_cmd_t *cmd, h1394_cmd_priv_t *cmd_priv, int *result); int hci1394_async_write_response(hci1394_async_handle_t async_handle, cmd1394_cmd_t *cmd, h1394_cmd_priv_t *cmd_priv, int *result); int hci1394_async_read_response(hci1394_async_handle_t async_handle, cmd1394_cmd_t *cmd, h1394_cmd_priv_t *cmd_priv, int *result); int hci1394_async_lock_response(hci1394_async_handle_t async_handle, cmd1394_cmd_t *cmd, h1394_cmd_priv_t *cmd_priv, int *result); void hci1394_async_response_complete(hci1394_async_handle_t async_handle, cmd1394_cmd_t *cmd, h1394_cmd_priv_t *cmd_priv); #ifdef __cplusplus } #endif #endif /* _SYS_1394_ADAPTERS_HCI1394_ASYNC_H */ /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License, Version 1.0 only * (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 (c) 1999-2000 by Sun Microsystems, Inc. * All rights reserved. */ #ifndef _SYS_1394_ADAPTERS_HCI1394_BUF_H #define _SYS_1394_ADAPTERS_HCI1394_BUF_H /* * hci1394_buf.h * These routines handle IO bound memory. They include routines to alloc and * free. IO bound memory and a routine to get the adapter's default dma * attributes. */ #ifdef __cplusplus extern "C" { #endif #include #include #include /* * Input parameters into buf_alloc(). * bp_length - size of buffer to alloc and map into IO space. * bp_max_cookies - maximum number of cookies we can handle. * bp_alignment - buffer alignment requirements. * * bp_max_cookies overwrites the adapter's default dma_attr_sgllen setting. * bp_alignment overwrites the adapter's default dma_attr_align setting. */ typedef struct hci1394_buf_parms_s { size_t bp_length; uint_t bp_max_cookies; uint64_t bp_alignment; } hci1394_buf_parms_t; /* * Output from buf_alloc(). This structure contains information * about the buffer allocated. */ typedef struct hci1394_buf_info_s { ddi_dma_cookie_t bi_cookie; /* ddi_dma_addr_bind_handle */ uint_t bi_cookie_count; /* ddi_dma_addr_bind_handle */ caddr_t bi_kaddr; /* ddi_dma_mem_alloc */ size_t bi_length; /* copy of input parms bp_length */ size_t bi_real_length; /* ddi_dma_mem_alloc */ ddi_acc_handle_t bi_handle; /* ddi_dma_mem_alloc */ ddi_dma_handle_t bi_dma_handle; /* ddi_dma_alloc_handle */ } hci1394_buf_info_t; /* * private structure to track buffer information */ typedef struct hci1394_buf_s { ddi_acc_handle_t bu_handle; ddi_dma_handle_t bu_dma_handle; hci1394_drvinfo_t *bu_drvinfo; } hci1394_buf_t; /* * handle passed back from alloc() and used for free() */ typedef struct hci1394_buf_s *hci1394_buf_handle_t; void hci1394_buf_attr_get(ddi_dma_attr_t *dma_attr); int hci1394_buf_alloc(hci1394_drvinfo_t *drvinfo, hci1394_buf_parms_t *parms, hci1394_buf_info_t *info, hci1394_buf_handle_t *handle); void hci1394_buf_free(hci1394_buf_handle_t *handle); /* warlock directives */ _NOTE(SCHEME_PROTECTS_DATA("Single user", hci1394_buf_info_s hci1394_buf_s)) #ifdef __cplusplus } #endif #endif /* _SYS_1394_ADAPTERS_HCI1394_BUF_H */ /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License, Version 1.0 only * (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 (c) 1999-2000 by Sun Microsystems, Inc. * All rights reserved. */ #ifndef _SYS_1394_ADAPTERS_HCI1394_CSR_H #define _SYS_1394_ADAPTERS_HCI1394_CSR_H /* * hci1394_csr.h * This file contains the code for the CSR registers handled by the HAL in * SW. The HW implemented CSR registers are in hci1394_ohci.c * * For more information on CSR registers, see * IEEE 1212 * IEEE 1394-1995 * section 8.3.2 * IEEE P1394A Draft 3.0 * sections 10.32,10.33 * * NOTE: A read/write to a CSR SW based register will first go to the Services * Layer which will do some filtering and then come through the s1394if. */ #ifdef __cplusplus extern "C" { #endif #include #include #include #include /* * The 1394 bus sends out cycle start packets periodically. The time in * between these packets is commonly referred to as a bus cycle. The 1394 * cycle start packets come every 125uS. split_timeout is represented in 1394 * bus cycles (e.g. to have ATREQ ACK_PENDED timeout after 100mS, you would set * split_timeout to 800). * * The CSR register interface has the split timeout broken into two registers, * split_timeout_hi and split_timeout_lo. The least significant 3 bits of * split_timeout_hi contain the # of seconds and the most significant 13 bits * of split_timeout_lo contain the fraction of a seconds in 125uS increments. * There is a further constraint that the value in split_timeout_lo must be >= * 800 && <= 7999 (>=100mS && < 1S). (don't forget that this value is in the * most significant 13 bits, i.e. 800 << 19) We will threshold the writes into * these registers to make sure they always have legal values (i.e. if * [8000 << 19] is written to split_timeout_lo, we will write [7999 << 19]. * * The split timeout CSR registers have some inherent problems. There is a race * condition when updating the split timeout value since you cannot atomically * write to both the hi and lo registers. This should not be a serious problem * since we should never get close to having a split timeout of 1S or greater. */ /* CSR Register Address Offsets (1394-1995 8.3.2.2) */ #define CSR_STATE_CLEAR 0x000 #define CSR_STATE_SET 0x004 #define CSR_NODE_IDS 0x008 #define CSR_RESET_START 0x00C #define CSR_SPLIT_TIMEOUT_HI 0x018 #define CSR_SPLIT_TIMEOUT_LO 0x01C #define CSR_CYCLE_TIME 0x200 #define CSR_BUS_TIME 0x204 #define CSR_BUSY_TIMEOUT 0x210 #define CSR_BUS_MANAGER_ID 0x21C #define CSR_BANDWIDTH_AVAILABLE 0x220 #define CSR_CHANNELS_AVAILABLE_HI 0x224 #define CSR_CHANNELS_AVAILABLE_LO 0x228 typedef struct hci1394_csr_s { /* SW registers */ uint32_t csr_state; uint32_t csr_split_timeout_lo; uint32_t csr_split_timeout_hi; /* split timeout that we are observing */ uint_t csr_split_timeout; /* were we root last bus reset */ boolean_t csr_was_root; /* our node capabilities */ uint32_t csr_capabilities; /* copies of OpenHCI handle and pointer to general driver info */ hci1394_ohci_handle_t csr_ohci; hci1394_drvinfo_t *csr_drvinfo; kmutex_t csr_mutex; } hci1394_csr_t; /* handle passed back from init() and used for rest of functions */ typedef struct hci1394_csr_s *hci1394_csr_handle_t; void hci1394_csr_init(hci1394_drvinfo_t *drvinfo, hci1394_ohci_handle_t ohci, hci1394_csr_handle_t *csr_handle); void hci1394_csr_fini(hci1394_csr_handle_t *csr_handle); void hci1394_csr_resume(hci1394_csr_handle_t csr_handle); void hci1394_csr_node_capabilities(hci1394_csr_handle_t csr_handle, uint32_t *capabilities); void hci1394_csr_state_get(hci1394_csr_handle_t csr_handle, uint32_t *state); void hci1394_csr_state_bset(hci1394_csr_handle_t csr_handle, uint32_t state); void hci1394_csr_state_bclr(hci1394_csr_handle_t csr_handle, uint32_t state); void hci1394_csr_split_timeout_hi_get(hci1394_csr_handle_t csr_handle, uint32_t *split_timeout_hi); void hci1394_csr_split_timeout_lo_get(hci1394_csr_handle_t csr_handle, uint32_t *split_timeout_lo); void hci1394_csr_split_timeout_hi_set(hci1394_csr_handle_t csr_handle, uint32_t split_timeout_hi); void hci1394_csr_split_timeout_lo_set(hci1394_csr_handle_t csr_handle, uint32_t split_timeout_lo); uint_t hci1394_csr_split_timeout_get(hci1394_csr_handle_t csr_handle); void hci1394_csr_bus_reset(hci1394_csr_handle_t csr_handle); #ifdef __cplusplus } #endif #endif /* _SYS_1394_ADAPTERS_HCI1394_CSR_H */ /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License, Version 1.0 only * (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 (c) 1999-2000 by Sun Microsystems, Inc. * All rights reserved. */ #ifndef _SYS_1394_ADAPTERS_HCI1394_DEF_H #define _SYS_1394_ADAPTERS_HCI1394_DEF_H /* * hci1394_def.h * This should be the first file included before any other hci1394 * include file. It should only contain defines which are used by other * hci1394 include files. * * The one exception is for the typedef hci1394_state_t. This is in here * to simplify header organization. * * Other than hci1394_state_t, no macros, structures, or prototypes should * be in this file. */ #ifdef __cplusplus extern "C" { #endif /* The maximum number of Isochronous contexts in an OpenHCI adapter */ #define HCI1394_MAX_ISOCH_CONTEXTS 32 /* hci1394 driver state pointer */ typedef struct hci1394_state_s hci1394_state_t; #ifdef __cplusplus } #endif #endif /* _SYS_1394_ADAPTERS_HCI1394_DEF_H */ /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License, Version 1.0 only * (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 (c) 1999-2000 by Sun Microsystems, Inc. * All rights reserved. */ #ifndef _SYS_1394_ADAPTERS_HCI1394_DESCRIPTORS_H #define _SYS_1394_ADAPTERS_HCI1394_DESCRIPTORS_H /* * hci1394_descriptors.h * 1394 Open HCI command descriptors. * These are DMA commands chained together to form packets. */ #ifdef __cplusplus extern "C" { #endif #include /* * There are 2 different 1394 Open HCI entities defined in this file. * The HCI DMA descriptors (aka context descriptors or descriptor * commands), and the packet formats. * * Packet formats are used within descriptors for transmit and * are available in buffers for receive. EACH PACKET TYPE * (such as read_quadlet_request) may have a different format * depending on whether it is to be transmitted or whether it * is being received. * * In general, fields within a packet remain in the same location * within a quadlet either way. However, the location of the * quadlets themselves may be different. * * In an attempt to clarify what is used for what, Macros used * for setting up packets within a descriptor (an "Immediate" command) * shall have "DESC" in their name. Macros used for reading packets * from an input buffer shall have "PKT" in their name. * * For more information, see OpenHCI 1.00 chapters 7 (Asynch Transmit), * 8 (Asynch Receive), 9 (Isoch Transmit) and 10 (Isoch Receive). * Each chapter shows the DMA descriptors at the beginning, and * the packet formats at the end. * Also see chapter 11 (Self ID). */ /* * hci1394_desc is the basic format used for the following descriptor commands: * OUTPUT_MORE, OUTPUT_LAST, INPUT_MORE and INPUT_LAST */ typedef struct hci1394_desc_s { uint32_t hdr; uint32_t data_addr; uint32_t branch; /* branch or skip address (& Z) */ uint32_t status; /* status and/or (timestamp or rescount) */ } hci1394_desc_t; _NOTE(SCHEME_PROTECTS_DATA("Single thread modifies", hci1394_desc_s)) /* * hci1394_desc_imm is the basic format used for the "immediate" descriptor * commands: OUTPUT_MORE_IMMEDIATE and OUTPUT_LAST_IMMEDIATE. */ typedef struct hci1394_desc_imm_s { uint32_t hdr; uint32_t data_addr; uint32_t branch; uint32_t status; uint32_t q1; uint32_t q2; uint32_t q3; uint32_t q4; } hci1394_desc_imm_t; _NOTE(SCHEME_PROTECTS_DATA("Single thread modifies", hci1394_desc_imm_s)) /* * hci1394_desc_hdr contains the immediate packet header quadlets * for OUTPUT_MORE_IMMEDIATE and OUTPUT_LAST_IMMEDIATE. A packet header * has up to 4 quadlets of data which are specific to the individual operation * and operation type (i.e. this data would be different between a quadlet read * and quadlet write). */ typedef struct hci1394_desc_hdr_s { uint32_t q1; uint32_t q2; uint32_t q3; uint32_t q4; } hci1394_desc_hdr_t; /* typedefs for each descriptor command */ typedef hci1394_desc_imm_t hci1394_output_more_imm_t; typedef hci1394_desc_t hci1394_output_more_t; typedef hci1394_desc_imm_t hci1394_output_last_imm_t; typedef hci1394_desc_t hci1394_output_last_t; typedef hci1394_desc_t hci1394_input_more_t; typedef hci1394_desc_t hci1394_input_last_t; /* * maximum number of 16-byte components comprising a descriptor block. * Note that "immediate" descriptors take up 32-bytes and therefore are * 2 Z counts. Refer to OHCI 1.00 sections 3.1.2, 7.1.5.1, 8.3.1, 9.2.1, * and table 10-2 for context specific info about Z. */ #define HCI1394_DESC_MAX_Z 8 /* * There are two sets of defines below. The first set includes * definitions for the descriptor header. Namely hdr, branch, and stat. * The second set includes definitions for the different packet header * formats that have to be placed in the immediate q1-q4 fields * of a descriptor. */ /* General descriptor HDR quadlet defs */ #define DESC_HDR_STAT_ENBL 0x08000000 /* AR, IT & IR only */ #define DESC_HDR_STAT_DSABL 0x00000000 /* AR, IT & IR only */ #define DESC_HDR_PING_ENBL 0x00800000 /* AT only */ #define DESC_HDR_REQCOUNT_MASK 0x0000FFFF /* IR only */ #define DESC_HDR_REQCOUNT_SHIFT 0 #define DESC_HDR_STVAL_MASK 0x0000FFFF /* IT STORE only */ #define DESC_HDR_STVAL_SHIFT 0 #define DESC_GET_HDR_REQCOUNT(DESCP) \ (((DESCP)->hdr & DESC_HDR_REQCOUNT_MASK) >> DESC_HDR_REQCOUNT_SHIFT) /* CMD_TYPE values */ #define DESC_TY_OUTPUT_MORE 0x00000000 /* AT & IT */ #define DESC_TY_OUTPUT_LAST 0x10000000 /* AT & IT */ #define DESC_TY_INPUT_MORE 0x20000000 /* AR & IR */ #define DESC_TY_INPUT_LAST 0x30000000 /* IR only */ #define DESC_TY_STORE 0x80000000 /* IT only */ /* CMD_KEY values */ #define DESC_KEY_REF 0x00000000 /* reference ptr to data */ #define DESC_KEY_IMMED 0x02000000 /* immediate data */ #define DESC_KEY_STORE 0x06000000 /* store data */ /* CMD_BR and CMD_INT values - two bits */ #define DESC_INTR_DSABL 0x00000000 #define DESC_INTR_ENBL 0x00300000 #define DESC_BR_DSABL 0x00000000 #define DESC_BR_ENBL 0x000C0000 #define DESC_W_DSABL 0x00000000 #define DESC_W_ENBL 0x00030000 /* * Shortcuts for AT Descriptor types. We will always interrupt upon command * completion for AT OL, OLI, and IM. */ #define DESC_AT_OM DESC_TY_OUTPUT_MORE #define DESC_AT_OMI (DESC_TY_OUTPUT_MORE | DESC_KEY_IMMED) #define DESC_AT_OL (DESC_TY_OUTPUT_LAST | DESC_INTR_ENBL | DESC_BR_ENBL) #define DESC_AT_OLI (DESC_AT_OL | DESC_KEY_IMMED) #define DESC_AR_IM (DESC_TY_INPUT_MORE | DESC_HDR_STAT_ENBL | \ DESC_INTR_ENBL | DESC_BR_ENBL) /* * descriptor BRANCH field defs * Branch addresses are 16-byte aligned. the low order 4-bits are * used for the Z value. */ #define DESC_BRANCH_MASK 0xFFFFFFF0 #define DESC_Z_MASK 0x0000000F #define HCI1394_SET_BRANCH(DESCP, ADDR, Z) ((DESCP)->branch = 0 | \ ((ADDR) & DESC_BRANCH_MASK) | ((Z) & DESC_Z_MASK)) #define HCI1394_GET_BRANCH_ADDR(DESCP) ((DESCP)->branch & ~DESC_Z_MASK) #define HCI1394_GET_BRANCH_Z(DESCP) ((DESCP)->branch & DESC_Z_MASK) /* * descriptor STATUS field defs. comprised of xfer status and either * a timestamp or a residual count (rescount) */ #define DESC_ST_XFER_STAT_MASK 0xFFFF0000 #define DESC_ST_XFER_STAT_SHIFT 16 #define DESC_ST_RESCOUNT_MASK 0x0000FFFF /* AR, IR only */ #define DESC_ST_RESCOUNT_SHIFT 0 #define DESC_ST_TIMESTAMP_MASK 0x0000FFFF /* AT, IT only */ #define DESC_ST_TIMESTAMP_SHIFT 0 #define HCI1394_DESC_RESCOUNT_GET(data) ((data) & DESC_ST_RESCOUNT_MASK) #define HCI1394_DESC_TIMESTAMP_GET(data) ((data) & DESC_ST_TIMESTAMP_MASK) /* * XFER status fields are the same as the context control fields. * but in the high 16 bits */ #define DESC_XFER_RUN_MASK (OHCI_CC_RUN_MASK << DESC_ST_XFER_STAT_SHIFT) #define DESC_XFER_WAKE_MASK (OHCI_CC_WAKE_MASK << DESC_ST_XFER_STAT_SHIFT) #define DESC_XFER_DEAD_MASK (OHCI_CC_DEAD_MASK << DESC_ST_XFER_STAT_SHIFT) #define DESC_XFER_ACTIVE_MASK (OHCI_CC_ACTIVE_MASK << DESC_ST_XFER_STAT_SHIFT) #define DESC_AT_SPD_MASK 0x7 #define DESC_AT_SPD_SHIFT 16 #define DESC_AR_SPD_MASK 0x00E00000 #define DESC_AR_SPD_SHIFT 21 #define DESC_AR_EVT_MASK 0x001F0000 #define DESC_AR_EVT_SHIFT 16 #define HCI1394_DESC_EVT_GET(data) \ (((data) & DESC_AR_EVT_MASK) >> DESC_AR_EVT_SHIFT) #define HCI1394_DESC_AR_SPD_GET(data) \ (((data) & DESC_AR_SPD_MASK) >> DESC_AR_SPD_SHIFT) #define HCI1394_DESC_AT_SPD_SET(data) \ (((data) & DESC_AT_SPD_MASK) << DESC_AT_SPD_SHIFT) /* * XferStatus events are as follows */ #define DESC_EVT_NO_STATUS 0x00 /* AT, AR, IT, IR */ #define DESC_EVT_LONG_PKT 0x02 /* IR */ #define DESC_EVT_MISSING_ACK 0x03 /* AT */ #define DESC_EVT_UNDERRUN 0x04 /* AT, IT */ #define DESC_EVT_OVERRUN 0x05 /* IR */ #define DESC_EVT_DESC_READ 0x06 /* AT, AR, IT, IR */ #define DESC_EVT_DATA_READ 0x07 /* AT, IT */ #define DESC_EVT_DATA_WRITE 0x08 /* AR, IR */ #define DESC_EVT_BUS_RESET 0x09 /* AR */ #define DESC_EVT_TIMEOUT 0x0A /* AT */ #define DESC_EVT_TCODE_ERR 0x0B /* AT, IT */ #define DESC_ACK_COMPLETE 0x11 /* AT, AR, IT, IR */ #define DESC_ACK_PENDING 0x12 /* AT, AR */ #define DESC_ACK_BUSY_X 0x14 /* AT */ #define DESC_ACK_BUSY_A 0x15 /* AT */ #define DESC_ACK_BUSY_B 0x16 /* AT */ #define DESC_ACK_TARDY 0x1B /* AT */ #define DESC_ACK_DATA_ERR 0x1D /* AT IR */ #define DESC_ACK_TYPE_ERR 0x1E /* AT, AR */ /* * Response packet response codes */ #define DESC_RESP_COMPLETE 0x0 #define DESC_RESP_CONFLICT_ERR 0x4 #define DESC_RESP_DATA_ERR 0x5 #define DESC_RESP_TYPE_ERR 0x6 #define DESC_RESP_ADDR_ERR 0x7 /* * Context dependent MACROs used to set up the command headers and * Caller provides only the necessary variables. */ /* * Isochronous Transmit Descriptors */ #define HCI1394_INIT_IT_OMORE(DESCP, REQCOUNT) ((DESCP)->hdr = 0 | \ (DESC_TY_OUTPUT_MORE | DESC_KEY_REF | DESC_BR_DSABL | \ ((REQCOUNT) << DESC_HDR_REQCOUNT_SHIFT))) #define HCI1394_INIT_IT_OMORE_IMM(DESCP) ((DESCP)->hdr = 0 | \ (DESC_TY_OUTPUT_MORE | DESC_KEY_IMMED | DESC_BR_DSABL | \ (8 << DESC_HDR_REQCOUNT_SHIFT))) #define HCI1394_INIT_IT_OLAST(DESCP, STAT, INTR, REQCOUNT) ((DESCP)->hdr = 0 |\ (DESC_TY_OUTPUT_LAST | (STAT) | DESC_KEY_REF | (INTR) | \ DESC_BR_ENBL | ((REQCOUNT) << DESC_HDR_REQCOUNT_SHIFT))) #define HCI1394_INIT_IT_OLAST_IMM(DESCP, STAT, INTR) ((DESCP)->hdr = 0 | \ (DESC_TY_OUTPUT_LAST | (STAT) | DESC_KEY_IMMED | (INTR) | \ DESC_BR_ENBL | (8 << DESC_HDR_REQCOUNT_SHIFT))) #define HCI1394_INIT_IT_STORE(DESCP, VAL) ((DESCP)->hdr = 0 | \ (DESC_TY_STORE | DESC_KEY_STORE | ((VAL) << DESC_HDR_STVAL_SHIFT))) /* * Isochronous Receive Descriptors * PPB is Packet-Per-Buffer mode, BF is Buffer-Fill mode */ #define HCI1394_INIT_IR_PPB_IMORE(DESCP, WAIT, REQCOUNT) (DESCP)->hdr = 0 | \ (DESC_TY_INPUT_MORE | DESC_HDR_STAT_DSABL | DESC_KEY_REF | \ DESC_INTR_DSABL | DESC_BR_DSABL | (WAIT) | \ ((REQCOUNT) << DESC_HDR_REQCOUNT_SHIFT)); \ (DESCP)->status = 0 | (((REQCOUNT) << DESC_ST_RESCOUNT_SHIFT) & \ DESC_ST_RESCOUNT_MASK); #define HCI1394_INIT_IR_PPB_ILAST(DESCP, STAT, INTR, WAIT, REQCOUNT) \ (DESCP)->hdr = 0 | (DESC_TY_INPUT_LAST | (STAT) | DESC_KEY_REF | \ (INTR) | DESC_BR_ENBL | (WAIT) | \ ((REQCOUNT) << DESC_HDR_REQCOUNT_SHIFT)); \ (DESCP)->status = 0 | (((REQCOUNT) << DESC_ST_RESCOUNT_SHIFT) & \ DESC_ST_RESCOUNT_MASK); #define HCI1394_INIT_IR_BF_IMORE(DESCP, INT, WAIT, REQCOUNT) \ (DESCP)->hdr = 0 | (DESC_TY_INPUT_MORE | DESC_HDR_STAT_ENBL | \ DESC_KEY_REF | (INT) | DESC_BR_ENBL | (WAIT) | \ ((REQCOUNT) << DESC_HDR_REQCOUNT_SHIFT)); \ (DESCP)->status = 0 | (((REQCOUNT) << DESC_ST_RESCOUNT_SHIFT) & \ DESC_ST_RESCOUNT_MASK); /* * Packet Formats * * HCI packet formats typically comprise 2-4 quadlets for transmit * and 3-5 quadlets for receive. Although particular quadlets * may be in different parts of the 1394 header, the fields within * the quadlets remain in a consistent location. */ typedef struct hci1394_basic_packet { uint32_t q1; /* (HCI format) packet header w/tcode */ uint32_t q2; uint32_t q3; uint32_t q4; uint32_t q5; /* xferstatus/rescount for AR/IR */ } hci1394_basic_pkt_t; /* defs for the # of bytes are used in building the immediate descriptors */ /* These are used to set REQCOUNT in the HDR etc... */ #define DESC_FIVE_QUADS 20 #define DESC_FOUR_QUADS 16 #define DESC_THREE_QUADS 12 #define DESC_TWO_QUADS 8 #define DESC_ONE_QUAD 4 #define DESC_ONE_OCTLET 8 #define DESC_TWO_OCTLETS 16 #define DESC_PKT_HDRLEN_AT_READQUAD DESC_THREE_QUADS #define DESC_PKT_HDRLEN_AT_WRITEQUAD DESC_FOUR_QUADS #define DESC_PKT_HDRLEN_AT_READBLOCK DESC_FOUR_QUADS #define DESC_PKT_HDRLEN_AT_WRITEBLOCK DESC_FOUR_QUADS #define DESC_PKT_HDRLEN_AT_LOCK DESC_FOUR_QUADS #define DESC_PKT_HDRLEN_AT_PHY DESC_THREE_QUADS #define DESC_PKT_HDRLEN_AT_WRITE_RESP DESC_THREE_QUADS #define DESC_PKT_HDRLEN_AT_READQUAD_RESP DESC_FOUR_QUADS #define DESC_PKT_HDRLEN_AT_READBLOCK_RESP DESC_FOUR_QUADS #define DESC_PKT_HDRLEN_AT_LOCK_RESP DESC_FOUR_QUADS #define DESC_PKT_HDRLEN_AT_STREAM DESC_TWO_QUADS #define DESC_PKT_HDRLEN_AT_ISOCH DESC_PKT_HDRLEN_AT_STREAM /* q1 shortcuts for ASYNC processing */ #define DESC_AT_SRCBUSID 0x00800000 #define DESC_ATREQ_Q1_PHY 0x000000E0 #define DESC_ATREQ_Q1_QWR 0x00000100 #define DESC_ATREQ_Q1_BWR 0x00000110 #define DESC_ATREQ_Q1_QRD 0x00000140 #define DESC_ATREQ_Q1_BRD 0x00000150 #define DESC_ATREQ_Q1_LCK 0x00000190 #define DESC_ATRESP_Q1_WR 0x00000120 #define DESC_ATRESP_Q1_QRD 0x00000160 #define DESC_ATRESP_Q1_BRD 0x00000170 #define DESC_ATRESP_Q1_LCK 0x000001B0 /* q1 - definitions for the asynch packet first quadlet */ #define DESC_PKT_SRCBUSID_SHIFT 23 #define DESC_PKT_SRCBUSID_MASK 0x00800000 #define DESC_PKT_SPD_SHIFT 16 /* asynch and isoch */ #define DESC_PKT_SPD_MASK 0x00070000 #define DESC_PKT_TLABEL_SHIFT 10 /* asynch and isoch */ #define DESC_PKT_TLABEL_MASK 0x0000FC00 #define DESC_PKT_RT_SHIFT 8 #define DESC_PKT_RT_MASK 0x00000300 #define DESC_PKT_TCODE_SHIFT 4 /* asynch and isoch */ #define DESC_PKT_TCODE_MASK 0x000000F0 #define DESC_RT_RETRYX 0x1 /* q1 - definitions for the isoch first quadlet (see q1 async above for spd) */ #define DESC_PKT_TAG_SHIFT 14 #define DESC_PKT_TAG_MASK 0x0000C000 #define DESC_PKT_CHAN_SHIFT 8 #define DESC_PKT_CHAN_MASK 0x00003F00 #define DESC_PKT_SY_SHIFT 0 #define DESC_PKT_SY_MASK 0x0000000F /* q2 - definitions for the asynch second quadlet */ #define DESC_PKT_DESTID_SHIFT 16 /* 1st quadlet for AR */ #define DESC_PKT_DESTID_MASK 0xFFFF0000 #define DESC_PKT_SRCID_SHIFT 16 /* asynch recv only */ #define DESC_PKT_SRCID_MASK 0xFFFF0000 #define DESC_PKT_DESTOFFHI_SHIFT 0 #define DESC_PKT_DESTOFFHI_MASK 0x0000FFFF #define DESC_PKT_BUSID_SHIFT 22 /* in srcid or destid */ #define DESC_PKT_BUSID_MASK 0xFFC00000 /* in srcid or destid */ #define DESC_PKT_NODENUM_SHIFT 16 /* in srcid or destid */ #define DESC_PKT_NODENUM_MASK 0x003F0000 /* in srcid or destid */ #define DESC_PKT_RC_SHIFT 12 /* AT/AR read respnse */ #define DESC_PKT_RC_MASK 0x0000F000 /* AT/AR read respnse */ /* q3 - definitions for the asynch third quadlet */ #define DESC_PKT_DESTOFFLO_SHIFT 0 #define DESC_PKT_DESTOFFLO_MASK 0xFFFFFFFF #define DESC_PKT_PHYGEN_SHIFT 16 #define DESC_PKT_PHYGEN_MASK 0x00FF0000 /* q4 - definitions for the fourth quadlet */ #define DESC_PKT_QDATA_SHIFT 0 /* at_wr_quad, at_rd_resp_quad */ #define DESC_PKT_QDATA_MASK 0xFFFFFFFF #define DESC_PKT_DATALEN_SHIFT 16 /* at_rd_blk, at_wr_blk, isoch (q2), */ #define DESC_PKT_DATALEN_MASK 0xFFFF0000 /* at_rd_resp_blk, at_lock_resp, */ /* ar_rd_blk, ar_wr_blk, ar_lock, */ /* ar_rd_resp, ar_lock_resp */ #define DESC_PKT_EXTTCODE_MASK 0x0000FFFF /* * MACROS for getting and setting HCI packet fields */ /* ASYNCHRONOUS */ #define HCI1394_DESC_TCODE_GET(data) \ (((data) & DESC_PKT_TCODE_MASK) >> DESC_PKT_TCODE_SHIFT) #define HCI1394_DESC_TLABEL_GET(data) \ (((data) & DESC_PKT_TLABEL_MASK) >> DESC_PKT_TLABEL_SHIFT) #define HCI1394_DESC_RCODE_GET(data) \ (((data) & DESC_PKT_RC_MASK) >> DESC_PKT_RC_SHIFT) #define HCI1394_DESC_DESTID_GET(data) \ (((data) & DESC_PKT_DESTID_MASK) >> DESC_PKT_DESTID_SHIFT) #define HCI1394_DESC_SRCID_GET(data) \ (((data) & DESC_PKT_SRCID_MASK) >> DESC_PKT_SRCID_SHIFT) #define HCI1394_DESC_DATALEN_GET(data) \ (((data) & DESC_PKT_DATALEN_MASK) >> DESC_PKT_DATALEN_SHIFT) #define HCI1394_DESC_EXTTCODE_GET(data) \ ((data) & DESC_PKT_EXTTCODE_MASK) #define HCI1394_DESC_PHYGEN_GET(data) \ (((data) & DESC_PKT_PHYGEN_MASK) >> DESC_PKT_PHYGEN_SHIFT) #define HCI1394_DESC_TLABEL_SET(data) \ (((data) << DESC_PKT_TLABEL_SHIFT) & DESC_PKT_TLABEL_MASK) #define HCI1394_DESC_RCODE_SET(data) \ (((data) << DESC_PKT_RC_SHIFT) & DESC_PKT_RC_MASK) #define HCI1394_DESC_DESTID_SET(data) \ (((data) << DESC_PKT_DESTID_SHIFT) & DESC_PKT_DESTID_MASK) #define HCI1394_DESC_DATALEN_SET(data) \ (((data) << DESC_PKT_DATALEN_SHIFT) & DESC_PKT_DATALEN_MASK) #define HCI1394_DESC_EXTTCODE_SET(data) \ ((data) & DESC_PKT_EXTTCODE_MASK) /* ISOCHRONOUS */ /* * note: the GET macros for isoch take the actual quadlet as an arg because * the location of the IR header quadlet varies depending on the mode. * SETs are expected to be done only for isochronous transmit. */ #define HCI1394_GETTAG(Q) (((Q) & DESC_TAG_MASK) >> DESC_TAG_SHIFT) #define HCI1394_SETTAG(PKT, VAL) ((PKT)->q1 = (((PKT)->q1) & \ ~DESC_PKT_TAG_MASK) | (((VAL) << DESC_PKT_TAG_SHIFT) & \ DESC_PKT_TAG_MASK)) #define HCI1394_GETCHAN(Q) (((Q) & PKT_CHAN_MASK) >> \ DESC_PKT_CHAN_SHIFT) #define HCI1394_SETCHAN(PKT, VAL) ((PKT)->q1 = ((PKT)->q1) & \ ~DESC_PKT_CHAN_MASK) | (((VAL) << DESC_PKT_CHAN_SHIFT) & \ DESC_PKT_CHAN_MASK)) #define HCI1394_GETSY(Q) (((Q) & DESC_PKT_SY_MASK) >> \ DESC_PKT_SY_SHIFT) #define HCI1394_SETSY(PKT, VAL) ((PKT)->q1 = ((PKT)->q1) & \ ~DESC_PKT_SY_MASK) | (((VAL) << DESC_PKT_SY_SHIFT) & DESC_PKT_SY_MASK)) #define HCI1394_GET_ILEN(Q) (((Q) & DESC_DATALEN_MASK) >> \ DESC_DATALEN_SHIFT) #define HCI1394_SET_ILEN(PKT, VAL) ((PKT)->q2 = (((PKT)->q1) & \ ~DESC_PKT_DATALEN_MASK) | (((VAL) << DESC_PKT_DATALEN_SHIFT) & \ DESC_PKT_DATALEN_MASK)) #define HCI1394_IT_SET_HDR_Q1(PKT, SPD, TAG, CH, TC, SY) ((PKT)->q1 = 0 | \ (((SPD) << DESC_PKT_SPD_SHIFT) & DESC_PKT_SPD_MASK) | \ (((TAG) << DESC_PKT_TAG_SHIFT) & DESC_PKT_TAG_MASK) | \ (((CH) << DESC_PKT_CH_SHIFT) & DESC_PKT_CH_MASK) | \ (((TC) << DESC_PKT_TCODE_SHIFT) & DESC_PKT_TCODE_MASK) | \ (((SY) << DESC_PKT_SY_SHIFT) & DESC_PKT_SY_MASK)) /* * OpenHCI Packet format sizes (header only) */ #define DESC_SZ_AR_WRITEQUAD_REQ DESC_FIVE_QUADS #define DESC_SZ_AR_WRITEBLOCK_REQ DESC_FIVE_QUADS /* add data_len */ #define DESC_SZ_AR_WRITE_RESP DESC_FOUR_QUADS #define DESC_SZ_AR_READQUAD_REQ DESC_FOUR_QUADS #define DESC_SZ_AR_READBLOCK_REQ DESC_FIVE_QUADS #define DESC_SZ_AR_READQUAD_RESP DESC_FIVE_QUADS #define DESC_SZ_AR_READ_BLOCK_RESP DESC_FIVE_QUADS /* add data_len */ #define DESC_SZ_AR_PHY DESC_FOUR_QUADS #define DESC_SZ_AR_LOCK_REQ DESC_FIVE_QUADS /* add data_len */ #define DESC_SZ_AR_LOCK_RESP DESC_FIVE_QUADS /* add data_len */ #ifdef __cplusplus } #endif #endif /* _SYS_1394_ADAPTERS_HCI1394_DESCRIPTORS_H */ /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License, Version 1.0 only * (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 (c) 1999-2000 by Sun Microsystems, Inc. * All rights reserved. */ #ifndef _SYS_1394_ADAPTERS_HCI1394_DRVINFO_H #define _SYS_1394_ADAPTERS_HCI1394_DRVINFO_H /* * hci1394_drvinfo.h * drvinfo contains the core information which is shared amoung the various * different parts of the this driver. It should be the file that everyone * else includes. * * This file should not have any dependencies on any other hci1394 header * files. */ #ifdef __cplusplus extern "C" { #endif #include #include #include #include /* State of the HAL driver */ typedef enum { HCI1394_INITIAL, HCI1394_BUS_RESET, HCI1394_NORMAL, HCI1394_SHUTDOWN } hci1394_statevar_t; /* protected state */ typedef struct hci1394_drvstate_s { hci1394_statevar_t ds_state; kmutex_t ds_mutex; } hci1394_drvstate_t; /* Driver Statistics */ typedef struct hci1394_stats_s { uint_t st_bus_reset_count; uint_t st_selfid_count; uint_t st_phy_isr; uint_t st_phy_loop_err; uint_t st_phy_pwrfail_err; uint_t st_phy_timeout_err; uint_t st_phy_portevt_err; } hci1394_stats_t; /* General Driver Information use in all parts of the driver */ typedef struct hci1394_drvinfo_s { dev_info_t *di_dip; void *di_sl_private; int di_instance; uint32_t di_gencnt; hci1394_drvstate_t di_drvstate; hci1394_stats_t di_stats; ddi_iblock_cookie_t di_iblock_cookie; ddi_device_acc_attr_t di_reg_attr; ddi_device_acc_attr_t di_buf_attr; } hci1394_drvinfo_t; _NOTE(SCHEME_PROTECTS_DATA("Single thread modifies", hci1394_drvinfo_s)) #ifdef __cplusplus } #endif #endif /* _SYS_1394_ADAPTERS_HCI1394_DRVINFO_H */ /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License, Version 1.0 only * (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 (c) 1999-2000 by Sun Microsystems, Inc. * All rights reserved. */ #ifndef _SYS_1394_ADAPTERS_HCI1394_EXTERN_H #define _SYS_1394_ADAPTERS_HCI1394_EXTERN_H /* * hci1394_extern.h * Provides common location for extern definitions */ #ifdef __cplusplus extern "C" { #endif #include #include /* see hci1394.c for this externally referenced variable */ extern void *hci1394_statep; /* see hci1394_s1394if.c for this externally referenced variable */ extern h1394_evts_t hci1394_evts; /* * See hci1394_extern.c for a description of these externally referenced * variables */ extern uint32_t hci1394_split_timeout; extern h1394_addr_map_t hci1394_addr_map[]; extern uint_t hci1394_phy_delay_uS; extern uint_t hci1394_phy_stabilization_delay_uS; #ifdef __cplusplus } #endif #endif /* _SYS_1394_ADAPTERS_HCI1394_EXTERN_H */ /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License, Version 1.0 only * (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 (c) 1999-2000 by Sun Microsystems, Inc. * All rights reserved. */ #ifndef _SYS_1394_ADAPTERS_HCI1394_IOCTL_H #define _SYS_1394_ADAPTERS_HCI1394_IOCTL_H /* * hci1394_ioctl.h * Test ioctl's to support test/debug of the 1394 HW. hci1394_ioctl_enum_t is * passed in cmd and a pointer to the appropriate structure (i.e. * hci1394_ioctl_wrreg_t) is passed in arg. */ #ifdef __cplusplus extern "C" { #endif /* * write_reg - write OpenHCI register * read_reg - read OpenHCI register * write_vreg - write OpenHCI Vendor Specific register * read_vreg - read OpenHCI Vendor Specific register * reset_bus - reset the 1394 bus * selfid_cnt - return the number of times we saw the selfid complete * interrupt signifying a bus reset has completed. This does not * have to match the bus generation and probably won't. * busgen_cnt - return the current bus generation * read_selfid - read selfid buffer * write_phy - write PHY register * read_phy - read PHY register * hba_info - HBA vendor information */ #define HCI11394_IOCTL ('f' << 8) typedef enum { HCI1394_IOCTL_WRITE_REG = HCI11394_IOCTL | 0x00, HCI1394_IOCTL_READ_REG = HCI11394_IOCTL | 0x01, HCI1394_IOCTL_WRITE_VREG = HCI11394_IOCTL | 0x02, HCI1394_IOCTL_READ_VREG = HCI11394_IOCTL | 0x03, HCI1394_IOCTL_RESET_BUS = HCI11394_IOCTL | 0x04, HCI1394_IOCTL_SELFID_CNT = HCI11394_IOCTL | 0x05, HCI1394_IOCTL_BUSGEN_CNT = HCI11394_IOCTL | 0x06, HCI1394_IOCTL_READ_SELFID = HCI11394_IOCTL | 0x07, HCI1394_IOCTL_WRITE_PHY = HCI11394_IOCTL | 0x08, HCI1394_IOCTL_READ_PHY = HCI11394_IOCTL | 0x09, HCI1394_IOCTL_HBA_INFO = HCI11394_IOCTL | 0x0A } hci1394_ioctl_enum_t; /* * HCI1394_IOCTL_WRITE_REG * Write OHCI register. addr is an offset into the OpenHCI register map. * (i.e. addr = 0 would write to the Version Register). addr must be 32-bit * aligned (i.e. 0, 4, 8, C, 10). data is the 32-bit word to write into the * OpenHCI register. * * NOTE: Writing OpenHCI registers can cause the hardware and/or SW to * misbehave. Extreme care should be used when using this call. */ typedef struct hci1394_ioctl_wrreg_s { uint_t addr; uint32_t data; } hci1394_ioctl_wrreg_t; /* * HCI1394_IOCTL_READ_REG * Read OHCI register. addr is an offset into the OpenHCI register map. * (i.e. addr = 0 would write to the Version Register). addr must be 32-bit * aligned (i.e. 0, 4, 8, C, 10). When the ioctl returns successfully, data * will contain the 32-bit word read from the OHCI register. */ typedef struct hci1394_ioctl_rdreg_s { uint_t addr; uint32_t data; } hci1394_ioctl_rdreg_t; /* * HCI1394_IOCTL_WRITE_VREG * Write Vendor Specific OHCI register. addr is an offset into the Vendor * Specific OpenHCI register map. (i.e. addr = 0 would write to the first * Vendor Specific register. addr must be 32-bit aligned (i.e. 0, 4, 8, C, * 10). data is the 32-bit word to write into the Vendor Specific OpenHCI * register. regset defines which vendor specific register set to write to. * There will usually be one vendor specific register set so this will * usually be set to 0. * * NOTE: Writing Vendor Specific OpenHCI registers can cause the hardware * and/or SW to misbehave. Extreme care should be used when using this * call. */ typedef struct hci1394_ioctl_wrvreg_s { uint_t regset; uint_t addr; uint32_t data; } hci1394_ioctl_wrvreg_t; /* * HCI1394_IOCTL_READ_VREG * Read Vendor specific OHCI register. addr is an offset into the Vendor * Specific OpenHCI register space. (i.e. addr = 0 is the first Vendor * Specific register). addr must be 32-bit aligned (i.e. 0, 4, 8, C, 10). * When the ioctl returns successfully, data will contain the 32-bit word * read from the Vendor Specific OHCI register. regset defines which vendor * specific register set to read from. There will usually be one vendor * specific register set so this will usually be set to 0. */ typedef struct hci1394_ioctl_rdvreg_s { uint_t regset; uint_t addr; uint32_t data; } hci1394_ioctl_rdvreg_t; /* HCI1394_IOCTL_RESET_BUS has no parameters */ /* * HCI1394_IOCTL_SELFID_CNT * When the ioctl returns successfully, count will contain the number of * times the nexus driver has seen and responded to a selfid_complete * interrupt. This interrupt signifies that the bus reset has completed * and the hardware based bus enumeration has completed. This number will * most likely not be the same as the bus generation. Everytime this * increments, the bus generation count should increment by at least one. * * NOTE: The current implementation of the nexus driver uses a uint_t for * selfid_cnt. */ typedef struct hci1394_ioctl_selfid_cnt_s { uint_t count; } hci1394_ioctl_selfid_cnt_t; /* * HCI1394_IOCTL_BUSGEN_CNT * When the ioctl returns successfully, count will contain the current 1394 * bus generation count. * * NOTE: The current implementation of the nexus driver uses the OpenHCI * generation count which is an 8 bit value. Therefore, this count will * wrap over at 0xFF. */ typedef struct hci1394_ioctl_busgen_cnt_s { uint_t count; } hci1394_ioctl_busgen_cnt_t; /* * HCI1394_IOCTL_READ_SELFID * Copies the contents of the selfid buffer into a buffer pointed to by buf. * Count is the number of 32-bit words to copy into buf. The maximum size * of the selfid buffer is 1024 32-bit words. The very first word is the * OpenHCI selfid header. */ typedef struct hci1394_ioctl_read_selfid_s { uint32_t *buf; uint_t count; } hci1394_ioctl_read_selfid_t; /* * HCI1394_IOCTL_WRPHY * Write PHY register. addr is an offset into the phy register space. * (i.e. addr = 0 is the first phy register). addr is byte aligned * (i.e. 0, 1, 2, 3, 4). data should contain the 8-bit value to write to the * PHY register. The data should be stored as follows <0x000000dd> where dd * is the byte written. * * NOTE: Phy register 0 cannot be read or written. * * NOTE: Writing PHY registers can cause the hardware and/or SW to misbehave. * Extreme care should be used when using this call. */ typedef struct hci1394_ioctl_wrphy_s { uint_t addr; uint_t data; } hci1394_ioctl_wrphy_t; /* * HCI1394_IOCTL_RDPHY * Read PHY register. addr is an offset into the phy register space. * (i.e. addr = 0 is the first phy register). addr is byte aligned * (i.e. 0, 1, 2, 3, 4). When the ioctl returns successfully, data will * contain the 8-bit data read from the PHY register. The data will be stored * as follows <0x000000dd> where dd is the byte read. * * NOTE: Phy register 0 cannot be read or written. */ typedef struct hci1394_ioctl_rdphy_s { uint_t addr; uint_t data; } hci1394_ioctl_rdphy_t; /* * HCI1394_IOCTL_HBA_INFO * HBA Vendor Information * * Vendor Specific Info * pci_vendor_id - VendorID from PCI config space (0x0-0x1) * pci_device_id - DeviceID from PCI config space (0x2-0x3) * pci_revision_id - RevisionID from PCI config space (0x8) * ohci_version - 1394 OpenHCI Version Register (0x0) * ohci_vendor_id - 1394 OpenHCI Vendor ID Register (0x40) * ohci_vregset_cnt - Number of vendor specific register maps that have been * mapped by the driver. The driver will only map in * vendor specific registers for adapters it knows about. */ typedef struct hci1394_ioctl_hbainfo_s { uint_t pci_vendor_id; uint_t pci_device_id; uint_t pci_revision_id; uint32_t ohci_version; uint32_t ohci_vendor_id; uint_t ohci_vregset_cnt; } hci1394_ioctl_hbainfo_t; #ifdef __cplusplus } #endif #endif /* _SYS_1394_ADAPTERS_HCI1394_IOCTL_H */ /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License, Version 1.0 only * (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 2004 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #ifndef _SYS_1394_ADAPTERS_HCI1394_ISOCH_H #define _SYS_1394_ADAPTERS_HCI1394_ISOCH_H /* * hci1394_isoch.h * Function declarations for front-end functions for hci1394 isochronous * support. Also all isochronous related soft_state structures and defs. */ #ifdef __cplusplus extern "C" { #endif #include #include /* handle passed back from init() and used for rest of functions */ typedef struct hci1394_isoch_s *hci1394_isoch_handle_t; /* * Isochronous structures and defs used in the hci1394 soft state. * (see hci1394_state.h). */ /* * control structure for allocated isochronous dma descriptor memory. * when attempting to bind memory, if ddi_addr_bind_handle indicates multiple * cookies, each cookie will be tracked within a separate copy of this * structure. Only the last cookie's idma_desc_mem structure will contain * a valid mem_handle and mem, to be used when freeing all the memory. * * 'used' specifies the number of bytes used for descriptors in this cookie. * 'offset' is this cookie's offset relative to the beginning of the buffer. */ typedef struct hci1394_idma_desc_mem_s { struct hci1394_idma_desc_mem_s *dma_nextp; hci1394_buf_handle_t mem_handle; hci1394_buf_info_t mem; uint32_t used; uint32_t offset; } hci1394_idma_desc_mem_t; _NOTE(SCHEME_PROTECTS_DATA("Single thread modifies", hci1394_idma_desc_mem_s)) /* structure to track one isochronous context */ /* XXX if IR Multichan mode support is added, this must be modified */ typedef struct hci1394_iso_ctxt_s { int ctxt_index; /* 0-31 -- which context this is */ int ctxt_io_mode; /* xmit, recv pkt or buf, hdrs, multi */ uint32_t ctxt_flags; /* general context info */ volatile uint32_t intr_flags; /* flags while context is running */ kmutex_t intrprocmutex; /* interrupt/update coordination */ kcondvar_t intr_cv; /* interrupt completion cv */ uint16_t isospd; /* speed of packets for context */ uint16_t isochan; /* isochronous channel for contxt */ hci1394_ctxt_regs_t *ctxt_regsp; /* ctxt regs within hci1394_regs_t */ void *xcs_firstp; /* first alloc xfer_ctl_t struct */ hci1394_idma_desc_mem_t *dma_firstp; /* 1st alloc dma descriptor mem */ uint32_t dma_mem_execp; /* exec start(bound mem w/Z bits) */ uint32_t reserved; ixl1394_command_t *ixl_firstp; /* 1st ixl cmmand in linked list */ ixl1394_command_t *ixl_execp; /* currently executing ixl cmmand */ uint_t ixl_exec_depth; /* curr exec ixl cmd xfer_ctl idx */ uint_t max_dma_skips; /* max skips allowed before xmit */ /* recovery required (16 => 2ms) */ uint_t max_noadv_intrs; /* max intrs with no dma descriptor */ /* block advances (8) */ uint_t rem_noadv_intrs; /* remaining intrs allowed with no */ /* dma advances (i.e. no status set) */ uint16_t dma_last_time; /* last completd desc blk tmestmp */ uint16_t default_tag; /* default tag value */ uint16_t default_sync; /* default sync value */ uint16_t default_skipmode; /* default skip mode */ ixl1394_command_t *default_skiplabelp; /* set if needed */ ixl1394_command_t *default_skipxferp; /* xfercmd for default skiplabl */ void *global_callback_arg; /* provided to IXLcallbacks */ opaque_t idma_evt_arg; /* provided to "stopped" callback */ /* target callback if dma stops */ void (*isoch_dma_stopped)(struct isoch_dma_handle *idma_hdl, opaque_t idma_evt_arg, id1394_isoch_dma_stopped_t idma_stop_args); } hci1394_iso_ctxt_t; _NOTE(SCHEME_PROTECTS_DATA("Single thread modifies", hci1394_iso_ctxt_s)) /* * defs for hci1394_iso_ctxt_t.ctxt_io_mode. * overall io characteristics of the contexts, initialized during isoch init * and never changed. */ /* * defs for hci1394_iso_ctxt_t.ctxt_flags * These flags are protected by the context list mutex in the isoch handle * (see hci1394_isoch.c for mutex definition) */ #define HCI1394_ISO_CTXT_INUSE 0x00000001 /* context is in use */ #define HCI1394_ISO_CTXT_RUNNING 0x00000002 /* context is running */ #define HCI1394_ISO_CTXT_RECV 0x00000004 /* isoch receive context */ #define HCI1394_ISO_CTXT_CMDREG 0x00000008 /* dev has readable dma cmdptr */ #define HCI1394_ISO_CTXT_BFFILL 0x00000010 /* on=BufFill off=Pkt IR only */ #define HCI1394_ISO_CTXT_RHDRS 0x00000020 /* recv packet hdrs into mem */ #define HCI1394_ISO_CTXT_MULTI 0x00000040 /* in multichan mode - IR only */ /* * defs for hci1394_iso_ctxt_t.intr_flags * These flags are protected by the per-context mutex "intrprocmutex" */ #define HCI1394_ISO_CTXT_STOP 0x00000010 /* context stopped */ #define HCI1394_ISO_CTXT_INTRSET 0x00000020 /* intr flagged, not processed */ #define HCI1394_ISO_CTXT_ININTR 0x00000040 /* in intrproc, not due to int */ #define HCI1394_ISO_CTXT_INUPDATE 0x00000080 /* in intrproc, not due to int */ #define HCI1394_ISO_CTXT_INCALL 0x00000100 /* intrproc is doing callback */ /* * structure used to do accounting for interrupt usage. Specifically, * used to determine when CYCLE_LOST or CYCLE_INCONSISTENT storms * should cause us to disable those interrupts. */ typedef struct hci1394_intr_thresh_s { hrtime_t last_intr_time; hrtime_t delta_t_thresh; int delta_t_counter; int counter_thresh; } hci1394_intr_thresh_t; /* defs for the hci1394_intr_thresh_t struct */ #define HCI1394_CYC_LOST_DELTA 400000; /* 400ms */ #define HCI1394_CYC_LOST_COUNT 25; #define HCI1394_CYC_INCON_DELTA 400000; /* 400ms */ #define HCI1394_CYC_INCON_COUNT 25; /* * Structure used for tracking all transmit and receive isochronous contexts * Also contains the information necessary for tracking CYCLE_LOST and * CYCLE_INCONSISTENT interrupt usage. * The ctxt_list mutex protects the in-use status of the contexts while * searching for a free isoch context to use in hci1394_alloc_isoch_dma(), * during interrupt processing, and during free_isoch_dma processing. * An openHCI 1.0 hardware implementation may support up to 32 separate DMA * engines each for transmit and receive, referred to as "contexts". * The number of supported contexts is determined during ohci board * initialization, and can be different for transmit vs. receive. */ typedef struct hci1394_isoch_s { hci1394_intr_thresh_t cycle_lost_thresh; hci1394_intr_thresh_t cycle_incon_thresh; int isoch_dma_alloc_cnt; int unused; int ctxt_xmit_count; int ctxt_recv_count; hci1394_iso_ctxt_t ctxt_xmit[HCI1394_MAX_ISOCH_CONTEXTS]; hci1394_iso_ctxt_t ctxt_recv[HCI1394_MAX_ISOCH_CONTEXTS]; kmutex_t ctxt_list_mutex; } hci1394_isoch_t; void hci1394_isoch_init(hci1394_drvinfo_t *drvinfo, hci1394_ohci_handle_t ohci, hci1394_isoch_handle_t *isoch_hdl); void hci1394_isoch_fini(hci1394_isoch_handle_t *isoch_hdl); void hci1394_isoch_cycle_inconsistent(hci1394_state_t *soft_statep); void hci1394_isoch_cycle_lost(hci1394_state_t *soft_statep); int hci1394_isoch_resume(hci1394_state_t *soft_statep); void hci1394_isoch_error_ints_enable(hci1394_state_t *soft_statep); int hci1394_isoch_recv_count_get(hci1394_isoch_handle_t isoch_hdl); hci1394_iso_ctxt_t *hci1394_isoch_recv_ctxt_get(hci1394_isoch_handle_t isoch_hdl, int num); int hci1394_isoch_xmit_count_get(hci1394_isoch_handle_t isoch_hdl); hci1394_iso_ctxt_t *hci1394_isoch_xmit_ctxt_get(hci1394_isoch_handle_t isoch_hdl, int num); int hci1394_alloc_isoch_dma(void *hal_private, id1394_isoch_dmainfo_t *idi, void **hal_idma_handle, int *resultp); void hci1394_free_isoch_dma(void *hal_private, void *hal_isoch_dma_handle); int hci1394_start_isoch_dma(void *hal_private, void *hal_isoch_dma_handle, id1394_isoch_dma_ctrlinfo_t *idma_ctrlinfo, uint_t flags, int *resultp); int hci1394_update_isoch_dma(void *hal_private, void *hal_isoch_dma_handle, id1394_isoch_dma_updateinfo_t *idma_updateinfop, uint_t flags, int *resultp); void hci1394_stop_isoch_dma(void *hal_private, void *hal_isoch_dma_handle, int *resultp); void hci1394_do_stop(hci1394_state_t *soft_statep, hci1394_iso_ctxt_t *ctxtp, boolean_t do_callback, id1394_isoch_dma_stopped_t stop_args); #ifdef __cplusplus } #endif #endif /* _SYS_1394_ADAPTERS_HCI1394_ISOCH_H */ /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License, Version 1.0 only * (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 1999-2002 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #ifndef _SYS_1394_ADAPTERS_HCI1394_IXL_H #define _SYS_1394_ADAPTERS_HCI1394_IXL_H /* * hci1394_ixl.h * Structures and defines for IXL processing. * 1. Structures tracking per-command state [created during compilation * and stored in each command's compiler_privatep]. * 2. Structures used for state tracking during IXL program compilation. * 3. Structures used during IXL dynamic update for assessment and the * performing the update itself. */ #ifdef __cplusplus extern "C" { #endif #include #include #include /* * function return codes from hci1394_ixl_dma_sync() */ #define HCI1394_IXL_INTR_NOERROR (0) /* no error */ #define HCI1394_IXL_INTR_INUPDATE (1) /* update active at intr entry */ /* (info only, not err) */ #define HCI1394_IXL_INTR_DMASTOP (2) /* encountered end of dma or stopped */ /* (might be info only) */ #define HCI1394_IXL_INTR_DMALOST (-1) /* dma location indeterminate (lost) */ #define HCI1394_IXL_INTR_NOADV (-2) /* dma non-advance retries exhausted */ /* (stuck or lost) */ /* fatal internal errors from hci1394_ixl_dma_sync() */ #define HCI1394_IXL_INTR_ININTR (-3) /* interrupt active at intrrupt entry */ #define HCI1394_IXL_INTR_INCALL (-4) /* callback active at entry */ #define HCI1394_IXL_INTR_STOP (-5) /* context is being stopped */ /* * maximum number of jump IXL commands permitted between two data transfer * commands. This allows for several label and jump combinations to exist, but * also is used to detect when the label/jump complexity probably indicates * an infinite loop without any transfers. */ #define HCI1394_IXL_MAX_SEQ_JUMPS 10 /* * xfer control structures - for execution and update control of compiled * ixl program. * * For pkt, buf and special xfer start ixl commands, address * of allocated xfer_ctl struct is set into ixl compiler_privatep. * * For pkt xfer non-start ixl commands, address of pkt xfer start ixl * command is set into compiler_privatep and the index [1-n] of * this non-start pkt xfer ixl command to its related component in the * generated descriptor block is set into compiler_resv. * * The xfer_ctl_dma struct array is needed because allocation of subsequent * descriptor blocks may be from different memory pages (i.e. not contiguous) * and thus, during update processing, subsequent descriptor block addrs * can't be calculated (e.g. change of buf addr or size or modification to * set tag&sync, setskipmode or jump cmds). */ #define XCTL_LABELLED 1 /* flag: ixl xfer cmd initiated by ixl label cmd */ typedef struct hci1394_xfer_ctl_dma { /* * dma descriptor block's bound addr (with "Z" bits set); is used to * fill jump/skip addrs of previous dma descriptor block (previous on * exec path, not link path); Note:("Z" bits)*16 is size of this * descriptor block; individual component's format depends on IXL cmd * type; */ uint32_t dma_bound; /* * kernel virtual (unbound) addr of last component of allocated * descriptor block; start addr of descriptor block can be calculated * by adding size of a descriptor block component(16) and subtracting * ("Z" bits)*16; Note: if ixl cmd is xmit_hdr_only, must add 2*desc * block component(32), instead; * used to determine current location during exec by examining/clearing * the status/timestamp value; * used to obtain value for store timestamp cmd; used to set new * jump/skip addr on update calls; * used to set new tag and sync on update calls; */ caddr_t dma_descp; /* * pointer to the hci1394_buf_info_t structure corresponding to the * mapped DMA memory into which this descriptor was written. Contains * the DMA handles necessary for ddi_dma_sync() and ddi_put32/get32() * calls. */ hci1394_buf_info_t *dma_buf; } hci1394_xfer_ctl_dma_t; typedef struct hci1394_xfer_ctl { struct hci1394_xfer_ctl *ctl_nextp; /* next ixl xfer_ctl struct */ ixl1394_command_t *execp; /* next ixlxfer cmd (along exec path) */ ixl1394_set_skipmode_t *skipmodep; /* associated skip cmd. if any */ uint16_t ctl_flags; /* xctl flags defined above */ uint16_t cnt; /* dma descriptor blocks alloc count */ /* (for pkt=1) */ hci1394_xfer_ctl_dma_t dma[1]; /* addrs of descriptor blocks, cnt of */ /* these are allocated */ } hci1394_xfer_ctl_t; _NOTE(SCHEME_PROTECTS_DATA("Single thread modifies", hci1394_xfer_ctl)) /* * IXL Compiler temporary working variables for building IXL context program. * (i.e. converting IXL program to a list of hci descriptor blocks) */ typedef struct hci1394_comp_ixl_vars_s { /* COMMON RECV/XMIT COMPILE VALUES */ hci1394_state_t *soft_statep; /* driver state */ hci1394_iso_ctxt_t *ctxtp; /* current context */ hci1394_xfer_ctl_t *xcs_firstp; /* 1st alloc xfer_ctl_t struc */ hci1394_xfer_ctl_t *xcs_currentp; /* last alloc xfer_ctl_t struc */ hci1394_idma_desc_mem_t *dma_firstp; /* 1st alloc descriptor mem */ hci1394_idma_desc_mem_t *dma_currentp; /* cur dma descriptor mem */ int dma_bld_error; /* compilation error code */ uint_t ixl_io_mode; /* I/O mode: 0=recv,1=xmit */ ixl1394_command_t *ixl_cur_cmdp; /* processing current ixl cmd */ ixl1394_command_t *ixl_cur_xfer_stp; /* currently buildng xfer cmd */ ixl1394_command_t *ixl_cur_labelp; /* set if xfer inited by labl */ uint16_t ixl_xfer_st_cnt; /* # of xfer start ixl cmds built */ uint_t xfer_state; /* none, pkt, buf, skip, hdronly */ uint_t xfer_hci_flush; /* updateable - xfer, jump, set */ uint32_t xfer_pktlen; uint32_t xfer_bufp[HCI1394_DESC_MAX_Z]; uint16_t xfer_bufcnt; uint16_t xfer_size[HCI1394_DESC_MAX_Z]; uint16_t descriptors; uint16_t reserved; hci1394_desc_t descriptor_block[HCI1394_DESC_MAX_Z]; /* START RECV ONLY SECTION */ uint16_t ixl_setsyncwait_cnt; /* END RECV ONLY SECTION */ /* START XMIT ONLY SECTION */ ixl1394_set_tagsync_t *ixl_settagsync_cmdp; ixl1394_set_skipmode_t *ixl_setskipmode_cmdp; uint16_t default_tag; uint16_t default_sync; uint16_t default_skipmode; /* next, self, stop, jump */ uint16_t skipmode; /* next, self, stop, jump */ ixl1394_command_t *default_skiplabelp; ixl1394_command_t *default_skipxferp; ixl1394_command_t *skiplabelp; ixl1394_command_t *skipxferp; uint32_t xmit_pkthdr1; uint32_t xmit_pkthdr2; uint32_t storevalue_bufp; uint32_t storevalue_data; /* END XMIT ONLY SECTION */ } hci1394_comp_ixl_vars_t; _NOTE(SCHEME_PROTECTS_DATA("Single thread modifies", hci1394_comp_ixl_vars_s)) /* * hci1394_comp_ixl_vars.xfer_hci_flush - xfer descriptor block build hci * flush evaluation flags */ #define UPDATEABLE_XFER 0x01 /* current xfer command is updateable */ #define UPDATEABLE_JUMP 0x02 /* cur xfer is finalized by updateable jump */ #define UPDATEABLE_SET 0x04 /* current xfer has associated updateable set */ #define INITIATING_LBL 0x08 /* current xfer is initiated by a label cmd */ /* hci1394_comp_ixl_vars.xfer_state - xfer descriptr block build state values */ #define XFER_NONE 0 /* build inactive */ #define XFER_PKT 1 /* building xfer packet descriptor block */ #define XFER_BUF 2 /* building xfer buffer descriptor blocks */ #define XMIT_NOPKT 3 /* building skip cycle xmit descriptor block */ #define XMIT_HDRONLY 4 /* building header only xmit descriptor block */ /* * IXL Dynamic Update temporary working variables. * (used when assessing feasibility of an update based on where the hardware * is, and for performing the actual update.) */ #define IXL_MAX_LOCN 4 /* extent of location array */ typedef struct hci1394_upd_locn_info { ixl1394_command_t *ixlp; uint_t ixldepth; } hci1394_upd_locn_info_t; typedef struct hci1394_ixl_update_vars { hci1394_state_t *soft_statep; /* driver state struct */ hci1394_iso_ctxt_t *ctxtp; /* current iso context */ ixl1394_command_t *ixlnewp; /* ixl cmd containing new values */ ixl1394_command_t *ixloldp; /* cmd to be updated with new vals */ ixl1394_command_t *ixlxferp; /* xfer cmd which is real targ of upd */ ixl1394_command_t *skipxferp; /* xfer cmd if mode is skip to label */ /* currently exec xfer and MAX_LOCN-1 xfers following */ hci1394_upd_locn_info_t locn_info[IXL_MAX_LOCN]; uint_t ixldepth; /* xferp depth at which to start upd */ uint_t skipmode; /* set skip mode mode value */ uint_t pkthdr1; /* new pkt header 1 if tag or sync update */ uint_t pkthdr2; /* new pkt hdr 2 if send xfer size change */ uint32_t skipaddr; /* bound skip destaddr (0=not skip to labl) */ uint32_t jumpaddr; /* bound jump destaddr if jump update (w/Z) */ uint32_t bufaddr; /* new buf addr if xfer buffr addr change */ uint32_t bufsize; /* new buf size if xfer buffr size change */ uint32_t hcihdr; /* new hci descriptor hdr field (cmd,int,cnt) */ uint32_t hcistatus; /* new hci descrptr stat field (rescount) */ int32_t hci_offset; /* offset from xfer_ctl dma_descp to */ /* hci changing */ int hdr_offset; /* offset from xfer_ctl dma_descp to */ /* pkthdrs hci */ int upd_status; /* update completion return status value */ uint_t risklevel; /* caller risk override spec (unimplemented) */ uint16_t ixl_opcode; /* ixl update command code */ uint16_t ixlcount; /* ixlxferp # of dma cmds to update */ } hci1394_ixl_update_vars_t; _NOTE(SCHEME_PROTECTS_DATA("Single thread modifies", hci1394_ixl_update_vars)) int hci1394_compile_ixl(hci1394_state_t *soft_statep, hci1394_iso_ctxt_t *ctxtp, ixl1394_command_t *ixlp, int *resultp); int hci1394_ixl_update(hci1394_state_t *soft_statep, hci1394_iso_ctxt_t *ctxtp, ixl1394_command_t *ixlnewp, ixl1394_command_t *ixloldp, uint_t riskoverride, int *resultp); void hci1394_ixl_interrupt(hci1394_state_t *soft_statep, hci1394_iso_ctxt_t *ctxtp, boolean_t in_stop); int hci1394_ixl_dma_sync(hci1394_state_t *soft_statep, hci1394_iso_ctxt_t *ctxtp); int hci1394_ixl_set_start(hci1394_iso_ctxt_t *ctxtp, ixl1394_command_t *ixlstp); void hci1394_ixl_reset_status(hci1394_iso_ctxt_t *ctxtp); int hci1394_ixl_check_status(hci1394_xfer_ctl_dma_t *dma, uint16_t ixlopcode, uint16_t *timestamp, boolean_t do_status_reset); int hci1394_ixl_find_next_exec_xfer(ixl1394_command_t *ixl_start, uint_t *callback_cnt, ixl1394_command_t **next_exec_ixlpp); void hci1394_ixl_cleanup(hci1394_state_t *soft_statep, hci1394_iso_ctxt_t *ctxtp); #ifdef __cplusplus } #endif #endif /* _SYS_1394_ADAPTERS_HCI1394_IXL_H */ /* * 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 _SYS_1394_ADAPTERS_HCI1394_OHCI_H #define _SYS_1394_ADAPTERS_HCI1394_OHCI_H /* * hci1394_ohci.h * Provides access macros and routines to the OpenHCI HW. */ #ifdef __cplusplus extern "C" { #endif #include #include #include #include #include #include #include #define OHCI_MAX_SELFID_SIZE 2048 #define OHCI_BUSGEN_MAX 0xFF /* Misc */ #define OHCI_REG_SET 1 /* ddi_regs_map_setup */ #define OHCI_CHIP_RESET_TIME_IN_uSEC ((clock_t)100) /* 100uS */ #define OHCI_BUS_RESET_TIME_IN_uSEC ((clock_t)100000) /* 100mS */ #define OHCI_MAX_COOKIE 16 #define OHCI_uS_PER_BUS_CYCLE 125 #define OHCI_nS_PER_BUS_CYCLE 125000 #define OHCI_BUS_CYCLE_TO_uS(cycles) (cycles * OHCI_uS_PER_BUS_CYCLE) #define OHCI_BUS_CYCLE_TO_nS(cycles) (cycles * OHCI_nS_PER_BUS_CYCLE) #define OHCI_CYCLE_SEC_SHIFT 13 #define OHCI_CYCLE_SEC_MASK 0xE000 #define OHCI_CYCLE_CNT_MASK 0x1FFF #define OHCI_MAX_CYCLE_CNT 8000 #define OHCI_TIMESTAMP_MASK 0xFFFF #define OHCI_REG_ADDR_MASK 0x7FC /* OpenHCI Global Swap location in PCI space */ #define OHCI_PCI_HCI_CONTROL_REG ((off_t)0x40) #define OHCI_PCI_GLOBAL_SWAP 0x00000001 /* PHY Register #1 */ #define OHCI_PHY_RHB 0x80 #define OHCI_PHY_IBR 0x40 #define OHCI_PHY_MAX_GAP 0x3F /* PHY Register #4 */ #define OHCI_PHY_EXTND_MASK 0xE0 #define OHCI_PHY_EXTND 0xE0 /* PHY Register #4 */ #define OHCI_PHY_CNTDR 0x40 /* PHY Register #5 */ #define OHCI_PHY_ISBR 0x40 #define OHCI_PHY_LOOP_ERR 0x20 #define OHCI_PHY_PWRFAIL_ERR 0x10 #define OHCI_PHY_TIMEOUT_ERR 0x08 #define OHCI_PHY_PORTEVT_ERR 0x04 #define OHCI_PHY_ENBL_ACCEL 0x02 #define OHCI_PHY_ENBL_MULTI 0x01 /* OpenHCI Event Codes. Refer to OHCI 1.0 section 3.1.1 */ #define OHCI_EVT_NO_STATUS 0x0 #define OHCI_EVT_LONG_PACKET 0x2 #define OHCI_EVT_MISSING_ACK 0x3 #define OHCI_EVT_UNDERRUN 0x4 #define OHCI_EVT_OVERRUN 0x5 #define OHCI_EVT_DESCRIPTOR_READ 0x6 #define OHCI_EVT_DATA_READ 0x7 #define OHCI_EVT_DATA_WRITE 0x8 #define OHCI_EVT_BUS_RESET 0x9 #define OHCI_EVT_TIMEOUT 0xA #define OHCI_EVT_TCODE_ERR 0xB #define OHCI_EVT_UNKNOWN 0xE #define OHCI_EVT_FLUSHED 0xF #define OHCI_ACK_COMPLETE 0x11 #define OHCI_ACK_PENDING 0x12 #define OHCI_ACK_BUSY_X 0x14 #define OHCI_ACK_BUSY_A 0x15 #define OHCI_ACK_BUSY_B 0x16 #define OHCI_ACK_TARDY 0x1B #define OHCI_ACK_CONFLICT_ERROR 0x1C #define OHCI_ACK_DATA_ERROR 0x1D #define OHCI_ACK_TYPE_ERROR 0x1E #define OHCI_ACK_ADDRESS_ERROR 0x1F #define OHCI_REG_NODEID_ROOT 0x40000000 #define OHCI_REG_BUSOPTIONS_CMC 0x40000000 /* hci_regs_s.ir_ctxt_regs.ctxt_match */ #define OHCI_MTC_TAG3_MASK 0x80000000 #define OHCI_MTC_TAG3_SHIFT 31 #define OHCI_MTC_TAG2_MASK 0x40000000 #define OHCI_MTC_TAG2_SHIFT 30 #define OHCI_MTC_TAG1_MASK 0x20000000 #define OHCI_MTC_TAG1_SHIFT 29 #define OHCI_MTC_TAG0_MASK 0x10000000 #define OHCI_MTC_TAG0_SHIFT 28 #define OHCI_MTC_MATCH_MASK 0x07FFF000 #define OHCI_MTC_MATCH_SHIFT 12 #define OHCI_MTC_SYNC_MASK 0x00000F00 #define OHCI_MTC_SYNC_SHIFT 8 #define OHCI_MTC_TAG1SY_MASK 0x00000040 #define OHCI_MTC_TAG1SY_SHIFT 6 #define OHCI_MTC_CHAN_MASK 0x0000003F #define OHCI_MTC_CHAN_SHIFT 0 /* hci_regs_s.self_id_buflo - See OpenHCI 1.00 section 11.1 */ #define OHCI_SLF_BUF_LO 0xFFFFF800 /* hci_regs_s.self_id_count - See OpenHCI 1.00 section 11.2 */ #define OHCI_SLFC_ERROR 0x80000000 #define OHCI_SLFC_GEN_MASK 0x00FF0000 #define OHCI_SLFC_GEN_SHIFT 16 #define OHCI_SLFC_NUM_QUADS_MASK 0x00001FFC /* * hci_regs_s.int_event_* and hci_regs_s.int_mask_* * See OpenHCI 1.00 section 6 */ #define OHCI_INTR_REQ_TX_CMPLT 0x00000001 #define OHCI_INTR_RESP_TX_CMPLT 0x00000002 #define OHCI_INTR_ARRQ 0x00000004 #define OHCI_INTR_ARRS 0x00000008 #define OHCI_INTR_RQPKT 0x00000010 #define OHCI_INTR_RSPKT 0x00000020 #define OHCI_INTR_ISOCH_TX 0x00000040 /* RO */ #define OHCI_INTR_ISOCH_RX 0x00000080 /* RO */ #define OHCI_INTR_POST_WR_ERR 0x00000100 #define OHCI_INTR_LOCK_RESP_ERR 0x00000200 #define OHCI_INTR_SELFID_CMPLT 0x00010000 #define OHCI_INTR_BUS_RESET 0x00020000 #define OHCI_INTR_PHY 0x00080000 #define OHCI_INTR_CYC_SYNCH 0x00100000 #define OHCI_INTR_CYC_64_SECS 0x00200000 #define OHCI_INTR_CYC_LOST 0x00400000 #define OHCI_INTR_CYC_INCONSISTENT 0x00800000 #define OHCI_INTR_UNRECOVERABLE_ERR 0x01000000 #define OHCI_INTR_CYC_TOO_LONG 0x02000000 #define OHCI_INTR_PHY_REG_RCVD 0x04000000 #define OHCI_INTR_VENDOR_SPECIFIC 0x40000000 #define OHCI_INTR_MASTER_INTR_ENBL 0x80000000 /* int_mask_* only */ /* hci_regs_s.fairness_ctrl - See OpenHCI 1.00 section 5.8 */ #define OHCI_FAIR_PRI_REQ 0x000000FF /* hci_regs_s.link_ctrl_set/clr - See OpenHCI 1.00 section 5.9 */ #define OHCI_LC_CYC_SRC 0x00400000 #define OHCI_LC_CYC_MAST 0x00200000 #define OHCI_LC_CTIME_ENBL 0x00100000 #define OHCI_LC_RCV_PHY 0x00000400 #define OHCI_LC_RCV_SELF 0x00000200 #define OHCI_LC_CYC_SYNC 0x00000010 /* Defines for registers in HCI register space */ /* Note: bits are read/write unless otherwise noted (RO-read only) */ /* hci_regs_s.version - See OpenHCI 1.00 section 5.2 */ #define OHCI_VER_GUID_ROM 0x01000000 #define OHCI_VER_VERSION_MASK 0x00FF0000 #define OHCI_VER_VERSION_SHIFT 16 #define OHCI_VER_REVISION_MASK 0x000000FF #define OHCI_VERSION(version) \ ((version & OHCI_VER_VERSION_MASK) >> OHCI_VER_VERSION_SHIFT) #define OHCI_REVISION(revision) \ (revision & OHCI_VER_REVISION_MASK) /* hci_regs_s.guid_rom - See OpenHCI 1.00 section 5.3 */ #define OHCI_GROM_ADDR_RESET 0x80000000 /* 1-initiate reset */ #define OHCI_GROM_RD_START 0x02000000 /* 1-start byte read */ #define OHCI_GROM_RD_DATA 0x00FF0000 /* RO */ /* hci_regs_s.at_retries - See OpenHCI 1.00 section 5.4 */ #define OHCI_RET_SECLIM_MASK 0xE0000000 /* dual-phase retry */ #define OHCI_RET_SECLIM_SHIFT 29 #define OHCI_RET_CYCLLIM_MASK 0xFFFF0000 /* dual-phase retry */ #define OHCI_RET_CYCLLIM_SHIFT 16 #define OHCI_RET_MAX_PHYS_RESP_MASK 0x00000F00 /* physical resp rtry */ #define OHCI_RET_MAX_PHYS_RESP_SHIFT 8 #define OHCI_RET_MAX_ATRESP_MASK 0x000000F0 /* AT response retry */ #define OHCI_RET_MAX_ATRESP_SHIFT 4 #define OHCI_RET_MAX_ATREQ_MASK 0x0000000F /* AT request retry */ #define OHCI_RET_MAX_ATREQ_SHIFT 0 /* hci_regs_s.csr_ctrl - See OpenHCI 1.00 section 5.5.1 */ #define OHCI_CSR_DONE 0x80000000 /* RO 1-cmp_swap complete */ #define OHCI_CSR_SELECT 0x00000003 #define OHCI_CSR_SEL_BUS_MGR_ID 0 /* bus manager ID register */ #define OHCI_CSR_SEL_BANDWIDTH_AVAIL 1 /* bandwidth available reg */ #define OHCI_CSR_SEL_CHANS_AVAIL_HI 2 /* channels_available_hi reg */ #define OHCI_CSR_SEL_CHANS_AVAIL_LO 3 /* channels_available_lo reg */ /* hci_regs_s.config_rom_hdr - See OpenHCI 1.00 section 5.5.6 */ #define OHCI_CROM_INFO_LEN 0xFF000000 #define OHCI_CROM_CRC_LEN 0x00FF0000 #define OHCI_CROM_ROM_CRC_VAL 0x0000FFFF /* hci_regs_s.bus_options - See OpenHCI 1.00 section 5.5.4 */ #define OHCI_BOPT_IRMC 0x80000000 /* Isoch resrce mgr capable */ #define OHCI_BOPT_CMC 0x40000000 /* cycle master capable */ #define OHCI_BOPT_ISC 0x20000000 /* isochronous data capable */ #define OHCI_BOPT_BMC 0x10000000 /* bus manager capable */ #define OHCI_BOPT_PMC 0x80000000 /* power manager capable */ #define OHCI_BOPT_CYC_CLK_ACC 0x00FF0000 #define OHCI_BOPT_MAX_REC 0x0000F000 #define OHCI_BOPT_GEN 0x000000C0 #define OHCI_BOPT_LINK_SPD 0x00000007 /* hci_regs_s.guid_hi - See OpenHCI 1.00 section 5.5.5 */ #define OHCI_GUID_NODE_VENDOR_ID 0xFFFFFF00 #define OHCI_GUID_CHIP_ID_HI 0x000000FF /* hci_regs_s.config_rom_maplo - See OpenHCI 1.00 section 5.5.6 */ #define OHCI_CMAP_ADDR 0xFFFFFF00 /* 1k aligned */ /* hci_regs_s.posted_write_addrhi - See OpenHCI 1.00 section 13.2.8.1 */ #define OHCI_POST_SOURCE_ID 0xFFFF0000 #define OHCI_POST_OFFSET_HI 0x0000FFFF /* hci_regs_s.vendor_id - See OpenHCI 1.00 section 5.2 */ #define OHCI_VEND_ID 0x00FFFFFF #define OHCI_VEND_UNIQUE 0xFF000000 /* hci_regs_s.hc_ctrl_set/clr - See OpenHCI 1.00 section 5.7 */ #define OHCI_HC_NO_BSWAP 0x40000000 /* 1-big endian,0-little end */ #define OHCI_HC_PROG_PHY_ENBL 0x00800000 /* 1-prog phy capabilities */ #define OHCI_HC_APHY_ENBL 0x00040000 /* 1-Aphy enhancements enbld */ #define OHCI_HC_LPS 0x00080000 /* 1-link pwr on, 0-off */ #define OHCI_HC_POSTWR_ENBL 0x00040000 /* 1-enabled, 0-disabled */ #define OHCI_HC_LINK_ENBL 0x00020000 /* 1-enabled, 0-disabled */ #define OHCI_HC_SOFT_RESET 0x00010000 /* 1-reset in prog, 0-done */ /* hci_regs_s.node_id - See OpenHCI 1.00 section 5.10 */ #define OHCI_NDID_IDVALID 0x80000000 #define OHCI_NDID_ROOT_MASK 0x40000000 #define OHCI_NDID_ROOT_SHIFT 30 #define OHCI_NDID_CPS_MASK 0x08000000 #define OHCI_NDID_CPS_SHIFT 27 #define OHCI_NDID_BUSNUM_MASK 0x0000FFC0 #define OHCI_NDID_BUSNUM_SHIFT 6 #define OHCI_NDID_NODENUM_MASK 0x0000003F #define OHCI_NDID_NODENUM_SHIFT 0 /* hci_regs_s.phy_ctrl - See OpenHCI 1.00 section 5.11, 1394-1994 J.4.1 */ #define OHCI_PHYC_RDDONE 0x80000000 #define OHCI_PHYC_RDREG 0x00008000 #define OHCI_PHYC_WRREG 0x00004000 #define OHCI_PHYC_RDADDR_MASK 0x0F000000 #define OHCI_PHYC_RDADDR_SHIFT 24 #define OHCI_PHYC_RDDATA_MASK 0x00FF0000 #define OHCI_PHYC_RDDATA_SHIFT 16 #define OHCI_PHYC_REGADDR_MASK 0x00000F00 #define OHCI_PHYC_REGADDR_SHIFT 8 #define OHCI_PHYC_WRDATA_MASK 0x000000FF #define OHCI_PHYC_WRDATA_SHIFT 0 /* hci_regs_s.context_ctrl -- several contexts */ #define OHCI_CC_RUN_MASK 0x00008000 #define OHCI_CC_RUN_SHIFT 15 #define OHCI_CC_WAKE_MASK 0x00001000 #define OHCI_CC_WAKE_SHIFT 12 #define OHCI_CC_DEAD_MASK 0x00000800 #define OHCI_CC_DEAD_SHIFT 11 #define OHCI_CC_ACTIVE_MASK 0x00000400 #define OHCI_CC_ACTIVE_SHIFT 10 #define OHCI_CC_SPD_MASK 0x000000E0 #define OHCI_CC_SPD_SHIFT 5 #define OHCI_CC_EVT_MASK 0x0000001F #define OHCI_CC_EVT_SHIFT 0 /* hci_regs context_ctrl for IR */ #define OHCI_IRCTL_BFILL_MASK 0x80000000 #define OHCI_IRCTL_BFILL_SHIFT 31 #define OHCI_IRCTL_IHDR_MASK 0x40000000 #define OHCI_IRCTL_IHDR_SHIFT 30 #define OHCI_IRCTL_MTC_ENBL_MASK 0x20000000 #define OHCI_IRCTL_MTC_ENBL_SHIFT 29 #define OHCI_IRCTL_MULTI_MASK 0x10000000 #define OHCI_IRCTL_MULTI_SHIFT 28 /* hci_regs context_ctrl for IT */ #define OHCI_ITCTL_MTC_ENBL_MASK 0x80000000 #define OHCI_ITCTL_MTC_ENBL_SHIFT 31 #define OHCI_ITCTL_MATCH_MASK 0x7FFF0000 #define OHCI_ITCTL_MATCH_SHIFT 16 #define HCI1394_IS_ARRESP(tcode) \ ((tcode == IEEE1394_TCODE_WRITE_RESP) || \ (tcode == IEEE1394_TCODE_READ_QUADLET_RESP) || \ (tcode == IEEE1394_TCODE_READ_BLOCK_RESP) || \ (tcode == IEEE1394_TCODE_LOCK_RESP)) #define HCI1394_IS_ARREQ(tcode) \ ((tcode == IEEE1394_TCODE_READ_QUADLET) || \ (tcode == IEEE1394_TCODE_WRITE_QUADLET) || \ (tcode == IEEE1394_TCODE_READ_BLOCK) || \ (tcode == IEEE1394_TCODE_WRITE_BLOCK) || \ (tcode == IEEE1394_TCODE_LOCK) || \ (tcode == IEEE1394_TCODE_PHY)) #define HCI1394_IRCTXT_CTRL_SET(HCIP, I, BFFILL, IHDR, MATCHENBL, MULTI, RUN, \ WAKE) (ddi_put32((HCIP)->ohci->ohci_reg_handle, \ &(HCIP)->ohci->ohci_regs->ir[(I)].ctxt_ctrl_set, \ 0 | (((BFFILL) << OHCI_IRCTL_BFILL_SHIFT) & OHCI_IRCTL_BFILL_MASK) | \ (((IHDR) << OHCI_IRCTL_IHDR_SHIFT) & OHCI_IRCTL_IHDR_MASK) | \ (((MATCHENBL) << OHCI_IRCTL_MTC_ENBL_SHIFT) & \ OHCI_IRCTL_MTC_ENBL_MASK) | \ (((MULTI) << OHCI_IRCTL_MULTI_SHIFT) & OHCI_IRCTL_MULTI_MASK) | \ (((RUN) << OHCI_CC_RUN_SHIFT) & OHCI_CC_RUN_MASK) | \ (((WAKE) << OHCI_CC_WAKE_SHIFT) & OHCI_CC_WAKE_MASK))) #define HCI1394_IRCTXT_CTRL_CLR(HCIP, I, BFFILL, IHDR, MATCHENBL, MULTI, RUN) \ (ddi_put32((HCIP)->ohci->ohci_reg_handle, \ &(HCIP)->ohci->ohci_regs->ir[(I)].ctxt_ctrl_clr, \ 0 | (((BFFILL) << OHCI_IRCTL_BFILL_SHIFT) & OHCI_IRCTL_BFILL_MASK) | \ (((IHDR) << OHCI_IRCTL_IHDR_SHIFT) & OHCI_IRCTL_IHDR_MASK) | \ (((MATCHENBL) << OHCI_IRCTL_MTC_ENBL_SHIFT) & \ OHCI_IRCTL_MTC_ENBL_MASK) | \ (((MULTI) << OHCI_IRCTL_MULTI_SHIFT) & OHCI_IRCTL_MULTI_MASK) | \ (((RUN) << OHCI_CC_RUN_SHIFT) & OHCI_CC_RUN_MASK))) #define HCI1394_ITCTXT_CTRL_SET(HCIP, I, MATCHENBL, MATCH, RUN, WAKE) \ (ddi_put32((HCIP)->ohci->ohci_reg_handle, \ &(HCIP)->ohci->ohci_regs->it[(I)].ctxt_ctrl_set, 0 | \ (((MATCHENBL) << OHCI_ITCTL_MTC_ENBL_SHIFT) & \ OHCI_ITCTL_MTC_ENBL_MASK) | \ (((MATCH) << OHCI_ITCTL_MATCH_SHIFT) & OHCI_ITCTL_MATCH_MASK) | \ (((RUN) << OHCI_CC_RUN_SHIFT) & OHCI_CC_RUN_MASK) | \ (((WAKE) << OHCI_CC_WAKE_SHIFT) & OHCI_CC_WAKE_MASK))) #define HCI1394_ITCTXT_CTRL_CLR(HCIP, I, MATCHENBL, MATCH, RUN) \ (ddi_put32((HCIP)->ohci->ohci_reg_handle, \ &(HCIP)->ohci->ohci_regs->it[(I)].ctxt_ctrl_clr, 0 | \ (((MATCHENBL) << OHCI_ITCTL_MTC_ENBL_SHIFT) & \ OHCI_ITCTL_MTC_ENBL_MASK) | \ (((MATCH) << OHCI_ITCTL_MATCH_SHIFT) & OHCI_ITCTL_MATCH_MASK) | \ (((RUN) << OHCI_CC_RUN_SHIFT) & OHCI_CC_RUN_MASK))) #define HCI1394_IRCTXT_MATCH_WRITE(HCIP, I, TAG3, TAG2, TAG1, TAG0, MATCH, \ SYNC, TAG1SYNC, CHAN) (ddi_put32((HCIP)->ohci->ohci_reg_handle, \ &(HCIP)->ohci->ohci_regs->ir[(I)].ctxt_match, 0 | \ (((TAG3) << OHCI_MTC_TAG3_SHIFT) & OHCI_MTC_TAG3_MASK) | \ (((TAG2) << OHCI_MTC_TAG2_SHIFT) & OHCI_MTC_TAG2_MASK) | \ (((TAG1) << OHCI_MTC_TAG1_SHIFT) & OHCI_MTC_TAG1_MASK) | \ (((TAG0) << OHCI_MTC_TAG0_SHIFT) & OHCI_MTC_TAG0_MASK) | \ (((MATCH) << OHCI_MTC_MATCH_SHIFT) & OHCI_MTC_MATCH_MASK) | \ (((SYNC) << OHCI_MTC_SYNC_SHIFT) & OHCI_MTC_SYNC_MASK) | \ (((TAG1SYNC) << OHCI_MTC_TAG1SY_SHIFT) & OHCI_MTC_TAG1SY_MASK) | \ (((CHAN) << OHCI_MTC_CHAN_SHIFT) & OHCI_MTC_CHAN_MASK))) #define HCI1394_ISOCH_CTXT_ACTIVE(SOFTSTATEP, CTXTP) \ (ddi_get32((SOFTSTATEP)->ohci->ohci_reg_handle, \ &(CTXTP)->ctxt_regsp->ctxt_ctrl_set) & OHCI_CC_ACTIVE_MASK) #define HCI1394_ISOCH_CTXT_RUN(SOFTSTATEP, CTXTP) \ (ddi_get32((SOFTSTATEP)->ohci->ohci_reg_handle, \ &(CTXTP)->ctxt_regsp->ctxt_ctrl_set) & OHCI_CC_RUN_MASK) #define HCI1394_ISOCH_CTXT_CMD_PTR(SOFTSTATEP, CTXTP) \ (ddi_get32((SOFTSTATEP)->ohci->ohci_reg_handle, \ &(CTXTP)->ctxt_regsp->cmd_ptrlo)) /* * 1394 OpenHCI 1.0 general context register layout * All contexts except for Isoch Receive have the following layout * See the OpenHCI v1.0 specification for register definitions. */ typedef struct hci1394_ctxt_regs_s { uint32_t ctxt_ctrl_set; uint32_t ctxt_ctrl_clr; uint32_t reserved; uint32_t cmd_ptrlo; } hci1394_ctxt_regs_t; /* * 1394 OpenHCI 1.0 Isochronous Receive context register layout * See the OpenHCI v1.0 specification for register definitions. */ typedef struct hci1394_ir_ctxt_regs_s { uint32_t ctxt_ctrl_set; uint32_t ctxt_ctrl_clr; uint32_t reserved0; uint32_t cmd_ptrlo; uint32_t ctxt_match; uint32_t reserved1[3]; } hci1394_ir_ctxt_regs_t; /* * 1394 OpenHCI 1.0 registers * See the OpenHCI v1.0 specification for register definitions. */ typedef struct hci1394_regs_s { uint32_t version; uint32_t guid_rom; uint32_t at_retries; uint32_t csr_data; uint32_t csr_compare_data; uint32_t csr_ctrl; uint32_t config_rom_hdr; uint32_t bus_id; uint32_t bus_options; uint32_t guid_hi; uint32_t guid_lo; uint32_t reserved01; uint32_t reserved02; uint32_t config_rom_maplo; uint32_t posted_write_addrlo; uint32_t posted_write_addrhi; uint32_t vendor_id; uint32_t reserved03[3]; uint32_t hc_ctrl_set; uint32_t hc_ctrl_clr; uint32_t reserved06[2]; uint32_t reserved08; uint32_t self_id_buflo; uint32_t self_id_count; uint32_t reserved09; uint32_t ir_multi_maskhi_set; uint32_t ir_multi_maskhi_clr; uint32_t ir_multi_masklo_set; uint32_t ir_multi_masklo_clr; uint32_t intr_event_set; uint32_t intr_event_clr; uint32_t intr_mask_set; uint32_t intr_mask_clr; uint32_t it_intr_event_set; uint32_t it_intr_event_clr; uint32_t it_intr_mask_set; uint32_t it_intr_mask_clr; uint32_t ir_intr_event_set; uint32_t ir_intr_event_clr; uint32_t ir_intr_mask_set; uint32_t ir_intr_mask_clr; uint32_t reserved10[11]; uint32_t fairness_ctrl; uint32_t link_ctrl_set; uint32_t link_ctrl_clr; uint32_t node_id; uint32_t phy_ctrl; uint32_t isoch_cycle_timer; uint32_t reserved21[3]; uint32_t ar_req_filterhi_set; uint32_t ar_req_filterhi_clr; uint32_t ar_req_filterlo_set; uint32_t ar_req_filterlo_clr; uint32_t phys_req_filterhi_set; uint32_t phys_req_filterhi_clr; uint32_t phys_req_filterlo_set; uint32_t phys_req_filterlo_clr; uint32_t phys_upper_bound; uint32_t reserved24[23]; hci1394_ctxt_regs_t at_req; uint32_t reserved47[4]; hci1394_ctxt_regs_t at_resp; uint32_t reserved51[4]; hci1394_ctxt_regs_t ar_req; uint32_t reserved55[4]; hci1394_ctxt_regs_t ar_resp; uint32_t reserved59[4]; hci1394_ctxt_regs_t it[HCI1394_MAX_ISOCH_CONTEXTS]; hci1394_ir_ctxt_regs_t ir[HCI1394_MAX_ISOCH_CONTEXTS]; } hci1394_regs_t; /* private structure to keep track of OpenHCI */ typedef struct hci1394_ohci_s { /* config ROM and selfid buffers */ hci1394_buf_handle_t ohci_cfgrom_handle; hci1394_buf_handle_t ohci_selfid_handle; /* * Phy register #1 cached settings. These are only used for 1394-1995 * phy's. When setting the root holdoff bit and gap count in 1394, * you send out a PHY configuration packet. The 1995 PHY's will * not look at the PHY packet if we sent it out which means we have * to write directly to PHY register 1. This creates some ugly race * conditions. Since we will be following up these settings with a bus * reset shortly, we "cache" them until we generate the bus reset. This * solution is not perfect, but it is the best of a bad thing. */ boolean_t ohci_set_root_holdoff; boolean_t ohci_set_gap_count; uint_t ohci_gap_count; /* * The bus time is kept using the cycle timer and then counting the * rollovers via the cycle 64 seconds interrupt. (NOTE: every 2 * interrupts is one rollover) We do not wish to be interrupting * the CPU if there is nothing plugged into the bus (since bus time * really isn't used for anything yet (maybe when bridges come out?)). * We will start with the interrupt disabled, if the bus master writes * to the CSR bus time register, we will enable the interrupt. These * fields keep track of the rollover and whether or not the interrupt * is enabled. */ volatile uint_t ohci_bustime_count; boolean_t ohci_bustime_enabled; /* whether we have a 1394-1995 or 1394A phy */ h1394_phy_t ohci_phy; /* General Driver Info */ hci1394_drvinfo_t *ohci_drvinfo; /* * self id buffer and config rom info. These are towards bottom of the * structure to make debugging easier. */ hci1394_buf_info_t ohci_selfid; hci1394_buf_info_t ohci_cfgrom; /* OpenHCI registers */ ddi_acc_handle_t ohci_reg_handle; hci1394_regs_t *ohci_regs; /* * This mutex is used to protect "atomic" operations to the OpenHCI * hardware. This includes reads and writes to the PHY, cswap * operations to the HW implemented CSR registers, and any read/modify/ * write operations such as updating atreq retries. */ kmutex_t ohci_mutex; hci1394_state_t *soft_state; } hci1394_ohci_t; _NOTE(SCHEME_PROTECTS_DATA("Single thread modifies", \ hci1394_ohci_s::ohci_bustime_count \ hci1394_ohci_s::ohci_bustime_enabled \ hci1394_ohci_s::ohci_gap_count \ hci1394_ohci_s::ohci_set_gap_count \ hci1394_ohci_s::ohci_set_root_holdoff)) /* handle passed back from init() and used for rest of functions */ typedef hci1394_ohci_t *hci1394_ohci_handle_t; int hci1394_ohci_init(hci1394_state_t *soft_state, hci1394_drvinfo_t *drvinfo, hci1394_ohci_handle_t *ohci_hdl); void hci1394_ohci_fini(hci1394_ohci_handle_t *ohci_hdl); void hci1394_ohci_reg_read(hci1394_ohci_handle_t ohci_hdl, uint_t offset, uint32_t *data); void hci1394_ohci_reg_write(hci1394_ohci_handle_t ohci_hdl, uint_t offset, uint32_t data); int hci1394_ohci_phy_init(hci1394_ohci_handle_t ohci_hdl); int hci1394_ohci_phy_set(hci1394_ohci_handle_t ohci_hdl, uint_t regAddr, uint_t bits); int hci1394_ohci_phy_clr(hci1394_ohci_handle_t ohci_hdl, uint_t regAddr, uint_t bits); int hci1394_ohci_phy_read(hci1394_ohci_handle_t ohci_hdl, uint_t regAddr, uint_t *rdData); int hci1394_ohci_phy_write(hci1394_ohci_handle_t ohci_hdl, uint_t regAddr, uint_t wrData); int hci1394_ohci_phy_info(hci1394_ohci_handle_t ohci_hdl, uint32_t *info); void hci1394_ohci_intr_master_enable(hci1394_ohci_handle_t ohci_hdl); void hci1394_ohci_intr_master_disable(hci1394_ohci_handle_t ohci_hdl); uint32_t hci1394_ohci_intr_asserted(hci1394_ohci_handle_t ohci_hdl); void hci1394_ohci_intr_enable(hci1394_ohci_handle_t ohci_hdl, uint32_t intr_mask); void hci1394_ohci_intr_disable(hci1394_ohci_handle_t ohci_hdl, uint32_t intr_mask); void hci1394_ohci_intr_clear(hci1394_ohci_handle_t ohci_hdl, uint32_t intr_mask); uint32_t hci1394_ohci_it_intr_asserted(hci1394_ohci_handle_t ohci_hdl); void hci1394_ohci_it_intr_enable(hci1394_ohci_handle_t ohci_hdl, uint32_t intr_mask); void hci1394_ohci_it_intr_disable(hci1394_ohci_handle_t ohci_hdl, uint32_t intr_mask); void hci1394_ohci_it_intr_clear(hci1394_ohci_handle_t ohci_hdl, uint32_t intr_mask); int hci1394_ohci_it_ctxt_count_get(hci1394_ohci_handle_t ohci_hdl); void hci1394_ohci_it_cmd_ptr_set(hci1394_ohci_handle_t ohci_hdl, uint_t context_number, uint32_t io_addr); uint32_t hci1394_ohci_ir_intr_asserted(hci1394_ohci_handle_t ohci_hdl); void hci1394_ohci_ir_intr_enable(hci1394_ohci_handle_t ohci_hdl, uint32_t intr_mask); void hci1394_ohci_ir_intr_disable(hci1394_ohci_handle_t ohci_hdl, uint32_t intr_mask); void hci1394_ohci_ir_intr_clear(hci1394_ohci_handle_t ohci_hdl, uint32_t intr_mask); int hci1394_ohci_ir_ctxt_count_get(hci1394_ohci_handle_t ohci_hdl); void hci1394_ohci_ir_cmd_ptr_set(hci1394_ohci_handle_t ohci_hdl, uint_t context_number, uint32_t io_addr); void hci1394_ohci_link_enable(hci1394_ohci_handle_t ohci_hdl); void hci1394_ohci_link_disable(hci1394_ohci_handle_t ohci_hdl); uint_t hci1394_ohci_current_busgen(hci1394_ohci_handle_t ohci_hdl); int hci1394_ohci_soft_reset(hci1394_ohci_handle_t ohci_hdl); int hci1394_ohci_startup(hci1394_ohci_handle_t ohci_hdl); uint64_t hci1394_ohci_guid(hci1394_ohci_handle_t ohci_hdl); int hci1394_ohci_csr_read(hci1394_ohci_handle_t ohci_hdl, uint_t offset, uint32_t *data); int hci1394_ohci_csr_cswap(hci1394_ohci_handle_t ohci_hdl, uint_t generation, uint_t offset, uint32_t compare, uint32_t swap, uint32_t *old); int hci1394_ohci_bus_reset(hci1394_ohci_handle_t ohci_hdl); int hci1394_ohci_bus_reset_nroot(hci1394_ohci_handle_t ohci_hdl); int hci1394_ohci_bus_reset_short(hci1394_ohci_handle_t ohci_hdl); void hci1394_ohci_postwr_addr(hci1394_ohci_handle_t ohci_hdl, uint64_t *addr); int hci1394_ohci_contender_enable(hci1394_ohci_handle_t ohci_hdl); int hci1394_ohci_root_holdoff_enable(hci1394_ohci_handle_t ohci_hdl); int hci1394_ohci_gap_count_set(hci1394_ohci_handle_t ohci_hdl, uint_t gap_count); int hci1394_ohci_phy_filter_set(hci1394_ohci_handle_t ohci_hdl, uint64_t mask, uint_t generation); int hci1394_ohci_phy_filter_clr(hci1394_ohci_handle_t ohci_hdl, uint64_t mask, uint_t generation); void hci1394_ohci_cfgrom_update(hci1394_ohci_handle_t ohci_hdl, void *local_buf, uint_t quadlet_count); void hci1394_ohci_selfid_enable(hci1394_ohci_handle_t ohci_hdl); void hci1394_ohci_selfid_read(hci1394_ohci_handle_t ohci_hdl, uint_t offset, uint32_t *data); void hci1394_ohci_selfid_info(hci1394_ohci_handle_t ohci_hdl, uint_t *busgen, uint_t *size, boolean_t *error); boolean_t hci1394_ohci_selfid_buf_current(hci1394_ohci_handle_t ohci_hdl); void hci1394_ohci_selfid_sync(hci1394_ohci_handle_t ohci_hdl); void hci1394_ohci_nodeid_set(hci1394_ohci_handle_t ohci_hdl, uint_t nodeid); void hci1394_ohci_nodeid_get(hci1394_ohci_handle_t ohci_hdl, uint_t *nodeid); void hci1394_ohci_nodeid_info(hci1394_ohci_handle_t ohci_hdl, uint_t *nodeid, boolean_t *error); void hci1394_ohci_cycletime_get(hci1394_ohci_handle_t ohci_hdl, uint32_t *cycle_time); void hci1394_ohci_cycletime_set(hci1394_ohci_handle_t ohci_hdl, uint32_t cycle_time); void hci1394_ohci_bustime_get(hci1394_ohci_handle_t ohci_hdl, uint32_t *bus_time); void hci1394_ohci_bustime_set(hci1394_ohci_handle_t ohci_hdl, uint32_t bus_time); void hci1394_ohci_atreq_retries_get(hci1394_ohci_handle_t ohci_hdl, uint_t *atreq_retries); void hci1394_ohci_atreq_retries_set(hci1394_ohci_handle_t ohci_hdl, uint_t atreq_retries); void hci1394_ohci_isr_cycle64seconds(hci1394_ohci_handle_t ohci_hdl); void hci1394_ohci_isr_phy(hci1394_ohci_handle_t ohci_hdl); boolean_t hci1394_ohci_root_check(hci1394_ohci_handle_t ohci_hdl); boolean_t hci1394_ohci_cmc_check(hci1394_ohci_handle_t ohci_hdl); void hci1394_ohci_cycle_master_enable(hci1394_ohci_handle_t ohci_hdl); void hci1394_ohci_cycle_master_disable(hci1394_ohci_handle_t ohci_hdl); int hci1394_ohci_resume(hci1394_ohci_handle_t ohci_hdl); void hci1394_ohci_bus_capabilities(hci1394_ohci_handle_t ohci_hdl, uint32_t *bus_capabilities); boolean_t hci1394_ohci_at_active(hci1394_ohci_handle_t ohci_hdl); void hci1394_ohci_atreq_start(hci1394_ohci_handle_t ohci_hdl, uint32_t cmdptr); void hci1394_ohci_atreq_wake(hci1394_ohci_handle_t ohci_hdl); void hci1394_ohci_atreq_stop(hci1394_ohci_handle_t ohci_hdl); void hci1394_ohci_arresp_start(hci1394_ohci_handle_t ohci_hdl, uint32_t cmdptr); void hci1394_ohci_arresp_wake(hci1394_ohci_handle_t ohci_hdl); void hci1394_ohci_arresp_stop(hci1394_ohci_handle_t ohci_hdl); void hci1394_ohci_arreq_start(hci1394_ohci_handle_t ohci_hdl, uint32_t cmdptr); void hci1394_ohci_arreq_wake(hci1394_ohci_handle_t ohci_hdl); void hci1394_ohci_arreq_stop(hci1394_ohci_handle_t ohci_hdl); void hci1394_ohci_atresp_start(hci1394_ohci_handle_t ohci_hdl, uint32_t cmdptr); void hci1394_ohci_atresp_wake(hci1394_ohci_handle_t ohci_hdl); void hci1394_ohci_atresp_stop(hci1394_ohci_handle_t ohci_hdl); #ifdef __cplusplus } #endif #endif /* _SYS_1394_ADAPTERS_HCI1394_OHCI_H */ /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License, Version 1.0 only * (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 (c) 1999-2000 by Sun Microsystems, Inc. * All rights reserved. */ #ifndef _SYS_1394_ADAPTERS_HCI1394_Q_H #define _SYS_1394_ADAPTERS_HCI1394_Q_H /* * hci1394_q.h * This code decouples some of the OpenHCI async descriptor logic/structures * from the async processing. The goal was to combine as much of the * duplicate code as possible for the different type of async transfers * without going too overboard. * * There are two parts to the Q, the descriptor buffer and the data buffer. * for the most part, data to be transmitted and data which is received go * in the data buffers. The information of where to get the data and put * the data reside in the descriptor buffers. There are exceptions to this. */ #ifdef __cplusplus extern "C" { #endif #include #include #include #include #include #include #include #include #include /* * Part of q_info passed in during q_init(). This tells us if this is an async * transmit or async receive Q. This makes a big difference inside of q. For * the transmit Q we will just setup an empty Q ready for TX calls into us. For * receive Q's we have to make sure we get multiple data buffers and then setup * the buffers so they are ready to receive data (by adding in the IM * descriptors). */ typedef enum { HCI1394_ARQ, HCI1394_ATQ } hci1394_q_mode_t; /* * Part of q_info passed in during q_init(). These are the callbacks for * starting and waking up the async Q's. When the first descriptor is placed * on the Q, the async DMA engine is started with an address of where to find * the descriptor on the Q. That descriptor will be changed to point to the * next descriptor when the next descriptor is added (i.e. a chained dma). * Whenever an additional descriptor is added, wake is called. */ typedef void (*hci1394_q_start_t)(void *arg, uint32_t io_addr); typedef void (*hci1394_q_wake_t)(void *arg); /* * Passed in during q_init(). This contains the size of the descriptor Q, the * size of the data Q, what kind of Q it is (AT or AR), the callbacks for start * and wake, and the argument to pass during start and wake. */ typedef struct hci1394_q_info_s { uint_t qi_desc_size; uint_t qi_data_size; hci1394_q_mode_t qi_mode; hci1394_q_start_t qi_start; hci1394_q_wake_t qi_wake; void *qi_callback_arg; } hci1394_q_info_t; /* * Per command tracking information for the AT Q's. This is not used on the AR * side. This structure has two parts to it, the public data and the private * data. The public data is shared between async.c and q.c. The private data * is for internal q.c access only. It is only put in this structure so that * we do not have to dynamically alloc space for each transfer. */ typedef struct hci1394_q_cmd_s { /* PUBLIC DATA STRUCTURES */ /* * qc_arg is an input paramter to hci1394_q_at() (along with the data * versions). It is an opaque address pointer which is used by async.c * to determine the commands address after a call to * hci1394_q_at_next(). */ void *qc_arg; /* * qc_generation is an input parameter to hci1394_q_at() (along with the * data versions). It is the generation count for which this command is * valid. If qc_generation does not match the current bus generation, * hci1394_q_at*() will return failure. */ uint_t qc_generation; /* * qc_timestamp is used when sending an atresp to set the time when the * response is to have timed out. It is also use on at_next to tell * when the AT command completed. */ uint_t qc_timestamp; /* * qc_status is an output of hci1394_q_at_next(). It contains the * command status after completion. */ uint32_t qc_status; /* PRIVATE DATA STRUCTURES */ /* * This is the memory address of where the status of this command * resides. */ uint32_t *qc_status_addr; /* * qc_descriptor_end and qc_descriptor_buf are used to track where the * descriptor q pointers should be set to when this command has * completed (i.e. free up the space used by this command) */ caddr_t qc_descriptor_end; uint_t qc_descriptor_buf; /* * qc_data_end and qc_data_buf are used to track where the data q * pointers should be set to when this command has completed (i.e. free * up the space used by this command). Not all commands use the data * q so qc_data_used give us state on if this command uses the data q. */ boolean_t qc_data_used; caddr_t qc_data_end; uint_t qc_data_buf; /* * This is the node for the queued list. Since AT requests finish in * the order that they were submitted, we queue these up in a linked * list so that it is easy to figure out which command has finished. * Just look at the head of the list. */ hci1394_tlist_node_t qc_node; } hci1394_q_cmd_t; _NOTE(SCHEME_PROTECTS_DATA("Single thread modifies", \ hci1394_q_cmd_s::qc_status \ hci1394_q_cmd_s::qc_timestamp)) typedef struct hci1394_q_bufptr_s { /* * kernel virtual addresses. The q may be broken down into multiple * cookies. The q is contiguous relative to the driver, but segmented * relative to the 1394 HW DMA engines. * * qp_top is the top the q. qp_bottom is the bottom of the q. These * never change after initial setup. qp_bottom is inclusive (i.e. for a * q size of 16 bytes where top was = to 0, qp_bottom would be = to 15). * * qp_current and qp_free are pointers within top and bottom. qp_current * refers to the next free space to write and free refers to the end of * free space (i.e. used memory within q). qp_free is inclusive (see * qp_bottom). */ caddr_t qp_top; caddr_t qp_bottom; caddr_t qp_current; caddr_t qp_free; /* * qp_begin and qp_end are also kernel virtual addresses. They are the * beginning and ending address of the current_buf (cookie) within the * q. qp_offset is (qp_current - qp_begin). This is used to determine * the 32 bit PCI address to put into the OpenHCI descriptor. We know * the base PCI address from the cookie structure, we add offset to that * to determine the correct PCI address. */ caddr_t qp_begin; caddr_t qp_end; uint32_t qp_offset; /* * As stated above, the q may be broken into multiple cookies. * qp_current_buf is the cookie qp_current is in and qp_free_buf is the * cookie qp_free is in. NOTE: The cookie's are numbered 0, 1, 2, ..., * (i.e. if we have 4 cookies, qp_current_buf can be 0, 1, 2, or 3) */ uint_t qp_current_buf; uint_t qp_free_buf; /* * qp_resv_size is only used for the AT Q's. * How much space has been reserved. This value is set on the call to * hci1394_q_reserve() and decremented each time a data is written. It * is used to check for overrun conditions. This extra check is in there * as an added sanity check due to the complexity of this code. */ uint_t qp_resv_size; } hci1394_q_bufptr_t; typedef struct hci1394_q_buf_s { /* pointers to track used/free space/cookies in the buffer */ hci1394_q_bufptr_t qb_ptrs; /* * a backup of qb_ptrs. If we fail while setting up an AT Q, we need to * cleanup by putting things back the way that they were. */ hci1394_q_bufptr_t qb_backup_ptrs; /* copy of all of the cookie's structures for this buffer */ ddi_dma_cookie_t qb_cookie[OHCI_MAX_COOKIE]; /* Buffer handle used for calls into hci1394_buf_* routines */ hci1394_buf_handle_t qb_buf_handle; /* Buffer info (i.e. cookie count, kaddr, ddi handles, etc.) */ hci1394_buf_info_t qb_buf; } hci1394_q_buf_t; _NOTE(SCHEME_PROTECTS_DATA("Single thread modifies", \ hci1394_q_buf_s::qb_ptrs.qp_begin \ hci1394_q_buf_s::qb_ptrs.qp_bottom \ hci1394_q_buf_s::qb_ptrs.qp_current \ hci1394_q_buf_s::qb_ptrs.qp_current_buf \ hci1394_q_buf_s::qb_ptrs.qp_end \ hci1394_q_buf_s::qb_ptrs.qp_offset \ hci1394_q_buf_s::qb_ptrs.qp_top)) typedef struct hci1394_q_s { /* * q_queued_list is only used in the AT descriptor Qs. AT commands * complete in the order they were issued. We Q these commands up with * each new command being added to the end of the list. When a command * completes, we look at the top of this list to determine which command * completed. */ hci1394_tlist_handle_t q_queued_list; /* * pointer to general driver information (dip, instance, etc) and to * handle for access to openHCI routines. */ hci1394_drvinfo_t *q_drvinfo; hci1394_ohci_handle_t q_ohci; /* * The OpenHCI DMA engines are basically just chained DMA engines. Each * "link" in the chain is called a descriptor in OpenHCI. When you want * to add a new descriptor, you init the descriptor, setup its "next" * pointer to "NULL", update the previous descriptor to point to the * new descriptor, and tell the HW you added a new descriptor by setting * its wake bit. q_previous is a pointer to the previous descriptor. * When adding a new descriptor, we just de-reference q_previous to * update its "next" pointer. */ hci1394_desc_t *q_previous; /* * When updating the "next" pointer in the previous descriptor block * (as described above in q_previous), one of the things you need to * tell the HW is how many 16 byte blocks the next descriptor block * uses. This is what q_block_cnt is used for. This is only used in the * AT descriptor Q's. Since the IM's used in the AR Q's are the only * descriptor types used in AR, the block count is always the same for * an AR descriptor Q. */ uint_t q_block_cnt; /* * q_head is only used in the AR descriptor Qs. It contains the location * of the first descriptor on the Q. This is used to look at the * residual count in the AR data Q. The residual count tells us if we * have received any new packets to process. When a descriptor's data * buffer is empty (q_space_left = 0), we move q_head to the next * descriptor in the descriptor buffer. */ caddr_t q_head; /* * q_space_left is only used in the AR descriptor Qs. Each AR * descriptor has residual count embedded in the descriptor which says * how much free space is left in the descriptors associated data * buffer. q_space_left is how much SW thinks is left in the data * buffer. When they do not match, we have a new packet(s) in the data * buffer to process. Since the residual count is not updated by the * HW until the entire packet has been written to memory, we don't have * to worry about any partial packet RX problems. */ uint_t q_space_left; /* * status of the dma controller. This tells us if we should do a start * or a wake. If the dma engine is not running, we should start it. If * it is running, we should wake it. When the DMA engine is started, it * expects to have a valid descriptor to process. Since we don't have * anything to send in the beginning (AT), we have to wait until the * first AT packet comes down before we can start the DMA engine. */ boolean_t q_dma_running; /* The descriptor buffer for this Q */ hci1394_q_buf_t q_desc; /* The data buffer for this Q */ hci1394_q_buf_t q_data; /* copy of qinfo passed in during hci1394_q_init() */ hci1394_q_info_t q_info; kmutex_t q_mutex; } hci1394_q_t; _NOTE(SCHEME_PROTECTS_DATA("Single thread modifies", \ hci1394_q_s::q_dma_running \ hci1394_q_s::q_head \ hci1394_q_s::q_previous \ hci1394_q_s::q_space_left)) /* handle passed back from init() and used for rest of functions */ typedef struct hci1394_q_s *hci1394_q_handle_t; int hci1394_q_init(hci1394_drvinfo_t *drvinfo, hci1394_ohci_handle_t ohci_handle, hci1394_q_info_t *qinfo, hci1394_q_handle_t *q_handle); void hci1394_q_fini(hci1394_q_handle_t *q_handle); void hci1394_q_resume(hci1394_q_handle_t q_handle); void hci1394_q_stop(hci1394_q_handle_t q_handle); int hci1394_q_at(hci1394_q_handle_t q_handle, hci1394_q_cmd_t *cmd, hci1394_basic_pkt_t *hdr, uint_t hdrsize, int *result); int hci1394_q_at_with_data(hci1394_q_handle_t q_handle, hci1394_q_cmd_t *cmd, hci1394_basic_pkt_t *hdr, uint_t hdrsize, uint8_t *data, uint_t datasize, int *result); int hci1394_q_at_with_mblk(hci1394_q_handle_t q_handle, hci1394_q_cmd_t *cmd, hci1394_basic_pkt_t *hdr, uint_t hdrsize, h1394_mblk_t *mblk, int *result); void hci1394_q_at_next(hci1394_q_handle_t q_handle, boolean_t flush_q, hci1394_q_cmd_t **cmd); void hci1394_q_ar_next(hci1394_q_handle_t q_handle, uint32_t **q_addr); void hci1394_q_ar_free(hci1394_q_handle_t q_handle, uint_t size); uint32_t hci1394_q_ar_get32(hci1394_q_handle_t q_handle, uint32_t *addr); void hci1394_q_ar_rep_get8(hci1394_q_handle_t q_handle, uint8_t *dest, uint8_t *q_addr, uint_t size); void hci1394_q_ar_copy_to_mblk(hci1394_q_handle_t q_handle, uint8_t *addr, h1394_mblk_t *mblk); #ifdef __cplusplus } #endif #endif /* _SYS_1394_ADAPTERS_HCI1394_Q_H */ /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License, Version 1.0 only * (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 (c) 1999-2000 by Sun Microsystems, Inc. * All rights reserved. */ #ifndef _SYS_1394_ADAPTERS_HCI1394_RIO_REGS_H #define _SYS_1394_ADAPTERS_HCI1394_RIO_REGS_H /* * hci1394_rio_regs.h * Sun Microsystems RIO chipset * See the RIO specification (r1.0), section 5.9, for a description * of the vendor specific registers. */ #ifdef __cplusplus extern "C" { #endif /* * RIO's vendor specific register mapping information. What register set it * uses and the offset/size of the register set. */ #define RIOREG_REG_BASE 0x2 #define RIOREG_OFFSET 0x0 #define RIOREG_LENGTH 0x800 /* * For RIO pass 1, we will setup the GUID in as part of the vendor specific * init. This is to support the RIO PPX card (since it does not have firmware * to setup the GUID. */ #define RIOREG_GUID_MASK 0x000000FFFFFFFFFF #define RIOREG_GUID_SUN_MICROSYSTEMS 0x0800200000000000 #define RIOREG_SUNW_RIO_PASS1 0x01080020 /* * RIO vendor specific registers. These are the offsets of the registers. They * should be used as paramteres to hci1394_vendor_reg_write() and * hci1394_vendor_reg_read(). */ #define RIOREG_INTR_EVENT 0x00 #define RIOREG_INTR_MASK 0x04 #define RIOREG_DMA_BURST_SIZE 0x08 #define RIOREG_XMIT_CONTROL 0x0C #define RIOREG_HOST_CONTROL 0x10 #define RIOREG_STATS_RETRIES 0x14 #define RIOREG_STATS_ERRORS 0x18 #define RIOREG_STATS_PHYSICAL 0x1C /* RIO interrupt event & mask bit offsets */ #define RIOREG_INTR_STATS1 0x001 #define RIOREG_INTR_STATS2 0x002 #define RIOREG_INTR_STATS3 0x004 #define RIOREG_INTR_STATS4 0x008 #define RIOREG_INTR_STATS5 0x010 #define RIOREG_INTR_STATS6 0x020 #define RIOREG_INTR_STATS7 0x040 #define RIOREG_INTR_STATS8 0x080 #define RIOREG_INTR_LINKON 0x100 /* dma_burst_size (field defs) */ #define RIOREG_INF_BURST_SHIFT 0 #define RIOREG_DBURST_SHIFT 1 #define RIOREG_RXBURST_SHIFT 26 #define RIOREG_TXBURST_SHIFT 28 #define RIOREG_PFBURST_SHIFT 30 #define RIOREG_INF_BURST_MASK (1 << RIOREG_INF_BURST_SHIFT) #define RIOREG_DBURST_MASK (1 << RIOREG_DBURST_SHIFT) #define RIOREG_RXBURST_MASK (3 << RIOREG_RXBURST_SHIFT) #define RIOREG_TXBURST_MASK (3 << RIOREG_TXBURST_SHIFT) #define RIOREG_PFBURST_MASK (3 << RIOREG_PFBURST_SHIFT) /* dma_burst_size (values) */ #define RIOREG_BURST_32 0 /* 32 bytes or less */ #define RIOREG_BURST_64 1 /* 64 bytes or less */ #define RIOREG_BURST_128 2 /* 128 bytes or less */ #define RIOREG_BURST_256 3 /* 256 bytes or less */ /* xmit ctrl (field defs) */ #define RIOREG_XMIT_BND1_SHIFT 0 #define RIOREG_XMIT_BND2_SHIFT 8 #define RIOREG_XMIT_BND1_MASK (0xFF << RIOREG_XMIT_BND1_SHIFT) #define RIOREG_XMIT_BND2_MASK (0xFF << RIOREG_XMIT_BND2_SHIFT) /* host control (field defs) */ #define RIOREG_HOST_ATREQ 0x00000001 #define RIOREG_HOST_ATRESP 0x00000002 #define RIOREG_HOST_IT1 0x00000004 #define RIOREG_HOST_IT2 0x00000008 #define RIOREG_HOST_IT3 0x00000010 #define RIOREG_HOST_IT4 0x00000020 #define RIOREG_HOST_ARREQ 0x00000040 #define RIOREG_HOST_ARRESP 0x00000080 #define RIOREG_HOST_IR1 0x00000100 #define RIOREG_HOST_IR2 0x00000200 #define RIOREG_HOST_IR3 0x00000400 #define RIOREG_HOST_IR4 0x00000800 #define RIOREG_HOST_BWCAT 0x02000000 #define RIOREG_HOST_BRCAT 0x04000000 #define RIOREG_HOST_ISOCTL 0xC0000000 /* Allow Descriptor pre-fetching */ #define RIOREG_HOST_CONTROL_SETTING \ (RIOREG_HOST_ATREQ | RIOREG_HOST_ATRESP | RIOREG_HOST_IT1 | \ RIOREG_HOST_IT2 | RIOREG_HOST_IT3 | RIOREG_HOST_IT4 | \ RIOREG_HOST_ARREQ | RIOREG_HOST_ARRESP | RIOREG_HOST_IR1 | \ RIOREG_HOST_IR2 | RIOREG_HOST_IR3 | RIOREG_HOST_IR4) /* stats_retries (field defs) */ #define RIOREG_RET_PHYS 0xFF000000 #define RIOREG_RET_ATS 0x0000FF00 #define RIOREG_RET_ATQ 0x000000FF /* stats_errors (field defs) */ #define RIOREG_ERR_EACKR 0x000000FF #define RIOREG_ERR_EACKX 0x0000FF00 #define RIOREG_ERR_BUS 0x0FFF0000 /* stats_phys (field defs) */ #define RIOREG_PHYS_WRQ 0x000000FF #define RIOREG_PHYS_RDQ 0x00FF0000 #ifdef __cplusplus } #endif #endif /* _SYS_1394_ADAPTERS_HCI1394_RIO_REGS_H */ /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License, Version 1.0 only * (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 2004 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #ifndef _SYS_1394_ADAPTERS_HCI1394_STATE_H #define _SYS_1394_ADAPTERS_HCI1394_STATE_H /* * hci1394_state.h * The hci1394 driver soft state structure. */ #ifdef __cplusplus extern "C" { #endif #include #include #include #include #include #include #include #include #include #include #include #include /* * hci1394 state structure * put all handles and pointers at the top so it is easier to find things * when debugging */ struct hci1394_state_s { /* various module handles */ hci1394_ohci_handle_t ohci; /* see hci1394_ohci.h */ hci1394_async_handle_t async; /* see hci1394_async.h */ hci1394_vendor_handle_t vendor; /* see hci1394_vendor.h */ hci1394_csr_handle_t csr; /* see hci1394_csr.h */ hci1394_isoch_handle_t isoch; /* see hci1394_isoch.h */ /* * This is the address of the buffer we are to copy the selfid info * into. The Services layer will give us this during the Bus Reset * interrupt and we will copy it into the buffer during the selfid * complete interrupt. */ uint32_t *sl_selfid_buf; /* * drvinfo contains the core information which is shared among the * various different parts of the this driver. (e.g. dip, instance, * statistics, iblock_cookie, etc.) */ hci1394_drvinfo_t drvinfo; /* see hci1394_drvinfo.h */ /* Vendor Information about this adapter */ hci1394_vendor_info_t vendor_info; /* see hci1394_vendor.h */ /* attach stuff */ ddi_acc_handle_t pci_config; boolean_t swap_data; /* Adapter info passed up to the Services Layer */ h1394_halinfo_t halinfo; /* see h1394.h */ }; _NOTE(SCHEME_PROTECTS_DATA("Single thread modifies", \ hci1394_state_s::drvinfo.di_gencnt \ hci1394_state_s::drvinfo.di_stats.st_bus_reset_count \ hci1394_state_s::drvinfo.di_stats.st_selfid_count)) #ifdef __cplusplus } #endif #endif /* _SYS_1394_ADAPTERS_HCI1394_STATE_H */ /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License, Version 1.0 only * (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 (c) 1999-2000 by Sun Microsystems, Inc. * All rights reserved. */ #ifndef _SYS_1394_ADAPTERS_HCI1394_TLABEL_H #define _SYS_1394_ADAPTERS_HCI1394_TLABEL_H /* * hci1394_tlabel.h * These routines track the tlabel usage for a 1394 adapter. */ #ifdef __cplusplus extern "C" { #endif #include #include #include #include #include #include /* * TLABEL_RANGE specifies the number of tlabels that will be allocated for a * given node. tlabels are allocated starting at 0 and going up to * (TLABEL_RANGE - 1). * * e.g. if TLABEL_RANGE was set to 4, each node could have at most 4 outstanding * transactions to any other node at any given time and the tlabels allocated * would be 0, 1, 2, and 3. * * NOTE: the maximum value of TLABEL_RANGE is 64. */ #define TLABEL_RANGE 64 /* TLABEL_MASK is the mask used to extract the 6-bit tlabel */ #define TLABEL_MASK 0x3F /* * destination - a 16-bit value where the most significant 10-bits are the bus * # and the least significant 6 bits are the node #. The upper * 16 bits of this word are not used. * * tlabel - the 1394 tlabel to be used. A number ranging from * 0 - (TLABEL_RANGE - 1) */ typedef struct hci1394_tlabel_info_s { uint_t tbi_destination; uint_t tbi_tlabel; } hci1394_tlabel_info_t; _NOTE(SCHEME_PROTECTS_DATA("Single thread modifies", \ hci1394_tlabel_info_s::tbi_destination \ hci1394_tlabel_info_s::tbi_tlabel)) /* structure used to keep track of tlabels */ typedef struct hci1394_tlabel_s { /* * The maximum node number that we have sent a tlabel to inclusive. This * is used as an optimization during reset processing. */ uint_t tb_max_node; /* * Status if we have sent a broadcast request out. This is used as an * optimization during reset processing. */ boolean_t tb_bcast_sent; /* * free is used to keep track of free tlabels. The free tlabels are * tracked as a bit mask. If the bit is set to 1 the tlabel is free, * if set to 0 the tlabel is used. */ uint64_t tb_free[IEEE1394_MAX_NODES]; /* * bad is used to keep track of bad tlabels. A bad tlabel is used for a * ATREQ that was pended but the response was never received. They will * be put back into the free list when > 2 times the split timeout has * gone by (from the initial transfer). The bad tlabels are tracked as * a bit mask. If the bit is set to 1 the tlabel is bad, if set to 0 the * tlabel is good. */ uint64_t tb_bad[IEEE1394_MAX_NODES]; /* * last tracks the last used tlabel for a given node. This allows us to * walk through the tlabels for each node during tlabel allocation * (i.e. so we always don't allocate the same tlabel over and over again * if the device is accessed serially). */ uint8_t tb_last[IEEE1394_MAX_NODES]; /* * Times are in nS. reclaim_time is set to the duration to wait to * reclaim the bad tlabels. bad_timestamp is a timestamp for when the * last bad tlabel was added into the bit mask. */ hrtime_t tb_bad_timestamp[IEEE1394_MAX_NODES]; hrtime_t tb_reclaim_time; /* * *_lookup[node][tlabel] * Used to track a generic pointer for a given node/tlabel. */ void *tb_lookup[IEEE1394_MAX_NODES][TLABEL_RANGE]; /* general driver info */ hci1394_drvinfo_t *tb_drvinfo; kmutex_t tb_mutex; } hci1394_tlabel_t; _NOTE(SCHEME_PROTECTS_DATA("Single thread modifies", \ hci1394_tlabel_s::tb_reclaim_time)) /* handle passed back from init() and used for rest of functions */ typedef struct hci1394_tlabel_s *hci1394_tlabel_handle_t; void hci1394_tlabel_init(hci1394_drvinfo_t *drvinfo, hrtime_t reclaim_time_nS, hci1394_tlabel_handle_t *tlabel_handle); void hci1394_tlabel_fini(hci1394_tlabel_handle_t *tlabel_handle); int hci1394_tlabel_alloc(hci1394_tlabel_handle_t tlabel_handle, uint_t destination, hci1394_tlabel_info_t *tlabel_info); void hci1394_tlabel_free(hci1394_tlabel_handle_t tlabel_handle, hci1394_tlabel_info_t *tlabel_info); void hci1394_tlabel_register(hci1394_tlabel_handle_t tlabel_handle, hci1394_tlabel_info_t *tlabel_info, void *cmd); void hci1394_tlabel_lookup(hci1394_tlabel_handle_t tlabel_handle, hci1394_tlabel_info_t *tlabel_info, void **cmd); void hci1394_tlabel_bad(hci1394_tlabel_handle_t tlabel_handle, hci1394_tlabel_info_t *tlabel_info); void hci1394_tlabel_reset(hci1394_tlabel_handle_t tlabel_handle); void hci1394_tlabel_set_reclaim_time(hci1394_tlabel_handle_t tlabel_handle, hrtime_t reclaim_time_nS); #ifdef __cplusplus } #endif #endif /* _SYS_1394_ADAPTERS_HCI1394_TLABEL_H */ /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License, Version 1.0 only * (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 (c) 1999-2000 by Sun Microsystems, Inc. * All rights reserved. */ #ifndef _SYS_1394_ADAPTERS_HCI1394_TLIST_H #define _SYS_1394_ADAPTERS_HCI1394_TLIST_H /* * hci1394_tlist.h * This implements a timed double linked list. * This list supports: * - addition of node to the end of the list * - atomic deletion of node anywhere in list * - get and remove node from head of list * - enable/disable of timeout feature * - timeout feature, if enabled, will remove each node on the list which * has been on the list for > timeout. The callback provided will be * called for each node removed. The worst case time is around * timer_resolution after the timeout has occurred (i.e. if you set the * timer resolution to 50uS and the timeout to 100uS, you could get the * callback anywhere from 100uS to 150uS from when you added the node to * the list. This is a general statement and ignores things like * interrupt latency, context switching, etc. So if you see a time * around 155uS, don't complain :-) * - The timer is only used when something is on the list */ #ifdef __cplusplus extern "C" { #endif #include #include #include #include #include #include /* * Node Information * This structure is used to track the information for a given node in the * linked list. The node is added to the end of the linked list be calling * tlist_add(). */ typedef struct hci1394_tlist_node_s { /* * Public Members * addr * generic address pointer. This should be set to point to * whatever information you are using this node to track. */ void *tln_addr; /* * Private Members * These are private. They are only to be used in the tlist * implementation. They are included in the header file so that we * do not have to alloc/free memory when something is added/deleted * from the tlist. */ boolean_t tln_on_list; hrtime_t tln_expire_time; struct hci1394_tlist_node_s *tln_prev; struct hci1394_tlist_node_s *tln_next; } hci1394_tlist_node_t; /* * callback used in hci1394_tlist_timer_t. This will be called when a node on * the list expires. */ typedef void (*hci1394_tlist_callback_t)(hci1394_tlist_node_t *node, void *arg); /* * This structure is used if you are using the timeout feature of the linked * list. * timeout * time in nS when a node should be considered to haved timed out. * * timer_resolution * time in nS when the list should be checked for timeouts. It can be * varied from timeout to reduce the jitter in the callback. * * callback * function to call on timeout. * * callback_arg * user specified argument passed in callback * */ typedef struct hci1394_tlist_timer_s { hrtime_t tlt_timeout; hrtime_t tlt_timer_resolution; hci1394_tlist_callback_t tlt_callback; void *tlt_callback_arg; } hci1394_tlist_timer_t; /* State to determine if timeout is scheduled or not */ typedef enum { HCI1394_TLIST_TIMEOUT_OFF, HCI1394_TLIST_TIMEOUT_ON } hci1394_tlist_timeout_state_t; /* private structure used to keep track of the tlist */ typedef struct hci1394_tlist_s { /* head and tail of linked list */ hci1394_tlist_node_t *tl_head; hci1394_tlist_node_t *tl_tail; /* are we using timeout feature */ boolean_t tl_timer_enabled; /* has timeout() been called */ hci1394_tlist_timeout_state_t tl_state; /* id returned from timeout() */ timeout_id_t tl_timeout_id; /* local copy of timer_info */ hci1394_tlist_timer_t tl_timer_info; hci1394_drvinfo_t *tl_drvinfo; kmutex_t tl_mutex; } hci1394_tlist_t; _NOTE(SCHEME_PROTECTS_DATA("Single thread modifies", \ hci1394_tlist_s::tl_state \ hci1394_tlist_s::tl_timeout_id \ hci1394_tlist_s::tl_timer_info.tlt_timeout)) /* handle passed back from init() and used for rest of functions */ typedef struct hci1394_tlist_s *hci1394_tlist_handle_t; void hci1394_tlist_init(hci1394_drvinfo_t *drvinfo, hci1394_tlist_timer_t *timer, hci1394_tlist_handle_t *tlist_handle); void hci1394_tlist_fini(hci1394_tlist_handle_t *tlist_handle); void hci1394_tlist_add(hci1394_tlist_handle_t tlist_handle, hci1394_tlist_node_t *node); int hci1394_tlist_delete(hci1394_tlist_handle_t tlist_handle, hci1394_tlist_node_t *node); void hci1394_tlist_get(hci1394_tlist_handle_t tlist_handle, hci1394_tlist_node_t **node); void hci1394_tlist_peek(hci1394_tlist_handle_t tlist_handle, hci1394_tlist_node_t **node); void hci1394_tlist_timeout_update(hci1394_tlist_handle_t tlist_handle, hrtime_t timeout); void hci1394_tlist_timeout_cancel(hci1394_tlist_handle_t tlist_handle); #ifdef __cplusplus } #endif #endif /* _SYS_1394_ADAPTERS_HCI1394_TLIST_H */ /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License, Version 1.0 only * (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 (c) 1999-2000 by Sun Microsystems, Inc. * All rights reserved. */ #ifndef _SYS_1394_ADAPTERS_HCI1394_VERSION_H #define _SYS_1394_ADAPTERS_HCI1394_VERSION_H /* * hci1394_vendor.h * These routines provide initialization, cleanup, and general * access to vendor specific features on the OpenHCI adapter. */ #ifdef __cplusplus extern "C" { #endif #include #include #include #include /* Vendor Id's */ #define VENDOR_VID_SUN_MICROSYSTEMS 0x108E /* Sun Microsystems Device Id's */ #define VENDOR_DID_RIO_1394 0x1102 /* * we will support up to a maximum of 6 different Vendor Specific register * mappings. I would be surprised to see more than 1, but it is possible. */ #define VENDOR_MAX_REGSETS 6 /* Opaque handle */ typedef struct hci1394_vendor_s *hci1394_vendor_handle_t; /* * Vendor Specific Info * vendor_id - VendorID from PCI config space (0x0-0x1) * device_id - DeviceID from PCI config space (0x2-0x3) * revision_id - RevisionID from PCI config space (0x8) * ohci_version - 1394 OpenHCI Version Register (0x0) * ohci_vendor_id - 1394 OpenHCI Vendor ID Register (0x40) */ typedef struct hci1394_vendor_info_s { uint_t vendor_id; uint_t device_id; uint_t revision_id; uint32_t ohci_version; uint32_t ohci_vendor_id; uint_t vendor_reg_count; } hci1394_vendor_info_t; /* * structure to store vendor specific register address and handle. We will have * one of these for each Vendor Specific register mapping. */ typedef struct hci1394_vendor_reg_s { caddr_t vr_reg_addr; ddi_acc_handle_t vr_reg_handle; } hci1394_vendor_reg_t; /* * structure to track all of the vendor specific register mappings. * ve_reg_count is the number of different register mappings. ve_reg_array is * an array of these registers. If ve_reg_count = 2, ve_reg_array[0] will have * the first register mapping and ve_reg_array[1] will have the second register * mapping. */ typedef struct hci1394_vendor_s { hci1394_ohci_handle_t ve_ohci; uint_t ve_reg_count; hci1394_vendor_reg_t *ve_reg_array[VENDOR_MAX_REGSETS]; hci1394_drvinfo_t *ve_drvinfo; hci1394_vendor_info_t ve_info; } hci1394_vendor_t; int hci1394_vendor_init(hci1394_drvinfo_t *drvinfo, hci1394_ohci_handle_t ohci, hci1394_vendor_info_t *vendor_info, hci1394_vendor_handle_t *vendor_handle); void hci1394_vendor_fini(hci1394_vendor_handle_t *vendor_handle); int hci1394_vendor_resume(hci1394_vendor_handle_t vendor_handle); int hci1394_vendor_reg_write(hci1394_vendor_handle_t vendor_handle, uint_t reg_set, uint_t offset, uint32_t data); int hci1394_vendor_reg_read(hci1394_vendor_handle_t vendor_handle, uint_t reg_set, uint_t offset, uint32_t *data); #ifdef __cplusplus } #endif #endif /* _SYS_1394_ADAPTERS_HCI1394_VERSION_H */ /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License, Version 1.0 only * (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 2004 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #ifndef _SYS_1394_CMD1394_H #define _SYS_1394_CMD1394_H /* * cmd1394.h * Contains the enums, command structures, and error codes used with * the 1394 Framework's t1394_read(), t1394_write(), and t1394_lock() * interfaces. * For outgoing (Asynchronous Transmit - AT) commands, target drivers * allocate a command using t1394_alloc_cmd(), fill it in with the * transmit info, and send it using one of t1394_read(), t1394_write(), * of t1394_lock(). * The target driver can choose whether to get a callback when the * command completes, block until it completes, or poll on the return * status in the command. * For incoming (Asynchronous Receive - AR) requests, the same command * structure is used and most of the information has the same or a * similar meaning to what it does on the AT side. The major differences * are that nodeID indicates the node from which the command was sent * and broadcast informs a target driver whether the incoming request * was broadcast to everyone. */ #include #include #include #include #ifdef __cplusplus extern "C" { #endif /* * cmd1394_cmd.cmd_type * Used to select/indicate the request packet type */ typedef enum { CMD1394_ASYNCH_RD_QUAD = 0, CMD1394_ASYNCH_WR_QUAD = 1, CMD1394_ASYNCH_RD_BLOCK = 2, CMD1394_ASYNCH_WR_BLOCK = 3, CMD1394_ASYNCH_LOCK_32 = 4, CMD1394_ASYNCH_LOCK_64 = 5 } cmd1394_cmd_type_t; /* * cmd1394_cmd.flags * Used to select the request's behavior, including * how the destination address is determined, how * a large request will be broken into smaller requests, * whether the command should be resent after a * bus reset has happened, etc. */ typedef enum { CMD1394_CANCEL_ON_BUS_RESET = (1 << 0), CMD1394_OVERRIDE_ADDR = (1 << 1), CMD1394_OVERRIDE_MAX_PAYLOAD = (1 << 2), CMD1394_DISABLE_ADDR_INCREMENT = (1 << 3), CMD1394_BLOCKING = (1 << 4), CMD1394_OVERRIDE_SPEED = (1 << 5) } cmd1394_flags_t; /* * cmd1394_cmd.arg.l.lock_type * Used to select/indicate the type of lock operation * in the request. Some are supported by the 1394 spec * others (0x10000+) are supported locally in software. */ typedef enum { /* Reserved = 0x0000 */ CMD1394_LOCK_MASK_SWAP = 0x0001, CMD1394_LOCK_COMPARE_SWAP = 0x0002, CMD1394_LOCK_FETCH_ADD = 0x0003, CMD1394_LOCK_LITTLE_ADD = 0x0004, CMD1394_LOCK_BOUNDED_ADD = 0x0005, CMD1394_LOCK_WRAP_ADD = 0x0006, /* Vendor-Defined = 0x0007 */ /* Reserved = 0x0008 - 0xFFFF */ CMD1394_LOCK_BIT_AND = 0x10000, CMD1394_LOCK_BIT_OR = 0x10001, CMD1394_LOCK_BIT_XOR = 0x10002, CMD1394_LOCK_INCREMENT = 0x10003, CMD1394_LOCK_DECREMENT = 0x10004, CMD1394_LOCK_ADD = 0x10005, CMD1394_LOCK_SUBTRACT = 0x10006, CMD1394_LOCK_THRESH_ADD = 0x10007, CMD1394_LOCK_THRESH_SUBTRACT = 0x10008, CMD1394_LOCK_CLIP_ADD = 0x10009, CMD1394_LOCK_CLIP_SUBTRACT = 0x1000A } cmd1394_lock_type_t; /* Asynchronous Command (Data Quadlet) */ typedef struct cmd1394_quadlet { uint32_t quadlet_data; } cmd1394_quadlet_t; /* Asynchronous Command (Data Block) */ typedef struct cmd1394_block { mblk_t *data_block; size_t blk_length; size_t bytes_transferred; uint_t max_payload; } cmd1394_block_t; /* Asynchronous Command (Lock Cmd - 32 bit) */ typedef struct cmd1394_lock32 { uint32_t old_value; uint32_t data_value; uint32_t arg_value; uint_t num_retries; cmd1394_lock_type_t lock_type; } cmd1394_lock32_t; /* Asynchronous Command (Lock Cmd - 64 bit) */ typedef struct cmd1394_lock64 { uint64_t old_value; uint64_t data_value; uint64_t arg_value; uint_t num_retries; cmd1394_lock_type_t lock_type; } cmd1394_lock64_t; /* cmd1394_cmd: cmd1394 - common command type */ typedef struct cmd1394_cmd { int cmd_version; volatile int cmd_result; cmd1394_flags_t cmd_options; cmd1394_cmd_type_t cmd_type; void (*completion_callback)(struct cmd1394_cmd *); opaque_t cmd_callback_arg; uint64_t cmd_addr; uint_t cmd_speed; uint_t bus_generation; uint_t nodeID; uint_t broadcast; union { cmd1394_quadlet_t q; cmd1394_block_t b; cmd1394_lock32_t l32; cmd1394_lock64_t l64; } cmd_u; } cmd1394_cmd_t; /* * NOTE: Make sure CMD1394_ERR_LAST is updated if a new error code is * added. t1394_errmsg.c uses *FIRST and *LAST as bounds checks. */ /* cmd1394_cmd.result - Immediate failures (with DDI_FAILURE) */ #define CMD1394_ENULL_MBLK (-10) #define CMD1394_EMBLK_TOO_SMALL (-11) #define CMD1394_ESTALE_GENERATION (-12) #define CMD1394_EDEVICE_REMOVED (-13) #define CMD1394_EINVALID_CONTEXT (-14) #define CMD1394_EINVALID_COMMAND (-15) #define CMD1394_EUNKNOWN_ERROR (-16) #define CMD1394_NOSTATUS (-17) #define CMD1394_EFATAL_ERROR (-18) #define CMD1394_ENO_ATREQ (-19) #define CMD1394_EDEVICE_ERROR (-20) /* bad tcode or ack or... */ /* cmd1394_cmd.result - Returned with completion_callback */ #define CMD1394_CMDSUCCESS (0) #define CMD1394_EDEVICE_BUSY (-30) #define CMD1394_ERETRIES_EXCEEDED (-31) #define CMD1394_ETYPE_ERROR (-32) #define CMD1394_EDATA_ERROR (-33) #define CMD1394_EBUSRESET (-34) #define CMD1394_EADDRESS_ERROR (-35) #define CMD1394_ETIMEOUT (-36) #define CMD1394_ERSRC_CONFLICT (-37) #define CMD1394_ERR_FIRST CMD1394_CMDSUCCESS #define CMD1394_ERR_LAST CMD1394_ERSRC_CONFLICT /* Warlock directives for cmd1394 */ _NOTE(SCHEME_PROTECTS_DATA("One per call", cmd1394_cmd_t)) #ifdef __cplusplus } #endif #endif /* _SYS_1394_CMD1394_H */ /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License, Version 1.0 only * (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 1999-2002 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #ifndef _SYS_1394_H1394_H #define _SYS_1394_H1394_H /* * h1394.h * Contains the structure and error codes used to communicate * between the HAL and the rest of the 1394 Software Framework */ #include #include #include #include #include #include #include #ifdef __cplusplus extern "C" { #endif #define H1394_CLEANUP_LEVEL7 7 #define H1394_CLEANUP_LEVEL6 6 #define H1394_CLEANUP_LEVEL5 5 #define H1394_CLEANUP_LEVEL4 4 #define H1394_CLEANUP_LEVEL3 3 #define H1394_CLEANUP_LEVEL2 2 #define H1394_CLEANUP_LEVEL1 1 #define H1394_CLEANUP_LEVEL0 0 /* h1394_phy_t */ typedef enum { H1394_PHY_1995 = 0, H1394_PHY_1394A = 1 } h1394_phy_t; /* h1394_error_t */ typedef enum { H1394_LOCK_RESP_ERR = 1, H1394_POSTED_WR_ERR = 2, H1394_SELF_INITIATED_SHUTDOWN = 3, H1394_CYCLE_TOO_LONG = 4 } h1394_error_t; /* * h1394_posted_wr_err_t * The upper 16 bits contain the source id (bus/node) of the source node, * the lower 48 bits contain the address that the error occured at. */ typedef struct h1394_posted_wr_err_s { uint64_t addr; } h1394_posted_wr_err_t; /* * h1394_node_pwr_flags_t * Node power flags info */ typedef enum { H1394_NODE_PWR_FLAGS_NONE = (1 << 1), H1394_BUS_PWRD_NODES_ONE_MORE = (1 << 2), H1394_BUS_PWRD_NODES_ONE_LESS = (1 << 3), H1394_ACTIVE_NODES_ONE_MORE = (1 << 4), H1394_ACTIVE_NODES_ONE_LESS = (1 << 5) } h1394_node_pwr_flags_t; /* * h1394_addr_type_t * h1394_addr_map.addr_type */ typedef enum { H1394_ADDR_POSTED_WRITE = 0, H1394_ADDR_NORMAL = 1, H1394_ADDR_CSR = 2, H1394_ADDR_PHYSICAL = 3, H1394_ADDR_RESERVED = 4 } h1394_addr_type_t; /* h1394_mblk_t */ typedef struct h1394_mblk_s { mblk_t *curr_mblk; unsigned char *curr_offset; uint_t length; mblk_t *next_mblk; unsigned char *next_offset; } h1394_mblk_t; /* h1394_cmd_priv_t */ typedef struct h1394_cmd_priv_s { uint_t speed; uint_t ack_tstamp; uint_t recv_tstamp; uint_t bus_generation; h1394_mblk_t mblk; void *hal_overhead; } h1394_cmd_priv_t; _NOTE(SCHEME_PROTECTS_DATA("Used by a single thread", h1394_cmd_priv_s \ h1394_mblk_s::next_mblk h1394_mblk_s::next_offset)) /* h1394_evts_t */ typedef struct h1394_evts_s { uint_t hal_version; uint_t reserved; void (*shutdown)(void *hal_private); int (*send_phy_configuration_packet)(void *hal_private, cmd1394_cmd_t *phy_pkt, h1394_cmd_priv_t *cmd_private, int *result); int (*read)(void *hal_private, cmd1394_cmd_t *req, h1394_cmd_priv_t *cmd_private, int *result); int (*read_response)(void *hal_private, cmd1394_cmd_t *resp, h1394_cmd_priv_t *cmd_private, int *result); int (*write)(void *hal_private, cmd1394_cmd_t *req, h1394_cmd_priv_t *cmd_private, int *result); int (*write_response)(void *hal_private, cmd1394_cmd_t *resp, h1394_cmd_priv_t *cmd_private, int *result); void (*response_complete)(void *hal_private, cmd1394_cmd_t *resp, h1394_cmd_priv_t *cmd_private); int (*lock)(void *hal_private, cmd1394_cmd_t *req, h1394_cmd_priv_t *cmd_private, int *result); int (*lock_response)(void *hal_private, cmd1394_cmd_t *resp, h1394_cmd_priv_t *cmd_private, int *result); int (*alloc_isoch_dma)(void *hal_private, id1394_isoch_dmainfo_t *idi, void **hal_idma_handle, int *result); void (*free_isoch_dma)(void *hal_private, void *hal_isoch_dma_handle); int (*start_isoch_dma)(void *hal_private, void *hal_isoch_dma_handle, id1394_isoch_dma_ctrlinfo_t *idma_ctrlinfo, uint_t flags, int *result); void (*stop_isoch_dma)(void *hal_private, void *hal_isoch_dma_handle, int *result); int (*update_isoch_dma)(void *hal_private, void *hal_isoch_dma_handle, id1394_isoch_dma_updateinfo_t *idma_updateinfo, uint_t flags, int *result); int (*update_config_rom)(void *hal_private, void *local_buf, uint_t quadlet_count); int (*bus_reset)(void *hal_private); int (*short_bus_reset)(void *hal_private); int (*set_contender_bit)(void *hal_private); int (*set_root_holdoff_bit)(void *hal_private); int (*set_gap_count)(void *hal_private, uint_t gap_count); int (*csr_read)(void *hal_private, uint_t offset, uint32_t *data); int (*csr_write)(void *hal_private, uint_t offset, uint32_t data); int (*csr_cswap32)(void *hal_private, uint_t generation, uint_t offset, uint32_t compare, uint32_t swap, uint32_t *old); int (*physical_arreq_enable_set)(void *hal_private, uint64_t mask, uint_t generation); int (*physical_arreq_enable_clr)(void *hal_private, uint64_t mask, uint_t generation); void (*node_power_state_change)(void *hal_private, h1394_node_pwr_flags_t nodeflags); } h1394_evts_t; /* Version value for h1394_evts_t */ #define H1394_EVTS_V1 1 #define HAL_CALL(hal) (hal)->halinfo.hal_events /* Result field returned by read/write/lock requests */ #define H1394_STATUS_NO_ERROR 0 #define H1394_STATUS_INVALID_BUSGEN 1 #define H1394_STATUS_EMPTY_TLABEL 2 #define H1394_STATUS_NOMORE_SPACE 3 #define H1394_STATUS_INTERNAL_ERROR 4 /* h1394_addr_map_t */ typedef struct h1394_addr_map_s { uint64_t address; uint64_t length; h1394_addr_type_t addr_type; } h1394_addr_map_t; /* h1394_halinfo_t */ typedef struct h1394_halinfo_s { void *hal_private; dev_info_t *dip; h1394_evts_t hal_events; ddi_iblock_cookie_t hw_interrupt; /* Buffer attributes */ ddi_device_acc_attr_t acc_attr; ddi_dma_attr_t dma_attr; /* Type of PHY on HAL */ h1394_phy_t phy; uint_t hal_overhead; /* in bytes */ uint32_t bus_capabilities; uint64_t guid; uint32_t node_capabilities; /* * The maximum value generation can have before * it rolls over (inclusive) */ uint_t max_generation; /* Description of the 1394 Address Space */ h1394_addr_map_t *addr_map; uint_t addr_map_num_entries; /* Description of the reserved spaces */ h1394_addr_map_t *resv_map; uint_t resv_map_num_entries; } h1394_halinfo_t; /* Calls to Services layer during HAL driver _init() and _fini() */ int h1394_init(struct modlinkage *modlp); void h1394_fini(struct modlinkage *modlp); /* Calls to Services layer during HAL driver attach/detach */ int h1394_attach(h1394_halinfo_t *halinfo, ddi_attach_cmd_t cmd, void **sl_private); int h1394_detach(void **sl_private, ddi_detach_cmd_t cmd); /* Calls to Services layer during HW interrupt processing */ void h1394_cmd_is_complete(void *sl_private, cmd1394_cmd_t *command_id, uint32_t cmd_type, int status); /* Command types (passed to h1394_command_is_complete) */ #define H1394_AT_REQ 0 #define H1394_AT_RESP 1 /* Command statuses (passed to h1394_command_is_complete) */ #define H1394_CMD_SUCCESS 0x00 /* ack_complete */ #define H1394_CMD_ETIMEOUT 0x01 /* evt_missing_ack */ #define H1394_CMD_EBUSRESET 0x02 /* evt_flushed */ #define H1394_CMD_EDEVICE_BUSY 0x03 /* ack_busy_? */ #define H1394_CMD_EDATA_ERROR 0x04 /* ack_data_error */ #define H1394_CMD_ETYPE_ERROR 0x05 /* ack_type_error */ #define H1394_CMD_EADDR_ERROR 0x06 /* resp_address_error */ #define H1394_CMD_ERSRC_CONFLICT 0x07 /* resp_conflict_error */ #define H1394_CMD_EDEVICE_POWERUP 0x08 /* ack_tardy */ #define H1394_CMD_EDEVICE_ERROR 0x09 /* device error */ #define H1394_CMD_EUNKNOWN_ERROR 0x0A /* unknown error type */ void h1394_bus_reset(void *sl_private, void **selfid_buf_addr); void h1394_self_ids(void *sl_private, void *selfid_buf_addr, uint32_t selfid_size, uint32_t node_id, uint32_t generation_count); void h1394_write_request(void *sl_private, cmd1394_cmd_t *req); void h1394_read_request(void *sl_private, cmd1394_cmd_t *req); void h1394_lock_request(void *sl_private, cmd1394_cmd_t *req); int h1394_alloc_cmd(void *sl_private, uint_t flags, cmd1394_cmd_t **cmdp, h1394_cmd_priv_t **hal_priv_ptr); /* Flags for h1394_alloc_cmd() */ #define H1394_ALLOC_CMD_SLEEP 0x00000000 /* can sleep allocating */ #define H1394_ALLOC_CMD_NOSLEEP 0x00000001 /* don't sleep allocating */ int h1394_free_cmd(void *sl_private, cmd1394_cmd_t **cmdp); int h1394_ioctl(void *sl_private, int cmd, intptr_t arg, int mode, cred_t *cred_p, int *rval_p); void h1394_phy_packet(void *sl_private, uint32_t *packet_data, uint_t quadlet_count, uint_t timestamp); void h1394_error_detected(void *sl_private, h1394_error_t type, void *arg); #ifdef __cplusplus } #endif #endif /* _SYS_1394_H1394_H */ /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License, Version 1.0 only * (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 (c) 1999-2000 by Sun Microsystems, Inc. * All rights reserved. */ #ifndef _SYS_1394_ID1394_H #define _SYS_1394_ID1394_H /* * id1394.h * Contains enums and structures used for managing a local isochronous * DMA resource. */ #include #include #include #include #include #ifdef __cplusplus extern "C" { #endif /* * t1394_alloc_isoch_dma() is used to allocate a local isochronous * DMA resource for receiving or for transmitting isochronous data. * Upon successful allocation, the 1394 Framework returns a handle * of the type shown below. The target driver passes this handle back to * the 1394 Framework for all subsequent t1394_*_isoch_dma() calls * used to control the allocated resource. */ typedef struct isoch_dma_handle *t1394_isoch_dma_handle_t; /* * Target drivers use the id1394_isoch_dma_options_t enumerated type to * specify to t1394_alloc_isoch_dma() the desired characteristics of * the requested local isochronous DMA resource. * ID1394_TALK specifies an isochronous transmit DMA resource. * ID1394_LISTEN_PKT_MODE specifies an isochronous receive DMA resource in * which each packet is received into its own (set of) buffer(s). * ID1394_LISTEN_BUF_MODE specifies an isochronous receive DMA resource in * which packets may be concatenated into a single buffer. * ID1394_RECV_HEADERS specifies that isochronous packet header data for * received isochronous packets are stored into the data buffers along * with the packet data (otherwise the packet header is removed). */ typedef enum { ID1394_TALK = (1 << 0), ID1394_LISTEN_PKT_MODE = (1 << 1), ID1394_LISTEN_BUF_MODE = (1 << 2), ID1394_RECV_HEADERS = (1 << 3) } id1394_isoch_dma_options_t; /* * Enumerated type id1394_isoch_dma_stopped_t is a return argument to * the target's isoch_dma_stopped() callback. * Under a variety of circumstances, the local DMA resource may stop running. * If this occurs (independently of a target driver`s direct call to * t1394_stop_isoch_dma()), the target driver's isoch_dma_stopped callback is * invoked. In this callback, the reason for the stop is indicated in the * id1394_isoch_dma_stopped_t enumerated type. ID1394_DONE indicates the * isochronous DMA resource stopped because it reached the "end." * ID1394_FAIL indicates the isochronous DMA resource encountered an error. */ typedef enum { ID1394_DONE = 1, ID1394_FAIL = 2 } id1394_isoch_dma_stopped_t; /* * Targets use id1394_isoch_dmainfo_t with t1394_alloc_isoch_dma() to specify * the desired characteristics of the local isochronous DMA resource. * * ixlp * is the kernel virtual address of the first IXL program command. * For IXL program command structures, see ixl1394.h. * channel_num * is the isochronous channel number (0-63) for the allocated local * isochronous DMA resource. For an isochronous receive DMA resource, * only packets with the specified channel number are received into the * provided buffers. For an isochronous transmit DMA resource, the * 1394 Framework constructs isochronous transmit packet headers using the * specified channel number. * default_tag * are the tag bits for the local isochronous DMA resource. * For an isochronous receive DMA resource, only packets with the specified * tag bits are received into the provided buffers. For an isochronous * transmit DMA resource, the 1394 Framework constructs isochronous * transmit packet headers using the specified tag bits. * default_sync * are the sync bits for the local isochronous DMA resource. Usage is * similar to that of default_tag above. * it_speed * is used only for an isochronous transmit resource and indicates the * speed at which the 1394 Framework shall transmit packets. For valid * speeds, see ieee1394.h. * global_callback_arg * is the argument the 1394 Framework provides to the target when invoking * a callback specified in an ixl1394_callback_t IXL command or an IXL * program. Target drivers can use this to track state or any other * information. See ixl1394.h for IXL command info. * it_default_skip * is used for isochronous transmit DMA resources only and specifies the * default skip mode for the resource. See ixl1394.h for valid skip modes. * it_default_skiplabel * is used for isochronous transmit DMA resources only, and when * it_default_skip is IXL1394_SKIP_TO_LABEL. It contains a pointer to * the targetted IXL Label command. * idma_options * is used to specify the overall transmit or receive characteristics * of the requested local isochronous DMA resource. * isoch_dma_stopped * is the target driver's callback routine the 1394 Framework is to * invoke if the local isochronous DMA resource stops. * idma_evt_arg * is the target driver's callback argument to be handed back to the target * driver when the 1394 Framework invokes the isoch_dma_stopped() callback. */ typedef struct id1394_isoch_dmainfo_s { ixl1394_command_t *ixlp; /* 1st IXL command */ uint_t channel_num; /* isoch channel */ uint_t default_tag; /* tag */ uint_t default_sync; /* sync */ uint_t it_speed; /* speed - xmit only */ void *global_callback_arg; ixl1394_skip_t it_default_skip; /* skip - xmit only */ ixl1394_command_t *it_default_skiplabel; id1394_isoch_dma_options_t idma_options; /* I/O type */ void (*isoch_dma_stopped)(t1394_isoch_dma_handle_t t1394_idma_hdl, opaque_t idma_evt_arg, id1394_isoch_dma_stopped_t idma_stop_args); opaque_t idma_evt_arg; } id1394_isoch_dmainfo_t; /* * Target drivers supply the id1394_isoch_dma_ctrlinfo_t structure to the * t1394_start_isoch_dma() call to indicate the cycle at which the local * isochronous DMA resource is to start receiving or transmitting packets. */ typedef struct id1394_isoch_dma_ctrlinfo_s { uint_t start_cycle; } id1394_isoch_dma_ctrlinfo_t; /* * t1394_start_isoch_dma() flags. * ID1394_START_ON_CYCLE - if specified, this flag indicates that the local * isochronous DMA resource is to start receiving or transmitting packets * at the cycle time specified in id1394_isoch_dma_ctrlinfo_t. * If not specified, the isochronous DMA resource starts receiving or * transmitting packets as soon as possible. */ #define ID1394_START_ON_CYCLE 0x00000001 /* start on specified cycle */ /* * Target drivers use the id1394_isoch_dma_updateinfo_t structure to provide * information to t1394_update_isoch_dma(), which dynamically updates an IXL * program for an allocated local isochronous DMA resource. See ixl1394.h * for information on IXL program commands. * temp_ixlp * points to the first new IXL command used to update an existing IXL * command. * orig_ixlp * points to the original IXL command to be updated. * ixl_count * is the number of IXL commands to be updated. */ typedef struct id1394_isoch_dma_updateinfo_s { ixl1394_command_t *temp_ixlp; /* first new IXL cmd */ ixl1394_command_t *orig_ixlp; /* first updated IXL cmd */ uint_t ixl_count; /* length of update chain */ } id1394_isoch_dma_updateinfo_t; #ifdef __cplusplus } #endif #endif /* _SYS_1394_ID1394_H */ /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License, Version 1.0 only * (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 (c) 1999-2000 by Sun Microsystems, Inc. * All rights reserved. */ #ifndef _SYS_1394_IEEE1212_H #define _SYS_1394_IEEE1212_H /* * ieee1212.h * This file contains various defines for config rom entries */ #ifdef __cplusplus extern "C" { #endif #define IEEE1212_NODE_CAP_QUAD 2 /* node capability */ #define IEEE1212_ROOT_DIR_QUAD 5 /* root dir quad */ #define IEEE1212_DIR_LEN(data) (((data) >> 16) & 0xFFFF) #define IEEE1212_DIR_CRC(data) ((uint16_t)((data) & 0xFFFF)) #define CONFIG_ROM_GEN(rom_ptr) \ (((rom_ptr)[IEEE1212_NODE_CAP_QUAD] & 0x000000F0) >> 4) #define CFGROM_ROOT_DIR(cfgrom) (&(cfgrom)[IEEE1212_ROOT_DIR_QUAD]) #define CFGROM_DIR_LEN(dirptr) (((dirptr)[0] >> 16) & 0xFF) #define CFGROM_TYPE_KEY_VALUE(q, t, k, v) { \ (t) = (((q) & IEEE1212_KEY_TYPE_MASK) >> IEEE1212_KEY_TYPE_SHIFT); \ (k) = (((q) & IEEE1212_KEY_VALUE_MASK) >> IEEE1212_KEY_VALUE_SHIFT); \ (v) = (q) & IEEE1212_ENTRY_VALUE_MASK; \ } /* Key types */ #define IEEE1212_IMMEDIATE_TYPE 0 #define IEEE1212_CSR_OFFSET_TYPE 1 #define IEEE1212_LEAF_TYPE 2 #define IEEE1212_DIRECTORY_TYPE 3 /* Key values */ #define IEEE1212_TEXTUAL_DESCRIPTOR 0x01 #define IEEE1212_BUS_DEPENDENT_INFO 0x02 #define IEEE1212_MODULE_VENDOR_ID 0x03 #define IEEE1212_MODULE_HW_VERSION 0x04 #define IEEE1212_MODULE_SPEC_ID 0x05 #define IEEE1212_MODULE_SW_VERSION 0x06 #define IEEE1212_MODULE_DEPENDENT_INFO 0x07 #define IEEE1212_NODE_VENDOR_ID 0x08 #define IEEE1212_NODE_HW_VERSION 0x09 #define IEEE1212_NODE_SPEC_ID 0x0A #define IEEE1212_NODE_SW_VERSION 0x0B #define IEEE1212_NODE_CAPABILITIES 0x0C #define IEEE1212_NODE_UNIQUE_ID 0x0D #define IEEE1212_NODE_UNITS_EXTENT 0x0E #define IEEE1212_NODE_MEMORY_EXTENT 0x0F #define IEEE1212_NODE_DEPENDENT_INFO 0x10 #define IEEE1212_UNIT_DIRECTORY 0x11 #define IEEE1212_UNIT_SPEC_ID 0x12 #define IEEE1212_UNIT_SW_VERSION 0x13 #define IEEE1212_UNIT_DEPENDENT_INFO 0x14 #define IEEE1212_UNIT_LOCATION 0x15 #define IEEE1212_UNIT_POLL_MASK 0x16 #define IEEE1212_KEY_TYPE_MASK 0xC0000000 #define IEEE1212_KEY_TYPE_SHIFT 30 #define IEEE1212_KEY_VALUE_MASK 0x3F000000 #define IEEE1212_KEY_VALUE_SHIFT 24 #define IEEE1212_ENTRY_VALUE_MASK 0x00FFFFFF #define IEEE1212_NODE_CAPABILITIES_MASK 0x0000FFFF #ifdef __cplusplus } #endif #endif /* _SYS_1394_IEEE1212_H */ /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License, Version 1.0 only * (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 (c) 1999-2000 by Sun Microsystems, Inc. * All rights reserved. */ #ifndef _SYS_1394_IEEE1394_H #define _SYS_1394_IEEE1394_H /* * ieee1394.h * This file contains various defines that go with IEEE 1394 */ #ifdef __cplusplus extern "C" { #endif /* * IEEE1394_MAX_NODES defines the maximum number of nodes * that can be addressed on a single 1394 bus. There are * a 63 physical nodes that can be present and 1 broadcast * node id. The range of 1394 nodeid's are * 0 ... (IEEE1394_MAX_NODES - 1) */ #define IEEE1394_MAX_NODES 64 /* The node id for broadcast writes */ #define IEEE1394_BROADCAST_NODEID 63 /* Maximum number of ports per node */ #define IEEE1394_MAX_NUM_PORTS 16 #define IEEE1394_BUS_NUM_MASK 0x0000FFC0 #define IEEE1394_LOCAL_BUS 0x3FF #define IEEE1394_NODE_NUM_MASK 0x0000003F #define IEEE1394_NODE_NUM(DATA) ((DATA) & IEEE1394_NODE_NUM_MASK) #define IEEE1394_BUS_CYCLES_PER_SEC 8000 /* IEEE 1394 Bus related definitions */ #define IEEE1394_ADDR_NODE_ID_MASK 0xFFFF000000000000 #define IEEE1394_ADDR_NODE_ID_SHIFT 48 #define IEEE1394_ADDR_NODE_ID(ADDR) \ (((ADDR) & IEEE1394_ADDR_NODE_ID_MASK) >> \ IEEE1394_ADDR_NODE_ID_SHIFT) #define IEEE1394_ADDR_BUS_ID_MASK 0xFFC0000000000000 #define IEEE1394_ADDR_BUS_ID_SHIFT 54 #define IEEE1394_ADDR_BUS_ID(ADDR) \ (((ADDR) & IEEE1394_ADDR_BUS_ID_MASK) >> \ IEEE1394_ADDR_BUS_ID_SHIFT) #define IEEE1394_ADDR_PHY_ID_MASK 0x003F000000000000 #define IEEE1394_ADDR_PHY_ID_SHIFT 48 #define IEEE1394_ADDR_PHY_ID(ADDR) \ (((ADDR) & IEEE1394_ADDR_PHY_ID_MASK) >> \ IEEE1394_ADDR_PHY_ID_SHIFT) #define IEEE1394_ADDR_OFFSET_MASK 0x0000FFFFFFFFFFFF /* IEEE 1394 data sizes */ #define IEEE1394_QUADLET (sizeof (uint32_t)) #define IEEE1394_OCTLET (sizeof (uint64_t)) /* Still need to look at these */ /* TCODES - packet transaction codes (as defined in 1394-1995 6.2.4.5) */ #define IEEE1394_TCODE_WRITE_QUADLET 0x0 #define IEEE1394_TCODE_WRITE_BLOCK 0x1 #define IEEE1394_TCODE_WRITE_RESP 0x2 #define IEEE1394_TCODE_RES1 0x3 #define IEEE1394_TCODE_READ_QUADLET 0x4 #define IEEE1394_TCODE_READ_BLOCK 0x5 #define IEEE1394_TCODE_READ_QUADLET_RESP 0x6 #define IEEE1394_TCODE_READ_BLOCK_RESP 0x7 #define IEEE1394_TCODE_CYCLE_START 0x8 #define IEEE1394_TCODE_LOCK 0x9 #define IEEE1394_TCODE_ISOCH 0xA #define IEEE1394_TCODE_LOCK_RESP 0xB #define IEEE1394_TCODE_RES2 0xC #define IEEE1394_TCODE_RES3 0xD #define IEEE1394_TCODE_PHY 0xE #define IEEE1394_TCODE_RES4 0xF #define IEEE1394_RESP_COMPLETE 0x0 #define IEEE1394_RESP_CONFLICT_ERROR 0x4 #define IEEE1394_RESP_DATA_ERROR 0x5 #define IEEE1394_RESP_TYPE_ERROR 0x6 #define IEEE1394_RESP_ADDRESS_ERROR 0x7 #define IEEE1394_ISOCH_HDR_QUAD_SZ 3 /* Self ID packet definitions */ #define IEEE1394_SELFID_PCKT_ID_MASK 0xC0000000 #define IEEE1394_SELFID_PCKT_ID_SHIFT 30 #define IEEE1394_SELFID_PCKT_ID_VALID 0x2 #define IEEE1394_SELFID_ISVALID(S_PKT) \ (~((S_PKT)->spkt_data ^ (S_PKT)->spkt_inverse) ? 0 : 1) #define IEEE1394_SELFID_PHYID_MASK 0x3F000000 #define IEEE1394_SELFID_PHYID_SHIFT 24 #define IEEE1394_SELFID_PHYID(S_PKT) \ (((S_PKT)->spkt_data & IEEE1394_SELFID_PHYID_MASK) >> \ IEEE1394_SELFID_PHYID_SHIFT) /* SelfID PKT #0 */ #define IEEE1394_SELFID_L_MASK 0x00400000 #define IEEE1394_SELFID_L_SHIFT 22 #define IEEE1394_SELFID_ISLINKON(S_PKT) \ (((S_PKT)->spkt_data & IEEE1394_SELFID_L_MASK) >> \ IEEE1394_SELFID_L_SHIFT) #define IEEE1394_SELFID_GAP_CNT_MASK 0x003F0000 #define IEEE1394_SELFID_GAP_CNT_SHIFT 16 #define IEEE1394_SELFID_GAP_CNT(S_PKT) \ (((S_PKT)->spkt_data & IEEE1394_SELFID_GAP_CNT_MASK) >> \ IEEE1394_SELFID_GAP_CNT_SHIFT) #define IEEE1394_SELFID_SP_MASK 0x0000C000 #define IEEE1394_SELFID_SP_SHIFT 14 #define IEEE1394_SELFID_DEL_MASK (0x00003000) #define IEEE1394_SELFID_DEL_SHIFT 12 #define IEEE1394_SELFID_DELAY(S_PKT) \ (((S_PKT)->spkt_data & IEEE1394_SELFID_DEL_MASK) >> \ IEEE1394_SELFID_DEL_SHIFT) #define IEEE1394_SELFID_C_MASK 0x00000800 #define IEEE1394_SELFID_C_SHIFT 11 #define IEEE1394_SELFID_ISCONTENDER(S_PKT) \ (((S_PKT)->spkt_data & IEEE1394_SELFID_C_MASK) >> \ IEEE1394_SELFID_C_SHIFT) #define IEEE1394_SELFID_PWR_MASK 0x00000700 #define IEEE1394_SELFID_PWR_SHIFT 8 #define IEEE1394_SELFID_POWER(S_PKT) \ (((S_PKT)->spkt_data & IEEE1394_SELFID_PWR_MASK) >> \ IEEE1394_SELFID_PWR_SHIFT) #define IEEE1394_SELFID_PORT_TO_CHILD 0x3 #define IEEE1394_SELFID_PORT_TO_PARENT 0x2 #define IEEE1394_SELFID_PORT_NOT_CONNECTED 0x1 #define IEEE1394_SELFID_PORT_NO_PORT 0x0 #define IEEE1394_SELFID_I_MASK 0x00000002 #define IEEE1394_SELFID_I_SHIFT 1 #define IEEE1394_SELFID_INITIATED_RESET(S_PKT) \ (((S_PKT)->spkt_data & IEEE1394_SELFID_I_MASK) >> \ IEEE1394_SELFID_I_SHIFT) #define IEEE1394_SELFID_M_MASK 0x00000001 #define IEEE1394_SELFID_M_SHIFT 0 #define IEEE1394_SELFID_ISMORE(S_PKT) \ (((S_PKT)->spkt_data & IEEE1394_SELFID_M_MASK) >> \ IEEE1394_SELFID_M_SHIFT) #define IEEE1394_SELFID_PORT_OFFSET_FIRST 6 /* SelfID PKT #1 (n=0) */ #define IEEE1394_SELFID_N_MASK 0x00700000 #define IEEE1394_SELFID_N_SHIFT 20 #define IEEE1394_SELFID_PKT_NUM(S_PKT) \ (((S_PKT)->spkt_data & IEEE1394_SELFID_N_MASK) >> \ IEEE1394_SELFID_N_SHIFT) #define IEEE1394_SELFID_PORT_OFFSET_OTHERS 16 /* PHY Config Packet definitions */ #define IEEE1394_PHY_CONFIG_T_BIT_MASK 0x00400000 #define IEEE1394_PHY_CONFIG_T_BIT_SHIFT 22 #define IEEE1394_PHY_CONFIG_GAP_CNT_MASK 0x003F0000 #define IEEE1394_PHY_CONFIG_GAP_CNT_SHIFT 16 #define IEEE1394_PHY_CONFIG_R_BIT_MASK 0x00800000 #define IEEE1394_PHY_CONFIG_R_BIT_SHIFT 23 #define IEEE1394_PHY_CONFIG_ROOT_HOLD_MASK 0x3F000000 #define IEEE1394_PHY_CONFIG_ROOT_HOLD_SHIFT 24 /* * CSR Registers and register fields. */ /* CSR Register Addresses (IEEE1394-1995 8.3.2.2) */ #define IEEE1394_CSR_STATE_CLEAR 0xFFFFF0000000 #define IEEE1394_CSR_STATE_SET 0xFFFFF0000004 #define IEEE1394_CSR_NODE_IDS 0xFFFFF0000008 #define IEEE1394_CSR_RESET_START 0xFFFFF000000C #define IEEE1394_CSR_SPLIT_TIMEOUT_HI 0xFFFFF0000018 #define IEEE1394_CSR_SPLIT_TIMEOUT_LO 0xFFFFF000001C #define IEEE1394_CSR_ARG_HI 0xFFFFF0000020 #define IEEE1394_CSR_ARG_LO 0xFFFFF0000024 #define IEEE1394_CSR_TEST_START 0xFFFFF0000028 #define IEEE1394_CSR_TEST_STATUS 0xFFFFF000002C /* Optional Register Addresses */ #define IEEE1394_CSR_INTERRUPT_TARGET 0xFFFFF0000050 #define IEEE1394_CSR_INTERRUPT_MASK 0xFFFFF0000054 #define IEEE1394_CSR_CLOCK_VALUE 0xFFFFF0000058 #define IEEE1394_CSR_CLOCK_VALUE_SZ 0x28 #define IEEE1394_CSR_MESSAGE_REQUEST 0xFFFFF0000080 #define IEEE1394_CSR_MESSAGE_REQUEST_SZ 0x80 /* Serial Bus CSR Register Addresss (IEEE1394-1995 8.3.2.3) */ #define IEEE1394_SCSR_CYCLE_TIME 0xFFFFF0000200 #define IEEE1394_SCSR_BUS_TIME 0xFFFFF0000204 #define IEEE1394_SCSR_PWRFAIL_IMMINENT 0xFFFFF0000208 #define IEEE1394_SCSR_PWRSRC 0xFFFFF000020C #define IEEE1394_SCSR_BUSY_TIMEOUT 0xFFFFF0000210 #define IEEE1394_SCSR_BUSMGR_ID 0xFFFFF000021C #define IEEE1394_SCSR_BANDWIDTH_AVAIL 0xFFFFF0000220 #define IEEE1394_SCSR_CHANS_AVAIL_HI 0xFFFFF0000224 #define IEEE1394_SCSR_CHANS_AVAIL_LO 0xFFFFF0000228 /* Config ROM Address */ #define IEEE1394_CONFIG_ROM_ADDR 0xFFFFF0000400 #define IEEE1394_CONFIG_ROM_SZ 0x400 #define IEEE1394_CONFIG_ROM_QUAD_SZ 0x100 /* Unit CSR Register Addresses */ #define IEEE1394_UCSR_TOPOLOGY_MAP 0xFFFFF0001000 #define IEEE1394_UCSR_TOPOLOGY_MAP_SZ 0x400 #define IEEE1394_UCSR_SPEED_MAP 0xFFFFF0002000 #define IEEE1394_UCSR_SPEED_MAP_SZ 0x1000 /* Boundary for "reserved" CSR registers */ #define IEEE1394_UCSR_RESERVED_BOUNDARY 0xFFFFF0010000 #define IEEE1394_CSR_OFFSET_MASK 0x00000000FFFF /* 1394 Bus Speeds */ #define IEEE1394_S100 0 #define IEEE1394_S200 1 #define IEEE1394_S400 2 #define IEEE1394_S800 3 #define IEEE1394_S1600 4 #define IEEE1394_S3200 5 /* IEEE 1394 Bandwidth bounds */ #define IEEE1394_BANDWIDTH_MIN 0 #define IEEE1394_BANDWIDTH_MAX 0x1333 /* Speed Map specific defines */ #define IEEE1394_SPEED_MAP_CRC_LEN 0x03F1 #define IEEE1394_SPEED_MAP_LEN_MASK 0x0000FFFF #define IEEE1394_SPEED_MAP_LEN_SHIFT 16 #define IEEE1394_SPEED_MAP_DATA_LEN 0x0FBE /* Topology Map specific defines */ #define IEEE1394_TOP_MAP_LEN_MASK 0x0000FFFF #define IEEE1394_TOP_MAP_LEN_SHIFT 16 /* Config ROM specific defines */ #define IEEE1394_CFG_ROM_CRC_VALUE_MASK 0x0000FFFF #define IEEE1394_CFG_ROM_CRC_LEN_SHIFT 16 #define IEEE1394_CFG_ROM_CRC_LEN_MASK 0xFF #define IEEE1394_CFG_ROM_LEN_SHIFT 16 /* CRC16 defines */ #define IEEE1394_CRC16_MASK 0xFFFF /* Bit positions in the STATE register */ #define IEEE1394_CSR_STATE_CMSTR 0x00000100 #define IEEE1394_CSR_STATE_DREQ 0x00000040 #define IEEE1394_CSR_STATE_ABDICATE 0x00000400 /* Positions in the BUS_INFO_BLOCK */ #define IEEE1394_BIB_LNK_SPD_MASK 0x00000007 #define IEEE1394_BIB_LNK_SPD_SHIFT 0 #define IEEE1394_BIB_GEN_MASK 0x000000F0 #define IEEE1394_BIB_GEN_SHIFT 4 #define IEEE1394_BIB_MROM_MASK 0x00000300 #define IEEE1394_BIB_MROM_SHIFT 8 #define IEEE1394_BIB_IRMC_MASK 0x80000000 #define IEEE1394_BIB_IRMC_SHIFT 31 #define IEEE1394_BIB_BMC_MASK 0x10000000 #define IEEE1394_BIB_BMC_SHIFT 28 #define IEEE1394_BIB_CMC_MASK 0x40000000 #define IEEE1394_BIB_CMC_SHIFT 30 #define IEEE1394_BIB_MAXREC_MASK 0x0000F000 #define IEEE1394_BIB_MAXREC_SHIFT 12 #define IEEE1394_BIB_QUAD_SZ 5 #define IEEE1394_BIB_SZ 0x14 /* Bus Manager specific defines */ #define IEEE1394_BM_IRM_TIMEOUT 625000 #define IEEE1394_BM_INCUMBENT_TIMEOUT 125000 #ifdef __cplusplus } #endif #endif /* _SYS_1394_IEEE1394_H */ /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License, Version 1.0 only * (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 (c) 1999-2001 by Sun Microsystems, Inc. * All rights reserved. */ #ifndef _SYS_1394_IXL1394_H #define _SYS_1394_IXL1394_H /* * ixl1394.h * Contains all defines and structures necessary for Isochronous Transfer * Language (IXL) programs. IXL programs are used to specify the transmission * or receipt of isochronous packets for an isochronous channel. */ #ifdef __cplusplus extern "C" { #endif #include /* * Error codes for IXL program compilation and dynamic update * Comments indicate which are source of error * NOTE: Make sure IXL1394_COMP_ERR_LAST is updated if a new error code is * added. t1394_errmsg.c uses *FIRST and *LAST as bounds checks. */ #define IXL1394_EMEM_ALLOC_FAIL (-301) /* compile only */ #define IXL1394_EBAD_IXL_OPCODE (-302) /* compile only */ #define IXL1394_EFRAGMENT_OFLO (-303) /* compile only */ #define IXL1394_ENO_DATA_PKTS (-304) /* compile only */ #define IXL1394_EMISPLACED_RECV (-305) /* compile only */ #define IXL1394_EMISPLACED_SEND (-306) /* compile only */ #define IXL1394_EPKT_HDR_MISSING (-307) /* compile & update */ #define IXL1394_ENULL_BUFFER_ADDR (-308) /* compile only */ #define IXL1394_EPKTSIZE_MAX_OFLO (-309) /* compile & update */ #define IXL1394_EPKTSIZE_RATIO (-310) /* compile only */ #define IXL1394_EUNAPPLIED_SET_CMD (-311) /* compile only */ #define IXL1394_EDUPLICATE_SET_CMD (-312) /* compile only */ #define IXL1394_EJUMP_NOT_TO_LABEL (-313) /* compile & update */ #define IXL1394_EUPDATE_DISALLOWED (-314) /* compile & update */ #define IXL1394_EBAD_SKIPMODE (-315) /* compile & update */ #define IXL1394_EWRONG_XR_CMD_MODE (-316) /* compile only */ #define IXL1394_EINTERNAL_ERROR (-317) /* compile & update */ #define IXL1394_ENOT_IMPLEMENTED (-318) /* compile only */ #define IXL1394_EOPCODE_MISMATCH (-319) /* update only */ #define IXL1394_EOPCODE_DISALLOWED (-320) /* update only */ #define IXL1394_EBAD_SKIP_LABEL (-321) /* update only */ #define IXL1394_EXFER_BUF_MISSING (-322) /* update only */ #define IXL1394_EXFER_BUF_CNT_DIFF (-323) /* update only */ #define IXL1394_EORIG_IXL_CORRUPTED (-324) /* update only */ #define IXL1394_ECOUNT_MISMATCH (-325) /* update only */ #define IXL1394_EPRE_UPD_DMALOST (-326) /* update only */ #define IXL1394_EPOST_UPD_DMALOST (-327) /* update only */ #define IXL1394_ERISK_PROHIBITS_UPD (-328) /* update only */ #define IXL1394_COMP_ERR_FIRST IXL1394_EMEM_ALLOC_FAIL #define IXL1394_COMP_ERR_LAST IXL1394_ERISK_PROHIBITS_UPD #define IXL1394_ENO_DMA_RESRCS (-200) /* * IXL command opcodes * * IXL opcodes contain a unique opcode identifier and various flags to * speed compilation. */ /* 5 flag bits at high end of opcode field. */ #define IXL1394_OPF_MASK 0xF800 #define IXL1394_OPF_UPDATE 0x8000 /* cmd update allowed during exec */ #define IXL1394_OPF_ONRECV 0x4000 /* cmd is allowed on recv */ #define IXL1394_OPF_ONXMIT 0x2000 /* cmd is allowed on xmit */ #define IXL1394_OPF_ENDSXFER 0x1000 /* cmd ends cur pkt xfer build */ #define IXL1394_OPF_ISXFER 0x0800 /* cmd is data transfer command */ /* Useful flag composites. */ #define IXL1394_OPF_ONXFER (IXL1394_OPF_ONXMIT | IXL1394_OPF_ONRECV) #define IXL1394_OPF_ONXFER_ENDS (IXL1394_OPF_ONXFER | IXL1394_OPF_ENDSXFER) #define IXL1394_OPF_ONRECV_ENDS (IXL1394_OPF_ONRECV | IXL1394_OPF_ENDSXFER) #define IXL1394_OPF_ONXMIT_ENDS (IXL1394_OPF_ONXMIT | IXL1394_OPF_ENDSXFER) /* 2 type bits whose contents are interpreted based on isxr setting */ #define IXL1394_OPTY_MASK 0x0600 /* type bits when isxfer == 0 */ #define IXL1394_OPTY_OTHER 0x0000 /* type bits when isxr == 1 */ #define IXL1394_OPTY_XFER_PKT (0x0000 | IXL1394_OPF_ISXFER) #define IXL1394_OPTY_XFER_PKT_ST (0x0200 | IXL1394_OPF_ISXFER) #define IXL1394_OPTY_XFER_BUF_ST (0x0400 | IXL1394_OPF_ISXFER) #define IXL1394_OPTY_XFER_SPCL_ST (0x0600 | IXL1394_OPF_ISXFER) /* * IXL Command Opcodes. */ #define IXL1394_OP_LABEL (1 | IXL1394_OPTY_OTHER | IXL1394_OPF_ONXFER_ENDS) #define IXL1394_OP_JUMP (2 | IXL1394_OPTY_OTHER | IXL1394_OPF_ONXFER_ENDS) #define IXL1394_OP_CALLBACK (3 | IXL1394_OPTY_OTHER | IXL1394_OPF_ONXFER) #define IXL1394_OP_RECV_PKT (4 | IXL1394_OPTY_XFER_PKT | IXL1394_OPF_ONRECV) #define IXL1394_OP_RECV_PKT_ST \ (5 | IXL1394_OPTY_XFER_PKT_ST | IXL1394_OPF_ONRECV_ENDS) #define IXL1394_OP_RECV_BUF \ (6 | IXL1394_OPTY_XFER_BUF_ST | IXL1394_OPF_ONRECV_ENDS) #define IXL1394_OP_SEND_PKT (7 | IXL1394_OPTY_XFER_PKT | IXL1394_OPF_ONXMIT) #define IXL1394_OP_SEND_PKT_ST \ (8 | IXL1394_OPTY_XFER_PKT_ST | IXL1394_OPF_ONXMIT_ENDS) #define IXL1394_OP_SEND_PKT_WHDR_ST \ (9 | IXL1394_OPTY_XFER_PKT_ST | IXL1394_OPF_ONXMIT_ENDS) #define IXL1394_OP_SEND_BUF \ (10 | IXL1394_OPTY_XFER_BUF_ST | IXL1394_OPF_ONXMIT_ENDS) #define IXL1394_OP_SEND_HDR_ONLY \ (12 | IXL1394_OPTY_XFER_SPCL_ST | IXL1394_OPF_ONXMIT_ENDS) #define IXL1394_OP_SEND_NO_PKT \ (13 | IXL1394_OPTY_XFER_SPCL_ST | IXL1394_OPF_ONXMIT_ENDS) #define IXL1394_OP_STORE_TIMESTAMP \ (14 | IXL1394_OPTY_OTHER | IXL1394_OPF_ONXFER) #define IXL1394_OP_SET_TAGSYNC \ (15 | IXL1394_OPTY_OTHER | IXL1394_OPF_ONXMIT_ENDS) #define IXL1394_OP_SET_SKIPMODE \ (16 | IXL1394_OPTY_OTHER | IXL1394_OPF_ONXMIT_ENDS) #define IXL1394_OP_SET_SYNCWAIT \ (17 | IXL1394_OPTY_OTHER | IXL1394_OPF_ONRECV_ENDS) /* * The dynamic UPDATE versions of each updatable command. */ #define IXL1394_OP_JUMP_U (IXL1394_OP_JUMP | IXL1394_OPF_UPDATE) #define IXL1394_OP_CALLBACK_U (IXL1394_OP_CALLBACK | IXL1394_OPF_UPDATE) #define IXL1394_OP_RECV_PKT_U (IXL1394_OP_RECV_PKT | IXL1394_OPF_UPDATE) #define IXL1394_OP_RECV_PKT_ST_U (IXL1394_OP_RECV_PKT_ST | IXL1394_OPF_UPDATE) #define IXL1394_OP_RECV_BUF_U (IXL1394_OP_RECV_BUF | IXL1394_OPF_UPDATE) #define IXL1394_OP_SEND_PKT_U (IXL1394_OP_SEND_PKT | IXL1394_OPF_UPDATE) #define IXL1394_OP_SEND_PKT_ST_U (IXL1394_OP_SEND_PKT_ST | IXL1394_OPF_UPDATE) #define IXL1394_OP_SEND_PKT_WHDR_ST_U (IXL1394_OP_SEND_PKT_WHDR_ST | \ IXL1394_OPF_UPDATE) #define IXL1394_OP_SEND_BUF_U (IXL1394_OP_SEND_BUF | IXL1394_OPF_UPDATE) #define IXL1394_OP_SET_TAGSYNC_U (IXL1394_OP_SET_TAGSYNC | IXL1394_OPF_UPDATE) #define IXL1394_OP_SET_SKIPMODE_U (IXL1394_OP_SET_SKIPMODE | IXL1394_OPF_UPDATE) /* Opaque type for the ixl private data */ typedef struct ixl_priv_handle *ixl1394_priv_t; /* IXL1394_OP_SET_SKIPMODE values (used only with isoch transmit) */ typedef enum { IXL1394_SKIP_TO_SELF = 0, IXL1394_SKIP_TO_NEXT = 1, IXL1394_SKIP_TO_STOP = 2, IXL1394_SKIP_TO_LABEL = 3 } ixl1394_skip_t; /* * IXL Program Command Primitives */ /* The general command format. The operands vary depending on the opcode */ typedef struct ixl1394_command { struct ixl1394_command *next_ixlp; ixl1394_priv_t compiler_privatep; uint16_t compiler_resv; uint16_t ixl_opcode; uint32_t operands[1]; } ixl1394_command_t; _NOTE(SCHEME_PROTECTS_DATA("Single thread modifies", \ ixl1394_command::compiler_privatep \ ixl1394_command::compiler_resv)) /* * command structure used for a DDI_DMA bound buffer. For portability, * set this _dmac_ll to the buffer's allocated and bound * ddi_dma_cookie_t's _dmac_ll. */ typedef union ixl1394_buf_u { uint64_t _dmac_ll; /* 64-bit DMA address */ uint32_t _dmac_la[2]; /* 2 x 32-bit address */ } ixl1394_buf_t; /* shorthand access to IXL command buffers. similar to defs in dditypes.h */ #define ixldmac_laddr _dmac_ll #ifdef _LONG_LONG_HTOL #define ixldmac_notused _dmac_la[0] #define ixldmac_addr _dmac_la[1] #else #define ixldmac_addr _dmac_la[0] #define ixldmac_notused _dmac_la[1] #endif /* * ixl1394_xfer_pkt * Specifies a packet fragment. * Used with IXL1394_OP_SEND_PKT_ST, IXL1394_OP_SEND_PKT_WHDR_ST, * IXL1394_OP_SEND_PKT, IXL1394_OP_RECV_PKT_ST and IXL1394_OP_RECV_PKT. */ typedef struct ixl1394_xfer_pkt { ixl1394_command_t *next_ixlp; ixl1394_priv_t compiler_privatep; uint16_t compiler_resv; uint16_t ixl_opcode; uint16_t size; /* bytes in ixl_buf */ uint16_t resv; ixl1394_buf_t ixl_buf; /* ddi_dma bound address */ caddr_t mem_bufp; /* kernel virtual addr */ } ixl1394_xfer_pkt_t; _NOTE(SCHEME_PROTECTS_DATA("Single thread modifies", \ ixl1394_xfer_pkt::ixl_buf._dmac_ll \ ixl1394_xfer_pkt::ixl_buf._dmac_la \ ixl1394_xfer_pkt::mem_bufp \ ixl1394_xfer_pkt::size)) /* * ixl1394_xfer_buf * Specifies a buffer of multiple packets. * Used with IXL1394_OP_SEND_BUF and IXL1394_OP_RECV_BUF. */ typedef struct ixl1394_xfer_buf { ixl1394_command_t *next_ixlp; ixl1394_priv_t compiler_privatep; uint16_t compiler_resv; uint16_t ixl_opcode; uint16_t size; /* bytes in ixl_buf */ uint16_t pkt_size; /* bytes in each packet */ ixl1394_buf_t ixl_buf; /* ddi_dma bound address */ caddr_t mem_bufp; /* kernel (not bound) addrss */ } ixl1394_xfer_buf_t; _NOTE(SCHEME_PROTECTS_DATA("Single thread modifies", \ ixl1394_xfer_buf::compiler_privatep \ ixl1394_xfer_buf::ixl_buf._dmac_ll \ ixl1394_xfer_buf::ixl_buf._dmac_la \ ixl1394_xfer_buf::mem_bufp \ ixl1394_xfer_buf::pkt_size \ ixl1394_xfer_buf::size)) /* * ixl1394_xmit_special * Specifies how many cycles are to be skipped before the next packet * is sent. Specifies number of header only packets to be sent, next. * Used with IXL1394_OP_SEND_HDR_ONLY and IXL1394_OP_SEND_NO_PKT. */ typedef struct ixl1394_xmit_special { ixl1394_command_t *next_ixlp; ixl1394_priv_t compiler_privatep; uint16_t compiler_resv; uint16_t ixl_opcode; uint16_t count; uint16_t resv; } ixl1394_xmit_special_t; /* * ixl1394_callback * Specifies a callback function and callback data. * When the callback is invoked, it is passed the addr of this IXL * command, which it can use to retrieve the arg it has stored in * this struct. Used with IXL1394_OP_CALLBACK. */ typedef struct ixl1394_callback { ixl1394_command_t *next_ixlp; ixl1394_priv_t compiler_privatep; uint16_t compiler_resv; uint16_t ixl_opcode; void (*callback)(opaque_t, struct ixl1394_callback *); opaque_t callback_arg; } ixl1394_callback_t; _NOTE(SCHEME_PROTECTS_DATA("Single thread modifies", \ ixl1394_callback::callback \ ixl1394_callback::callback_arg)) /* * ixl1394_label * Specifies a label (location) which can be used as the target of a jump. * Used with IXL1394_OP_LABEL. */ typedef struct ixl1394_label { ixl1394_command_t *next_ixlp; ixl1394_priv_t compiler_privatep; uint16_t compiler_resv; uint16_t ixl_opcode; } ixl1394_label_t; /* * ixl1394_jump * Specifies a label (location) which can then be used as the target of a jump. * Used with IXL1394_OP_JUMP. */ typedef struct ixl1394_jump { ixl1394_command_t *next_ixlp; ixl1394_priv_t compiler_privatep; uint16_t compiler_resv; uint16_t ixl_opcode; ixl1394_command_t *label; } ixl1394_jump_t; _NOTE(SCHEME_PROTECTS_DATA("Single thread modifies", \ ixl1394_jump::label)) /* * ixl1394_set_tagsync * Specifies the tag and sync bits used for the port. * Used with IXL1394_OP_SET_TAGSYNC. */ typedef struct ixl1394_set_tagsync { ixl1394_command_t *next_ixlp; ixl1394_priv_t compiler_privatep; uint16_t compiler_resv; uint16_t ixl_opcode; uint16_t tag; uint16_t sync; } ixl1394_set_tagsync_t; _NOTE(SCHEME_PROTECTS_DATA("Single thread modifies", \ ixl1394_set_tagsync::sync \ ixl1394_set_tagsync::tag)) /* * ixl1394_set_skipmode * Specifies the tag and sync bits used for the port. * Used with IXL1394_OP_SET_SKIPMODE. */ typedef struct ixl1394_set_skipmode { ixl1394_command_t *next_ixlp; ixl1394_priv_t compiler_privatep; uint16_t compiler_resv; uint16_t ixl_opcode; ixl1394_command_t *label; ixl1394_skip_t skipmode; } ixl1394_set_skipmode_t; _NOTE(SCHEME_PROTECTS_DATA("Single thread modifies", \ ixl1394_set_skipmode::compiler_privatep \ ixl1394_set_skipmode::label \ ixl1394_set_skipmode::skipmode)) /* * ixl1394_set_syncwait * Specifies that next receive is to wait for sync before accepting input. * Used with IXL1394_OP_SET_SYNCWAIT. */ typedef struct ixl1394_set_syncwait { ixl1394_command_t *next_ixlp; ixl1394_priv_t compiler_privatep; uint16_t compiler_resv; uint16_t ixl_opcode; } ixl1394_set_syncwait_t; /* * ixl1394_store_timestamp * Specifies that the timestamp value of the most recently sent * packet be stored into the timestamp field of this ixl command. * Used with IXL1394_OP_STORE_TIMESTAMP. */ typedef struct ixl1394_store_timestamp { ixl1394_command_t *next_ixlp; ixl1394_priv_t compiler_privatep; uint16_t compiler_resv; uint16_t ixl_opcode; uint16_t timestamp; uint16_t resv; } ixl1394_store_timestamp_t; _NOTE(SCHEME_PROTECTS_DATA("Single thread modifies", \ ixl1394_store_timestamp::timestamp)) /* * Macros for extracting isochronous packet header fields when receiving * packets via IXL1394_OP_RECV_PKT_ST or IXL1394_OP_RECV_BUF with * ID1394_RECV_HEADERS mode enabled. * The argument to each macro is a quadlet of data. * Prior to using the macro, target drivers first retrieve this quadlet from * bound memory by using ddi_get32(9F). */ /* * timestamp is the first quadlet in an IXL1394_OP_RECV_PKT_ST packet, and is * the last quadlet (after the data payload) in an IXL1394_OP_RECV_BUF packet. */ #define IXL1394_GET_IR_TIMESTAMP(PKT_QUADLET) ((PKT_QUADLET) & 0x0000FFFF) /* * the following macros apply to the second quadlet in an * IXL1394_OP_RECV_PKT_ST packet, and the first quadlet in an * IXL1394_OP_RECV_BUF packet. */ #define IXL1394_GET_IR_DATALEN(PKT_QUADLET) (((PKT_QUADLET) & 0xFFFF0000) >> 16) #define IXL1394_GET_IR_TAG(PKT_QUADLET) (((PKT_QUADLET) & 0x0000C000) >> 14) #define IXL1394_GET_IR_CHAN(PKT_QUADLET) (((PKT_QUADLET) & 0x00003F00) >> 8) #define IXL1394_GET_IR_SYNC(PKT_QUADLET) ((PKT_QUADLET) & 0x0000000F) #ifdef __cplusplus } #endif #endif /* _SYS_1394_IXL1394_H */ /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License, Version 1.0 only * (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 2004 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #ifndef _SYS_1394_S1394_H #define _SYS_1394_S1394_H /* * s1394.h * Contains all of the structures used (internally) by the 1394 * Software Framework */ #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef __cplusplus extern "C" { #endif /* SelfID buffer size */ #define S1394_SELFID_BUF_SIZE 8192 /* Maximum number of allocated commands per target */ #define MAX_NUMBER_ALLOC_CMDS 256 /* Maximum number of lock retries */ #define MAX_NUMBER_OF_LOCK_RETRIES 256 #define S1394_INITIAL_STATES 2 /* Invalid entry in the Speed Map */ #define SPEED_MAP_INVALID 0xFF /* Invalid node num */ #define S1394_INVALID_NODE_NUM 0x3F /* Node state */ #define S1394_NODE_OFFLINE 1 #define S1394_NODE_ONLINE 2 /* Where are commands inserted onto the pending Q? */ #define S1394_PENDING_Q_FRONT 1 #define S1394_PENDING_Q_REAR 2 /* Number of self-initiated bus resets until HAL fails */ #define NUM_BR_FAIL 5 /* Reasons for Self-Initiated Bus Reset */ #define NON_CRITICAL 0 #define CRITICAL 1 /* Bus Mgr (IRM) defines */ #define ROOT_HOLDOFF (1 << 0) #define GAP_COUNT (1 << 1) /* Root Node has no parents */ #define NO_PARENT -1 /* Maximum number of Hops between Nodes on the Bus */ #define MAX_HOPS 23 /* Invalid lo and hi addresses used in s1394_init_addr_space() */ #define ADDR_LO_INVALID 0x0000000000000001 #define ADDR_HI_INVALID 0x0000000000000000 /* Time to delay after CYCLE_TOO_LONG before enabling cycle master */ #define CYCLE_MASTER_TIMER 1000 /* 1 second */ /* Size of directory stack used during config rom scan */ #define S1394_DIR_STACK_SIZE 16 /* * P1394a (Draft 2.x) proposes to disallow a * Config ROM "generation" to be repeated within * a 60 second window. * Because of that, this value should not be set * to any value smaller than 5 seconds without * another method in place to ensure that this * "generation" reuse can not happen. */ /* * Time delay (in ms) from Config ROM update to * software-initiated bus reset. */ #define CONFIG_ROM_UPDATE_DELAY 5000 /* 5 seconds */ #define S1394_ROOT_TEXT_LEAF_SZ 36 #define S1394_ROOT_TEXT_LEAF_QUAD_SZ 9 #define S1394_ROOT_TEXT_KEY 0x81 #define S1394_NODE_UNIQUE_ID_SZ 12 #define S1394_NODE_UNIQUE_ID_QUAD_SZ 3 #define S1394_NODE_UNIQUE_ID_KEY 0x8D #define S1394_UNIT_DIR_SZ 56 #define S1394_UNIT_DIR_QUAD_SZ 14 #define S1394_UNIT_DIR_KEY 0xD1 /* The Organizationally Unique Identifier for Sun Microsystems, Inc. */ #define S1394_SUNW_OUI 0x080020 /* Number of retries in reading the Config ROM */ #define CFGROM_READ_RETRIES 5 /* Delay time between reads of the Config ROM */ #define CFGROM_READ_DELAY 20000 /* 20ms */ /* Error message for serious HBA hardware shutdowns */ #define HALT_ERROR_MESSAGE "%s%d: Unexpected Error: Shutting down HBA -" \ " Hardware disabled until next reboot" /* Command Transaction Type */ #define S1394_CMD_READ 0 #define S1394_CMD_WRITE 1 #define S1394_CMD_LOCK 2 /* Channel allocations */ #define S1394_CHANNEL_ALLOC_HI 1 #define S1394_CHANNEL_ALLOC_LO 0 /* Maximum number of bus resets allowed in isoch rsrc alloc */ #define S1394_ISOCH_ALLOC_RETRIES 5 #define ADDR_RESERVED 1 /* Flags used by the used tree (red-black tree) */ #define BLACK 0 #define RED 1 #define LEFT 0 #define RIGHT 1 /* Isoch Bandwidth Allocation Units conversion */ #define ISOCH_SPEED_FACTOR_S100 16 #define ISOCH_SPEED_FACTOR_S200 8 #define ISOCH_SPEED_FACTOR_S400 4 /* s1394_hal_state_t */ typedef enum { S1394_HAL_INIT, S1394_HAL_RESET, S1394_HAL_NORMAL, S1394_HAL_DREQ, S1394_HAL_SHUTDOWN } s1394_hal_state_t; /* s1394_isoch_cec_type_t */ typedef enum { S1394_SINGLE = 1, S1394_PEER_TO_PEER = 2 } s1394_isoch_cec_type_t; /* s1394_isoch_cec_state_t */ typedef enum { ISOCH_CEC_FREE = (1 << 0), ISOCH_CEC_JOIN = (1 << 1), ISOCH_CEC_LEAVE = (1 << 2), ISOCH_CEC_SETUP = (1 << 3), ISOCH_CEC_TEARDOWN = (1 << 4), ISOCH_CEC_START = (1 << 5), ISOCH_CEC_STOP = (1 << 6) } s1394_isoch_cec_state_t; /* s1394_status_t */ typedef enum { S1394_NOSTATUS = (1 << 0), S1394_LOCK_FAILED = (1 << 1), S1394_CMD_ALLOC_FAILED = (1 << 2), S1394_XFER_FAILED = (1 << 3), S1394_UNKNOWN = (1 << 4), S1394_CMD_INFLIGHT = (1 << 5) } s1394_status_t; /* s1394_free_cfgrom_t */ typedef enum { S1394_FREE_CFGROM_BOTH, S1394_FREE_CFGROM_NEW, S1394_FREE_CFGROM_OLD } s1394_free_cfgrom_t; typedef struct s1394_node_s s1394_node_t; typedef struct s1394_target_s s1394_target_t; typedef struct s1394_hal_s s1394_hal_t; typedef struct s1394_addr_space_blk_s s1394_addr_space_blk_t; typedef struct s1394_config_rom_s s1394_config_rom_t; typedef struct s1394_kstat_s s1394_kstat_t; typedef struct s1394_isoch_cec_s s1394_isoch_cec_t; typedef struct s1394_isoch_cec_member_s s1394_isoch_cec_member_t; /* cfgrom_dir_t */ typedef struct { ushort_t dir_start; ushort_t dir_size; ushort_t dir_next_quad; } cfgrom_dir_t; /* s1394_selfid_pkt_t */ typedef struct s1394_selfid_pkt_s { uint32_t spkt_data; uint32_t spkt_inverse; } s1394_selfid_pkt_t; /* s1394_node_t */ struct s1394_node_s { s1394_selfid_pkt_t *selfid_packet; s1394_node_t *phy_port[IEEE1394_MAX_NUM_PORTS]; s1394_node_t *old_node; s1394_node_t *cur_node; s1394_target_t *target_list; ushort_t cfgrom_size; /* in quads */ ushort_t cfgrom_valid_size; /* in quads */ uchar_t link_active; uchar_t node_num; uchar_t max_1st; uchar_t max_2nd; uchar_t last_port_checked; uchar_t parent_port; uchar_t is_a_leaf; /* All fields above can be zero'd while initing the topology tree */ uint32_t *cfgrom; #define node_guid_hi cfgrom[3] #define node_guid_lo cfgrom[4] #define node_root_dir cfgrom[5] uint_t node_state; uint_t cfgrom_state; uint_t bus_enum_flags; /* fields dir_stack through expected_dir_quad constitute dir stack */ cfgrom_dir_t dir_stack[S1394_DIR_STACK_SIZE]; ushort_t cur_dir_start; ushort_t cur_dir_size; char dir_stack_top; uchar_t expected_type; uchar_t expected_dir_quad; ushort_t cfgrom_quad_to_read; ushort_t cfgrom_quad_read_cnt; /* if rdg blk */ uchar_t rescan_cnt; uchar_t cfgrom_read_fails; uchar_t cfgrom_read_delay; /* in ms */ }; /* defines used during enumeration */ #define NODE_DIR_SIZE(data) ((data) & 0xff) #define NODE_DIR_START(data) (((data) >> 8) & 0xff) #define NODE_DIR_QUAD(data) (((data) >> 16) & 0xff) /* defines for link_active */ #define SET_LINK_ACTIVE(n) ((n)->link_active = 1) #define CLEAR_LINK_ACTIVE(n) ((n)->link_active = 0) #define LINK_ACTIVE(n) \ (((n)->link_active == 0) ? B_FALSE : B_TRUE) /* defines for state */ #define S1394_NODE_CONSUMING_PWR 0x00000001 #define S1394_NODE_ACTIVE 0x00000010 #define S1394_NODE_BUS_PWR_CONSUMER(n) \ ((IEEE1394_SELFID_POWER((n)->selfid_packet) > 0x3) ? B_TRUE : B_FALSE) /* defines for cfgrom_state */ #define S1394_CFGROM_NEW_ALLOC 0x00000001 /* fresh alloc */ #define S1394_CFGROM_BIB_READ 0x00000002 /* bus info blocks read */ #define S1394_CFGROM_ALL_READ 0x00000004 /* read all of it */ #define S1394_CFGROM_BLK_READ_OK 0x00000008 /* can be read in blocks */ #define S1394_CFGROM_GEN_CHANGED 0x00000010 /* config rom gen changed */ #define S1394_CFGROM_PARSED 0x00000020 /* rom enumerated */ #define S1394_CFGROM_DIR_STACK_OFF 0x00000040 /* dir stack turned off */ #define S1394_CFGROM_SIZE_IS_CRCSIZE 0x00000080 /* crc size == cfgrom size */ #define S1394_CFGROM_READ_MASK (S1394_CFGROM_BIB_READ | S1394_CFGROM_ALL_READ) #define S1394_VALID_MASK \ (S1394_CFGROM_READ_MASK | S1394_CFGROM_BLK_READ_OK | \ S1394_CFGROM_GEN_CHANGED | S1394_CFGROM_PARSED) #define CLEAR_CFGROM_STATE(n) ((n)->cfgrom_state &= ~S1394_VALID_MASK) #define CFGROM_VALID(n) \ ((((n)->cfgrom_state & S1394_CFGROM_READ_MASK) != 0 && (n)->cfgrom != \ NULL) ? B_TRUE : B_FALSE) /* macros for cfgrom_state */ #define SET_CFGROM_NEW_ALLOC(n) ((n)->cfgrom_state |= S1394_CFGROM_NEW_ALLOC) #define CLEAR_CFGROM_NEW_ALLOC(n) ((n)->cfgrom_state &= ~S1394_CFGROM_NEW_ALLOC) #define CFGROM_NEW_ALLOC(n) \ (((n)->cfgrom_state & S1394_CFGROM_NEW_ALLOC) != 0 ? B_TRUE : B_FALSE) #define SET_CFGROM_BIB_READ(n) ((n)->cfgrom_state |= S1394_CFGROM_BIB_READ) #define CLEAR_CFGROM_BIB_READ(n) ((n)->cfgrom_state &= ~S1394_CFGROM_BIB_READ) #define CFGROM_BIB_READ(n) \ (((n)->cfgrom_state & S1394_CFGROM_BIB_READ) != 0 ? B_TRUE : B_FALSE) #define SET_CFGROM_ALL_READ(n) ((n)->cfgrom_state |= S1394_CFGROM_ALL_READ) #define CLEAR_CFGROM_ALL_READ(n) ((n)->cfgrom_state &= \ ~S1394_CFGROM_ALL_READ) #define CFGROM_ALL_READ(n) \ (((n)->cfgrom_state & S1394_CFGROM_ALL_READ) != 0 ? B_TRUE : B_FALSE) #define SET_CFGROM_BLK_READ_OK(n) \ ((n)->cfgrom_state |= S1394_CFGROM_BLK_READ_OK) #define CLEAR_CFGROM_BLK_READ_OK(n) \ ((n)->cfgrom_state &= ~S1394_CFGROM_BLK_READ_OK) #define CFGROM_BLK_READ_OK(n) \ (((n)->cfgrom_state & S1394_CFGROM_BLK_READ_OK) != 0 : B_TRUE : B_FALSE) #define SET_CFGROM_GEN_CHANGED(n) \ ((n)->cfgrom_state |= S1394_CFGROM_GEN_CHANGED) #define CLEAR_CFGROM_GEN_CHANGED(n) \ ((n)->cfgrom_state &= ~S1394_CFGROM_GEN_CHANGED) #define CFGROM_GEN_CHANGED(n) \ (((n)->cfgrom_state & S1394_CFGROM_GEN_CHANGED) != 0 ? B_TRUE : B_FALSE) #define SET_CFGROM_PARSED(n) ((n)->cfgrom_state |= S1394_CFGROM_PARSED) #define CLEAR_CFGROM_PARSED(n) ((n)->cfgrom_state &= ~S1394_CFGROM_PARSED) #define CFGROM_PARSED(n) \ (((n)->cfgrom_state & S1394_CFGROM_PARSED) != 0 ? B_TRUE : B_FALSE) #define SET_CFGROM_DIR_STACK_OFF(n) \ ((n)->cfgrom_state |= S1394_CFGROM_DIR_STACK_OFF) #define CLEAR_CFGROM_DIR_STACK_OFF(n) \ ((n)->cfgrom_state &= ~S1394_CFGROM_DIR_STACK_OFF) #define CFGROM_DIR_STACK_OFF(n) \ (((n)->cfgrom_state & S1394_CFGROM_DIR_STACK_OFF) != 0 ? B_TRUE : \ B_FALSE) #define SET_CFGROM_SIZE_IS_CRCSIZE(n) \ ((n)->cfgrom_state |= S1394_CFGROM_SIZE_IS_CRCSIZE) #define CLEAR_CFGROM_SIZE_IS_CRCSIZE(n) \ ((n)->cfgrom_state &= ~S1394_CFGROM_SIZE_IS_CRCSIZE) #define CFGROM_SIZE_IS_CRCSIZE(n) \ (((n)->cfgrom_state & S1394_CFGROM_SIZE_IS_CRCSIZE) != 0 ? B_TRUE : \ B_FALSE) /* defines for bus_enum_flags */ #define S1394_NODE_VISITED 0x00000001 #define S1394_NODE_MATCHED 0x00000010 /* macros that set/clear bus_enum_flags */ #define SET_NODE_VISITED(n) ((n)->bus_enum_flags |= S1394_NODE_VISITED) #define CLEAR_NODE_VISITED(n) ((n)->bus_enum_flags &= ~S1394_NODE_VISITED) #define NODE_VISITED(n) \ (((n)->bus_enum_flags & S1394_NODE_VISITED) != 0 ? B_TRUE : B_FALSE) #define SET_NODE_MATCHED(n) ((n)->bus_enum_flags |= S1394_NODE_MATCHED) #define CLEAR_NODE_MATCHED(n) ((n)->bus_enum_flags &= ~S1394_NODE_MATCHED) #define NODE_MATCHED(n) \ (((n)->bus_enum_flags & S1394_NODE_MATCHED) != 0 ? B_TRUE : B_FALSE) #define SET_NODE_IDENTIFIED(n) ((n)->bus_enum_flags |= S1394_NODE_IDENTIFIED) #define CLEAR_NODE_IDENTIFIED(n) ((n)->bus_enum_flags &= ~S1394_NODE_IDENTIFIED) #define NODE_IDENTIFIED(n) \ (((n)->bus_enum_flags & S1394_NODE_IDENTIFIED) != 0 ? B_TRUE : B_FALSE) /* * s1394_fa_type_t - FA types, used as index into target_fa and hal_fa */ typedef enum { S1394_FA_TYPE_FCP_CTL, /* FCP controller */ S1394_FA_TYPE_FCP_TGT, /* FCP target */ S1394_FA_TYPE_CMP_OMPR, /* CMP oMPR */ S1394_FA_TYPE_CMP_IMPR, /* CMP iMPR */ S1394_FA_NTYPES, /* should remain the last field */ S1394_FA_TYPE_CMP = S1394_FA_TYPE_CMP_OMPR /* common CMP type */ } s1394_fa_type_t; /* * s1394_fa_descr_t - FA type descriptor */ typedef struct s1394_fa_descr_s { uint64_t fd_addr; /* address space */ size_t fd_size; /* address space size */ t1394_addr_enable_t fd_enable; /* access types */ t1394_addr_evts_t fd_evts; /* event callbacks */ uint64_t fd_conv_base; /* address conversion base */ } s1394_fa_descr_t; /* * s1394_fcp_target_t - per-target data required for FCP support */ typedef struct s1394_fcp_target_s { t1394_fcp_evts_t fc_evts; } s1394_fcp_target_t; /* * s1394_cmp_target_t - per-target data required for CMP support */ typedef struct s1394_cmp_target_s { t1394_cmp_evts_t cm_evts; } s1394_cmp_target_t; /* * s1394_fa_target_t - per-target data required for fixed address support */ typedef struct s1394_fa_target_s { s1394_target_t *fat_next; /* next in the list */ /* type-specific data */ union { s1394_fcp_target_t fcp; s1394_cmp_target_t cmp; } fat_u; } s1394_fa_target_t; /* s1394_target_t - fields protected by the HAL's target_list_rwlock */ struct s1394_target_s { int target_version; dev_info_t *target_dip; /* Pointers to the node and HAL on which the target exists */ s1394_node_t *on_node; s1394_hal_t *on_hal; s1394_target_t *target_next; s1394_target_t *target_prev; /* target_list is a copy of target_list pointer in the node */ s1394_target_t *target_list; s1394_target_t *target_sibling; uint_t unit_dir; /* The max_payload sizes - max and current conditions */ uint_t dev_max_payload; uint_t current_max_payload; /* Number of asynch command target has allocated */ uint_t target_num_cmds; /* * Are physical AR requests allowed from this target's node? * This field keeps track of the number of allocated blocks * of physical memory the target has. */ uint_t physical_arreq_enabled; uint_t target_state; /* FCP controller and target */ s1394_fa_target_t target_fa[S1394_FA_NTYPES]; }; #define S1394_TARG_HP_NODE 0x00000001 /* on a hp node */ #define S1394_TARG_GONE 0x00000002 /* unplugged */ #define S1394_TARG_USING_BUS_PWR 0x00000004 /* consuming pwr now */ #define S1394_TARG_BUS_PWR_CONSUMER 0x00000008 /* power consumer */ #define S1394_TARG_ACTIVE 0x00000010 /* active */ /* * s1394_fa_hal_t - per-hal data required for fixed address support */ typedef struct s1394_fa_hal_s { /* * each hal keeps a list of registered fixed address clients */ s1394_target_t *fal_head; s1394_target_t *fal_tail; uint_t fal_gen; /* list generation */ s1394_fa_descr_t *fal_descr; /* type descriptor */ s1394_addr_space_blk_t *fal_addr_blk; /* address space block */ } s1394_fa_hal_t; /* * s1394_cmp_hal_t - per-hal data required for fixed address support */ typedef struct s1394_cmp_hal_s { /* oMPR */ krwlock_t cmp_ompr_rwlock; uint32_t cmp_ompr_val; /* iMPR */ krwlock_t cmp_impr_rwlock; uint32_t cmp_impr_val; } s1394_cmp_hal_t; /* s1394_hal_t */ struct s1394_hal_s { s1394_hal_t *hal_next; s1394_hal_t *hal_prev; /* Target list */ s1394_target_t *target_head; s1394_target_t *target_tail; krwlock_t target_list_rwlock; /* halinfo structure given at attach time */ h1394_halinfo_t halinfo; boolean_t hal_was_suspended; /* Bus reset thread */ kthread_t *br_thread; kmutex_t br_thread_mutex; kcondvar_t br_thread_cv; uint_t br_thread_ev_type; uint32_t br_cfgrom_read_gen; kmutex_t br_cmplq_mutex; kcondvar_t br_cmplq_cv; cmd1394_cmd_t *br_cmplq_head; cmd1394_cmd_t *br_cmplq_tail; s1394_hal_state_t hal_state; /* kstats - kernel statistics for the Services Layer */ s1394_kstat_t *hal_kstats; kstat_t *hal_ksp; /* CSR STATE register bits (DREQ and ABDICATE) */ uint_t disable_requests_bit; uint_t abdicate_bus_mgr_bit; boolean_t initiated_bus_reset; int initiated_br_reason; uint32_t num_bus_reset_till_fail; /* IRM and Bus Manager */ int IRM_node; kmutex_t bus_mgr_node_mutex; kcondvar_t bus_mgr_node_cv; int bus_mgr_node; boolean_t incumbent_bus_mgr; timeout_id_t bus_mgr_timeout_id; timeout_id_t bus_mgr_query_timeout_id; /* 1394 Bus stats */ int gap_count; int optimum_gap_count; uint8_t slowest_node_speed; /* Local Config ROM */ kmutex_t local_config_rom_mutex; uint32_t *local_config_rom; uint32_t *temp_config_rom_buf; s1394_config_rom_t *root_directory; uint_t free_space; uint_t config_rom_update_amount; boolean_t config_rom_timer_set; timeout_id_t config_rom_timer; /* Cycle Master - CYCLE_TOO_LONG timer */ kmutex_t cm_timer_mutex; boolean_t cm_timer_set; timeout_id_t cm_timer; /* Incoming (AR) request and 1394 address space */ kmutex_t addr_space_free_mutex; s1394_addr_space_blk_t *addr_space_free_list; kmutex_t addr_space_used_mutex; s1394_addr_space_blk_t *addr_space_used_tree; uint64_t physical_addr_lo; uint64_t physical_addr_hi; uint64_t csr_addr_lo; uint64_t csr_addr_hi; uint64_t normal_addr_lo; uint64_t normal_addr_hi; uint64_t posted_write_addr_lo; uint64_t posted_write_addr_hi; /* Outgoing (AT) request queues */ kmutex_t outstanding_q_mutex; cmd1394_cmd_t *outstanding_q_head; cmd1394_cmd_t *outstanding_q_tail; kmutex_t pending_q_mutex; cmd1394_cmd_t *pending_q_head; cmd1394_cmd_t *pending_q_tail; /* SelfID buffers */ void *selfid_buf0; void *selfid_buf1; int current_buffer; s1394_selfid_pkt_t *selfid_ptrs[IEEE1394_MAX_NODES]; /* Topology trees and local bus stats */ kmutex_t topology_tree_mutex; uint32_t cfgroms_being_read; s1394_node_t *topology_tree; s1394_node_t *old_tree; uint32_t generation_count; ushort_t number_of_nodes; ushort_t node_id; boolean_t topology_tree_valid; boolean_t topology_tree_processed; uint32_t old_generation_count; ushort_t old_number_of_nodes; ushort_t old_node_id; s1394_node_t current_tree[IEEE1394_MAX_NODES]; s1394_node_t last_valid_tree[IEEE1394_MAX_NODES]; boolean_t old_tree_valid; /* TOPOLOGY_MAP backing store buffer */ uint32_t *CSR_topology_map; /* Speed Map */ uint8_t speed_map[IEEE1394_MAX_NODES][IEEE1394_MAX_NODES]; /* Stack, Queue, and Node Number list */ void *hal_stack[IEEE1394_MAX_NODES]; int hal_stack_depth; void *hal_queue[IEEE1394_MAX_NODES]; int hal_queue_front; int hal_queue_back; int hal_node_number_list[IEEE1394_MAX_NODES]; int hal_node_number_list_size; /* Isoch CEC list */ kmutex_t isoch_cec_list_mutex; s1394_isoch_cec_t *isoch_cec_list_head; s1394_isoch_cec_t *isoch_cec_list_tail; struct kmem_cache *hal_kmem_cachep; ndi_event_hdl_t hal_ndi_event_hdl; callb_cpr_t hal_cprinfo; /* FCP controllers and targets */ s1394_fa_hal_t hal_fa[S1394_FA_NTYPES]; /* CMP support */ s1394_cmp_hal_t hal_cmp; }; _NOTE(SCHEME_PROTECTS_DATA("No lock needed to start/stop timer", \ s1394_hal_s::cm_timer)) /* defines for br_thread_ev_type */ #define BR_THR_CFGROM_SCAN 0x00000001 /* start reading */ #define BR_THR_GO_AWAY 0x00000002 /* clean & exit */ /* * FCP command and response address space */ #define IEC61883_FCP_BASE_ADDR 0xFFFFF0000B00 #define IEC61883_FCP_CMD_ADDR IEC61883_FCP_BASE_ADDR #define IEC61883_FCP_CMD_SIZE 0x200 #define IEC61883_FCP_RESP_ADDR (IEC61883_FCP_CMD_ADDR + IEC61883_FCP_CMD_SIZE) #define IEC61883_FCP_RESP_SIZE 0x200 #define IEC61883_FCP_END_ADDR (IEC61883_FCP_RESP_ADDR + IEC61883_FCP_RESP_SIZE) /* CMP master plugs */ #define IEC61883_CMP_OMPR_ADDR 0xFFFFF0000900 #define IEC61883_CMP_IMPR_ADDR 0xFFFFF0000980 #define IEC61883_CMP_OMPR_INIT_VAL 0xBFFFFF00 #define IEC61883_CMP_IMPR_INIT_VAL 0x80FFFF00 #define IEC61883_CMP_OMPR_LOCK_MASK 0x3FFFFF00 #define IEC61883_CMP_IMPR_LOCK_MASK 0x00FFFF00 /* s1394_addr_space_blk_t */ struct s1394_addr_space_blk_s { /* Pointers and coloring for Red-Black tree */ s1394_addr_space_blk_t *asb_parent; s1394_addr_space_blk_t *asb_left; s1394_addr_space_blk_t *asb_right; uint32_t asb_color; boolean_t free_kmem_bufp; /* Addr Blk info - callbacks, permissions, backing store, etc. */ uint64_t addr_lo; uint64_t addr_hi; uint32_t addr_reserved; t1394_addr_enable_t addr_enable; t1394_addr_type_t addr_type; t1394_addr_evts_t addr_events; caddr_t kmem_bufp; void *addr_arg; }; /* s1394_config_rom_t */ struct s1394_config_rom_s { boolean_t cfgrom_used; uint32_t cfgrom_addr_lo; uint32_t cfgrom_addr_hi; uint_t root_dir_offset; s1394_config_rom_t *cfgrom_next; s1394_config_rom_t *cfgrom_prev; }; /* s1394_kstat_t */ struct s1394_kstat_s { /* Asynch Receive (AR) requests */ uint_t arreq_quad_rd; uint_t arreq_blk_rd; uint_t arreq_quad_wr; uint_t arreq_blk_wr; uint_t arreq_lock32; uint_t arreq_lock64; uint_t arreq_blk_rd_size; uint_t arreq_blk_wr_size; uint_t arreq_posted_write_error; /* Failure responses to AR requests (sent) */ uint_t arresp_quad_rd_fail; uint_t arresp_blk_rd_fail; uint_t arresp_quad_wr_fail; uint_t arresp_blk_wr_fail; uint_t arresp_lock32_fail; uint_t arresp_lock64_fail; /* Asynch Transmit (AT) requests */ uint_t atreq_quad_rd; uint_t atreq_blk_rd; uint_t atreq_quad_wr; uint_t atreq_blk_wr; uint_t atreq_lock32; uint_t atreq_lock64; uint_t atreq_blk_rd_size; uint_t atreq_blk_wr_size; /* Failure responses to AT requests (received) */ uint_t atresp_quad_rd_fail; uint_t atresp_blk_rd_fail; uint_t atresp_quad_wr_fail; uint_t atresp_blk_wr_fail; uint_t atresp_lock32_fail; uint_t atresp_lock64_fail; /* Allocate & free requests */ uint_t cmd_alloc; uint_t cmd_alloc_fail; uint_t cmd_free; uint_t addr_phys_alloc; uint_t addr_posted_alloc; uint_t addr_normal_alloc; uint_t addr_csr_alloc; uint_t addr_alloc_fail; uint_t addr_space_free; /* Bus reset and miscellaneous */ uint_t bus_reset; uint_t selfid_complete; uint_t selfid_buffer_error; uint_t pending_q_insert; uint64_t guid; }; _NOTE(SCHEME_PROTECTS_DATA("Statistics", \ s1394_kstat_s::{arreq_blk_rd arreq_blk_wr arreq_quad_rd arreq_quad_wr \ cmd_free selfid_buffer_error arreq_posted_write_error})) /* s1394_isoch_cec_t */ struct s1394_isoch_cec_s { s1394_isoch_cec_t *cec_next; s1394_isoch_cec_t *cec_prev; kmutex_t isoch_cec_mutex; /* Isoch CEC member list */ s1394_isoch_cec_type_t cec_type; s1394_isoch_cec_member_t *cec_member_list_head; s1394_isoch_cec_member_t *cec_member_list_tail; s1394_isoch_cec_member_t *cec_member_talker; /* Properties given in t1394_alloc_isoch_cec() */ t1394_isoch_cec_props_t cec_alloc_props; /* Current state of Isoch CEC */ uint_t filter_min_speed; uint_t filter_max_speed; uint_t filter_current_speed; uint64_t filter_channel_mask; uint_t bandwidth; t1394_cec_options_t cec_options; s1394_isoch_cec_state_t state_transitions; boolean_t in_callbacks; boolean_t in_fail_callbacks; kcondvar_t in_callbacks_cv; boolean_t cec_want_wakeup; boolean_t realloc_valid; boolean_t realloc_failed; t1394_isoch_rsrc_error_t realloc_fail_reason; uint_t realloc_chnl_num; uint_t realloc_bandwidth; uint_t realloc_speed; }; #define CEC_IN_ANY_CALLBACKS(cec) (((cec)->in_callbacks == B_TRUE) || \ ((cec)->in_fail_callbacks == B_TRUE)) #define CEC_TRANSITION_LEGAL(cec, tran) ((cec)->state_transitions & (tran)) #define CEC_SET_LEGAL(cec, tran) ((cec)->state_transitions |= (tran)) #define CEC_SET_ILLEGAL(cec, tran) ((cec)->state_transitions &= ~(tran)) /* s1394_isoch_cec_member_t */ struct s1394_isoch_cec_member_s { s1394_isoch_cec_member_t *cec_mem_next; s1394_isoch_cec_member_t *cec_mem_prev; /* Events for Isoch CEC member - given in t1394_join_isoch_cec() */ t1394_isoch_cec_evts_t isoch_cec_evts; opaque_t isoch_cec_evts_arg; uint64_t req_channel_mask; uint_t req_max_speed; t1394_jii_options_t cec_mem_options; s1394_target_t *cec_mem_target; }; /* cmd1394_fa_cmd_priv_t - per-command data for fixed address support */ typedef struct s1394_fa_cmd_priv_s { s1394_fa_type_t type; void (*completion_callback)(); opaque_t callback_arg; } s1394_fa_cmd_priv_t; /* s1394_cmd_priv_t */ typedef struct s1394_cmd_priv_s { /* Services Layer private structure for asynch commands */ cmd1394_cmd_t *cmd_priv_next; cmd1394_cmd_t *cmd_priv_prev; uint32_t cmd_priv_xfer_type; s1394_target_t *sent_by_target; s1394_hal_t *sent_on_hal; int lock_req_step; int temp_num_retries; size_t data_remaining; kmutex_t blocking_mutex; kcondvar_t blocking_cv; boolean_t blocking_flag; boolean_t cmd_in_use; boolean_t posted_write; boolean_t arreq_valid_addr; /* * Commands can be extended to support additional functionality. * The only extension at this time is FA (currently used only for FCP). * The downside here is that every command should carry FA overhead * even if the target doesn't use FA. However, alternative approaches * would require separate allocation of FA overhead per command, which * complicates the code and fragments the memory -- seems not worth it * given that FA overhead is just a few bytes and there's a limit of * 256 commands per target. */ int cmd_ext_type; union { s1394_fa_cmd_priv_t fa; } cmd_ext; h1394_cmd_priv_t hal_cmd_private; } s1394_cmd_priv_t; #define S1394_GET_CMD_PRIV(cmd) \ ((s1394_cmd_priv_t *)((uchar_t *)(cmd) + sizeof (cmd1394_cmd_t))) /* command extension types */ enum { S1394_CMD_EXT_FA = 1 }; #define S1394_GET_FA_CMD_PRIV(cmd) (&(S1394_GET_CMD_PRIV(cmd)->cmd_ext.fa)) #define S1394_IS_CMD_FCP(s_priv) \ ((s_priv->cmd_ext.fa.type == S1394_FA_TYPE_FCP_CTL) || \ (s_priv->cmd_ext.fa.type == S1394_FA_TYPE_FCP_TGT)) _NOTE(SCHEME_PROTECTS_DATA("Unique per command", \ s1394_cmd_priv_s::cmd_priv_xfer_type)) /* s1394_state_t */ typedef struct s1394_state_s { /* HAL list */ kmutex_t hal_list_mutex; s1394_hal_t *hal_head; s1394_hal_t *hal_tail; } s1394_state_t; /* Service Layer Global State Pointer */ extern s1394_state_t *s1394_statep; /* 1394 Services Layer Internals - 1394 Address Space Routines */ int s1394_request_addr_blk(s1394_hal_t *hal, t1394_alloc_addr_t *addr_allocp); int s1394_claim_addr_blk(s1394_hal_t *hal, t1394_alloc_addr_t *addr_allocp); int s1394_free_addr_blk(s1394_hal_t *hal, s1394_addr_space_blk_t *blk); int s1394_reserve_addr_blk(s1394_hal_t *hal, t1394_alloc_addr_t *addr_allocp); int s1394_init_addr_space(s1394_hal_t *hal); void s1394_destroy_addr_space(s1394_hal_t *hal); void s1394_free_list_insert(s1394_hal_t *hal, s1394_addr_space_blk_t *new_blk); s1394_addr_space_blk_t *s1394_used_tree_search(s1394_hal_t *hal, uint64_t addr); s1394_addr_space_blk_t *s1394_used_tree_delete(s1394_hal_t *hal, s1394_addr_space_blk_t *z); boolean_t s1394_is_posted_write(s1394_hal_t *hal, uint64_t addr); boolean_t s1394_is_physical_addr(s1394_hal_t *hal, uint64_t addr); boolean_t s1394_is_csr_addr(s1394_hal_t *hal, uint64_t addr); boolean_t s1394_is_normal_addr(s1394_hal_t *hal, uint64_t addr); /* 1394 Services Layer Internals - Asynchronous Communications Routines */ int s1394_alloc_cmd(s1394_hal_t *hal, uint_t flags, cmd1394_cmd_t **cmdp); int s1394_free_cmd(s1394_hal_t *hal, cmd1394_cmd_t **cmdp); int s1394_xfer_asynch_command(s1394_hal_t *hal, cmd1394_cmd_t *cmd, int *err); int s1394_setup_asynch_command(s1394_hal_t *hal, s1394_target_t *target, cmd1394_cmd_t *cmd, uint32_t xfer_type, int *err); void s1394_insert_q_asynch_cmd(s1394_hal_t *hal, cmd1394_cmd_t *cmd); void s1394_remove_q_asynch_cmd(s1394_hal_t *hal, cmd1394_cmd_t *cmd); void s1394_atreq_cmd_complete(s1394_hal_t *hal, cmd1394_cmd_t *req, int status); void s1394_atresp_cmd_complete(s1394_hal_t *hal, cmd1394_cmd_t *resp, int status); int s1394_send_response(s1394_hal_t *hal, cmd1394_cmd_t *resp); int s1394_compare_swap(s1394_hal_t *hal, s1394_target_t *target, cmd1394_cmd_t *cmd); int s1394_split_lock_req(s1394_hal_t *hal, s1394_target_t *target, cmd1394_cmd_t *cmd); void s1394_pending_q_insert(s1394_hal_t *hal, cmd1394_cmd_t *cmd, uint_t flags); void s1394_resend_pending_cmds(s1394_hal_t *hal); /* 1394 Services Layer Internals - Bus Reset Routines */ int s1394_parse_selfid_buffer(s1394_hal_t *hal, void *selfid_buf_addr, uint32_t selfid_size); void s1394_sort_selfids(s1394_hal_t *hal); void s1394_init_topology_tree(s1394_hal_t *hal, boolean_t copied, ushort_t number_of_nodes); int s1394_topology_tree_build(s1394_hal_t *hal); void s1394_topology_tree_mark_all_unvisited(s1394_hal_t *hal); void s1394_old_tree_mark_all_unvisited(s1394_hal_t *hal); void s1394_old_tree_mark_all_unmatched(s1394_hal_t *hal); void s1394_copy_old_tree(s1394_hal_t *hal); void s1394_match_tree_nodes(s1394_hal_t *hal); int s1394_topology_tree_calculate_diameter(s1394_hal_t *hal); int s1394_gap_count_optimize(int diameter); int s1394_get_current_gap_count(s1394_hal_t *hal); void s1394_speed_map_fill(s1394_hal_t *hal); uint8_t s1394_speed_map_get(s1394_hal_t *hal, uint32_t from_node, uint32_t to_node); void s1394_update_speed_map_link_speeds(s1394_hal_t *hal); int s1394_get_isoch_rsrc_mgr(s1394_hal_t *hal); void s1394_physical_arreq_setup_all(s1394_hal_t *hal); void s1394_physical_arreq_set_one(s1394_target_t *target); void s1394_physical_arreq_clear_one(s1394_target_t *target); s1394_node_t *s1394_topology_tree_get_root_node(s1394_hal_t *hal); /* 1394 Services Layer Internals - CSR and Config ROM Routines */ int s1394_setup_CSR_space(s1394_hal_t *hal); void s1394_CSR_topology_map_update(s1394_hal_t *hal); void s1394_CSR_topology_map_disable(s1394_hal_t *hal); int s1394_init_local_config_rom(s1394_hal_t *hal); void s1394_destroy_local_config_rom(s1394_hal_t *hal); int s1394_add_config_rom_entry(s1394_hal_t *hal, uint8_t key, uint32_t *buffer, uint_t size, void **handle, int *status); int s1394_remove_config_rom_entry(s1394_hal_t *hal, void **handle, int *status); void s1394_update_config_rom_callback(void *arg); /* In s1394_dev_disc.c */ void s1394_br_thread(s1394_hal_t *hal); void s1394_free_cfgrom(s1394_hal_t *hal, s1394_node_t *node, s1394_free_cfgrom_t options); void s1394_copy_cfgrom(s1394_node_t *to, s1394_node_t *from); int s1394_read_rest_of_cfgrom(s1394_hal_t *hal, s1394_node_t *node, s1394_status_t *status); void s1394_cfgrom_parse_unit_dir(uint32_t *unit_dir, uint32_t *addr_hi, uint32_t *addr_lo, uint32_t *size_hi, uint32_t *size_lo); boolean_t s1394_valid_cfgrom(s1394_hal_t *hal, s1394_node_t *node); boolean_t s1394_valid_dir(s1394_hal_t *hal, s1394_node_t *node, uint32_t key, uint32_t *dir); void s1394_get_maxpayload(s1394_target_t *target, uint_t *dev_max_payload, uint_t *current_max_payload); int s1394_lock_tree(s1394_hal_t *hal); void s1394_unlock_tree(s1394_hal_t *hal); /* 1394 Services Layer Driver - Hotplug Routines */ dev_info_t *s1394_devi_find(dev_info_t *pdip, char *name, char *caddr); int s1394_update_devinfo_tree(s1394_hal_t *hal, s1394_node_t *node); int s1394_offline_node(s1394_hal_t *hal, s1394_node_t *node); int s1394_process_topology_tree(s1394_hal_t *hal, int *wait_for_cbs, uint_t *wait_gen); int s1394_process_old_tree(s1394_hal_t *hal); void s1394_add_target_to_node(s1394_target_t *target); void s1394_remove_target_from_node(s1394_target_t *target); /* fixed address support */ int s1394_fa_claim_addr(s1394_hal_t *hal, s1394_fa_type_t type, s1394_fa_descr_t *descr); void s1394_fa_free_addr(s1394_hal_t *hal, s1394_fa_type_t type); void s1394_fa_list_add(s1394_hal_t *hal, s1394_target_t *target, s1394_fa_type_t type); int s1394_fa_list_remove(s1394_hal_t *hal, s1394_target_t *target, s1394_fa_type_t type); boolean_t s1394_fa_list_is_empty(s1394_hal_t *hal, s1394_fa_type_t type); uint_t s1394_fa_list_gen(s1394_hal_t *hal, s1394_fa_type_t type); void s1394_fa_init_cmd(s1394_cmd_priv_t *s_priv, s1394_fa_type_t type); void s1394_fa_convert_cmd(s1394_hal_t *hal, cmd1394_cmd_t *cmd); void s1394_fa_restore_cmd(s1394_hal_t *hal, cmd1394_cmd_t *cmd); void s1394_fa_check_restore_cmd(s1394_hal_t *hal, cmd1394_cmd_t *cmd); /* FCP */ int s1394_fcp_hal_init(s1394_hal_t *hal); int s1394_fcp_register_ctl(s1394_target_t *target, t1394_fcp_evts_t *evts); int s1394_fcp_register_tgt(s1394_target_t *target, t1394_fcp_evts_t *evts); int s1394_fcp_unregister_ctl(s1394_target_t *target); int s1394_fcp_unregister_tgt(s1394_target_t *target); int s1394_fcp_write_check_cmd(cmd1394_cmd_t *cmd); /* CMP */ int s1394_cmp_register(s1394_target_t *target, t1394_cmp_evts_t *evts); int s1394_cmp_unregister(s1394_target_t *target); int s1394_cmp_read(s1394_target_t *target, t1394_cmp_reg_t reg, uint32_t *valp); int s1394_cmp_cas(s1394_target_t *target, t1394_cmp_reg_t reg, uint32_t arg_val, uint32_t new_val, uint32_t *old_valp); /* 1394 Services Layer Internals - Isochronous Communication Routines */ void s1394_isoch_rsrc_realloc(s1394_hal_t *hal); void s1394_isoch_rsrc_realloc_notify(s1394_hal_t *hal); int s1394_channel_alloc(s1394_hal_t *hal, uint32_t channel_mask, uint_t generation, uint_t flags, uint32_t *old_channels, int *result); int s1394_channel_free(s1394_hal_t *hal, uint32_t channel_mask, uint_t generation, uint_t flags, uint32_t *old_channels, int *result); int s1394_bandwidth_alloc(s1394_hal_t *hal, uint32_t bw_alloc_units, uint_t generation, int *result); uint_t s1394_compute_bw_alloc_units(s1394_hal_t *hal, uint_t bandwidth, uint_t speed); int s1394_bandwidth_free(s1394_hal_t *hal, uint32_t bw_alloc_units, uint_t generation, int *result); void s1394_isoch_cec_list_insert(s1394_hal_t *hal, s1394_isoch_cec_t *cec); void s1394_isoch_cec_list_remove(s1394_hal_t *hal, s1394_isoch_cec_t *cec); void s1394_isoch_cec_member_list_insert(s1394_hal_t *hal, s1394_isoch_cec_t *cec, s1394_isoch_cec_member_t *member); void s1394_isoch_cec_member_list_remove(s1394_hal_t *hal, s1394_isoch_cec_t *cec, s1394_isoch_cec_member_t *member); /* 1394 Services Layer Internals - Miscellaneous Routines */ void s1394_cleanup_for_detach(s1394_hal_t *hal, uint_t cleanup_level); void s1394_hal_shutdown(s1394_hal_t *hal, boolean_t disable_hal); void s1394_initiate_hal_reset(s1394_hal_t *hal, int reason); boolean_t s1394_on_br_thread(s1394_hal_t *hal); void s1394_destroy_br_thread(s1394_hal_t *hal); void s1394_tickle_bus_reset_thread(s1394_hal_t *hal); void s1394_block_on_asynch_cmd(cmd1394_cmd_t *cmd); int s1394_HAL_asynch_error(s1394_hal_t *hal, cmd1394_cmd_t *cmd, s1394_hal_state_t state); boolean_t s1394_mblk_too_small(cmd1394_cmd_t *cmd); boolean_t s1394_address_rollover(cmd1394_cmd_t *cmd); uint_t s1394_stoi(char *p, int len, int base); uint_t s1394_CRC16(uint_t *d, uint_t crc_length); uint_t s1394_CRC16_old(uint_t *d, uint_t crc_length); int s1394_ioctl(s1394_hal_t *hal, int cmd, intptr_t arg, int mode, cred_t *cred_p, int *rval_p); void s1394_check_pwr_mgmt(s1394_hal_t *hal, s1394_target_t *target, boolean_t add); int s1394_kstat_init(s1394_hal_t *hal); int s1394_kstat_delete(s1394_hal_t *hal); int s1394_kstat_update(kstat_t *ksp, int rw); void s1394_addr_alloc_kstat(s1394_hal_t *hal, uint64_t addr); void s1394_print_node_info(s1394_hal_t *hal); s1394_hal_t *s1394_dip_to_hal(dev_info_t *dip); s1394_target_t *s1394_target_from_dip(s1394_hal_t *hal, dev_info_t *tdip); s1394_target_t *s1394_target_from_dip_locked(s1394_hal_t *hal, dev_info_t *tdip); void s1394_destroy_timers(s1394_hal_t *hal); void s1394_cycle_too_long_callback(void *arg); #ifdef __cplusplus } #endif #endif /* _SYS_1394_S1394_H */ /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License, Version 1.0 only * (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 2004 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #ifndef _SYS_1394_S1394_IMPL_H #define _SYS_1394_S1394_IMPL_H /* * s1394_impl.h * Typedefs and defines used by all 1394 Software Framework files */ #ifdef __cplusplus extern "C" { #endif /* opaque_t type */ #ifndef _OPAQUE_T #define _OPAQUE_T typedef void *opaque_t; #endif #ifdef __cplusplus } #endif #endif /* _SYS_1394_S1394_IMPL_H */ /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License, Version 1.0 only * (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 1999-2002 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #ifndef _SYS_1394_T1394_H #define _SYS_1394_T1394_H /* * t1394.h * Contains all of the prototypes, defines, and structures necessary * for building drivers using the Solaris 1394 Software Framework. */ #include #include #include #include #include #include #include #include #include #include #ifdef __cplusplus extern "C" { #endif /* * Macro to convert a byte stream into a big endian quadlet or octlet or * back the other way. All data is treated as byte streams over the 1394 * bus. These macros will convert the data to a big endian "integer" on * x86 platforms, and it will do nothing if it is not on x86. */ #ifdef _LITTLE_ENDIAN #define T1394_DATA32(DATA) ddi_swap32(DATA) #define T1394_DATA64(DATA) ddi_swap64(DATA) #else #define T1394_DATA32(DATA) (DATA) #define T1394_DATA64(DATA) (DATA) #endif /* The various "handles" returned by the 1394 Framework */ /* Target handle type */ typedef struct target_handle *t1394_handle_t; /* Address handle type */ typedef struct address_handle *t1394_addr_handle_t; /* Isoch single handle type */ typedef struct isoch_handle *t1394_isoch_single_handle_t; /* Isoch CEC handle type */ typedef struct isoch_handle *t1394_isoch_cec_handle_t; /* Config ROM handle type */ typedef struct cfgrom_handle *t1394_cfgrom_handle_t; /* * t1394_localinfo_t * is filled in and returned by the 1394 Framework at attach time * (in the t1394_attachinfo_t structure returned from t1394_attach()) * to provide the local host nodeID and the current bus generation. */ typedef struct t1394_localinfo_s { uint_t bus_generation; uint_t local_nodeID; } t1394_localinfo_t; /* * t1394_attachinfo_t * is filled in and returned by the 1394 Framework at attach time * (returned from the call to t1394_attach()). This structure contains * the t1394_localinfo_t structure described above, as well as the * iblock cookie and the attributes necessary for DMA allocations, etc. */ typedef struct t1394_attachinfo_s { ddi_iblock_cookie_t iblock_cookie; ddi_device_acc_attr_t acc_attr; ddi_dma_attr_t dma_attr; t1394_localinfo_t localinfo; } t1394_attachinfo_t; /* * t1394_addr_enable_t * is used in the t1394_alloc_addr_t structure, passed to * t1394_alloc_addr(), to indicate what types of (incoming) * asynchronous requests will be allowed in a given address block. * If, for example, an address block is intended to be read-only, * then only the T1394_ADDR_RDENBL bit should be enabled at allocation * time. Then, when incoming requests of an inappropriate type (write * or lock requests, in this case) arrive, the 1394 Framework can * automatically respond to them with TYPE_ERROR in the response * without having to notify the target driver. */ typedef enum { T1394_ADDR_RDENBL = (1 << 0), T1394_ADDR_WRENBL = (1 << 1), T1394_ADDR_LKENBL = (1 << 2) } t1394_addr_enable_t; /* * t1394_addr_type_t * is used in the t1394_alloc_addr_t structure, passed to * t1394_alloc_addr(), to indicate what type of address block the * target driver would like to allocate. * T1394_ADDR_POSTED_WRITE indicates posted write memory, where * incoming write requests are automatically acknowledged as complete. * T1394_ADDR_NORMAL indicates memory, unlike the posted write area, * where all requests regardless of type are ack_pended upon receipt * and are subsequently responded to. * T1394_ADDR_CSR memory range is generally used by target drivers * that are implementing a well-defined protocol. * And T1394_ADDR_FIXED is used to indicate to t1394_alloc_addr() * that a specific set of addresses are needed. Unlike the other three * types, this type of request is used to choose a specific address or * range of addresses in 1394 address space. */ typedef enum { T1394_ADDR_POSTED_WRITE = 0, T1394_ADDR_NORMAL = 1, T1394_ADDR_CSR = 2, T1394_ADDR_FIXED = 3 } t1394_addr_type_t; /* * t1394_addr_evts_t * is used in the t1394_alloc_addr_t structure, passed to * t1394_alloc_addr(), to specify callback routines for the * allocated address block. When a request of the appropriate type * (read/write/lock) is received to a target driver's address * block, the appropriate callback routine is consulted and if it is * non-NULL it is called and passed a cmd1394_cmd_t structure used to * describe the incoming asynch request. */ typedef struct t1394_addr_evts { void (*recv_read_request)(cmd1394_cmd_t *req); void (*recv_write_request)(cmd1394_cmd_t *req); void (*recv_lock_request)(cmd1394_cmd_t *req); } t1394_addr_evts_t; /* * t1394_alloc_addr_t * is passed to t1394_alloc_addr(), when 1394 address space is being * allocated, to describe the type of address space. The target driver * is responsible for specifying the aa_enable, aa_type, and aa_evts * fields described above as well as the size of the allocated block. * Additionally, the target driver may specify backing store * (aa_kmem_bufp), a specific address (in aa_address if aa_type is * T1394_ADDR_FIXED), and a callback argument (in aa_arg) to be * passed to the target in any of its callback routines. * When it returns, t1394_alloc_addr() will return in aa_address the * starting address of the requested block of 1394 address space and * and address block handle (aa_hdl) used to free the address block * in a call to t1394_free_addr(). */ typedef struct t1394_alloc_addr { t1394_addr_type_t aa_type; /* IN: address region */ size_t aa_length; /* IN: # bytes requested */ t1394_addr_enable_t aa_enable; /* IN: request enables */ t1394_addr_evts_t aa_evts; /* IN: event callbacks */ opaque_t aa_arg; /* IN: evt callback arg */ caddr_t aa_kmem_bufp; /* IN: backing-store buf */ uint64_t aa_address; /* IN/OUT: alloced address */ t1394_addr_handle_t aa_hdl; /* OUT: returned to target */ } t1394_alloc_addr_t; /* * t1394_fcp_evts_t * is used in t1394_fcp_register_controller(). FCP only allows writes. */ typedef struct t1394_fcp_evts { int (*fcp_write_request)(cmd1394_cmd_t *req); opaque_t fcp_arg; } t1394_fcp_evts_t; /* values returned by the FCP callback */ enum { T1394_REQ_CLAIMED, /* request is recognized by the target */ T1394_REQ_UNCLAIMED /* request is not recognized by the target */ }; /* * t1394_cmp_reg_t * CMP register types */ typedef enum { T1394_CMP_OMPR, /* oMPR */ T1394_CMP_IMPR /* iMPR */ } t1394_cmp_reg_t; /* * t1394_cmp_evts_t * is used in t1394_cmp_register(). */ typedef struct t1394_cmp_evts { void (*cmp_reg_change)(opaque_t, t1394_cmp_reg_t); opaque_t cmp_arg; } t1394_cmp_evts_t; /* * t1394_isoch_rsrc_error_t * is used in the rsrc_fail_target() callback to indicate the reason * for the resource allocation failure. T1394_RSRC_BANDWIDTH indicates * that insufficient bandwidth was available for the requested allocation, * and T1394_RSRC_CHANNEL indicates that none of the requested channels * were available. */ typedef enum { T1394_RSRC_BANDWIDTH = 1, T1394_RSRC_CHANNEL = 2 } t1394_isoch_rsrc_error_t; /* * t1394_isoch_singleinfo_t * is passed to the t1394_alloc_isoch_single() routine. A target * driver will use this structure to indicate the channels it supports, * the maximum speed for the isochronous channel, the amount of * bandwidth required, and the callback (and callback arg) to be used * when notifying the target of resource reallocation failures. */ typedef struct t1394_isoch_singleinfo_s { uint64_t si_channel_mask; /* channels supported */ uint_t si_speed; /* 1394 speed for the channel */ uint_t si_bandwidth; /* max bytes per cycle */ void (*rsrc_fail_target)( t1394_isoch_single_handle_t t1394_single_hdl, opaque_t single_evt_arg, t1394_isoch_rsrc_error_t fail_args); opaque_t single_evt_arg; } t1394_isoch_singleinfo_t; /* * t1394_isoch_single_out_t * is filled in and returned to the target by the * t1394_alloc_isoch_single() routine. It indicates the number of the * channel that was actually allocated for the target driver. This * channel number will typically be used by a target driver to setup * isochronous DMA or other resources. */ typedef struct t1394_isoch_single_out_s { uint_t channel_num; /* number for the allocated channel */ } t1394_isoch_single_out_t; /* * t1394_setup_target_args_t * is used in the setup_target() callback to indicate the channel number * and channel speed for the isochronous channel coordinated by the * Isoch CEC routines. */ typedef struct t1394_setup_target_args_s { uint_t channel_num; /* number for the allocated channel */ uint_t channel_speed; /* 1394 speed for the channel */ } t1394_setup_target_args_t; /* * t1394_cec_options_t * is used in the t1394_isoch_cec_props_t structure, passed to * t1394_alloc_isoch_cec(). As the cec_options field in that * structure, it can be used to request that the 1394 Framework * NOT automatically reallocate the same isochronous channel and * bandwidth, if a bus reset happens. The default behavior is to * let the 1394 Framework attempt to reallocate the same channel and * bandwidth the target had after a bus reset, but some target drivers * may not require this functionality and they therefore have the option * to decline this service. */ typedef enum { T1394_NO_IRM_ALLOC = (1 << 0) } t1394_cec_options_t; /* * t1394_isoch_cec_props_t * is used in calls to the t1394_alloc_isoch_cec() routine. The * minimum and maximum speeds, channels supported, and the amount * of bandwidth necessary for the channel are specified. These * characteristics of the Isoch CEC are specified at allocation time * and are used to pass or fail targets that try to join the Isoch * CEC later. */ typedef struct t1394_isoch_cec_props_s { uint_t cec_min_speed; /* min speed supported */ uint_t cec_max_speed; /* max speed supported */ uint64_t cec_channel_mask; /* channels supported */ uint_t cec_bandwidth; /* max bytes per cycle */ t1394_cec_options_t cec_options; } t1394_isoch_cec_props_t; /* * t1394_isoch_cec_evts_t * is used in the t1394_join_isochinfo_t structure, passed to * t1394_join_isoch_cec(). This structure is a list of callbacks * for each of the various events the Isoch CEC is responsible for * coordinating. * The setup_target() callback is called after the isochronous * channel and bandwidth for the Isoch CEC have been allocated * (as a result of a call to t1394_setup_isoch_cec()) to inform the * member targets of the channel number and speed. * The start_target() callback is called for all member targets * as a result of a call to t1394_start_isoch_cec(). * The stop_target() callback is called for all member targets * as a result of a call to t1394_stop_isoch_cec(). * The rsrc_fail_target() callback (as mentioned above) is called * to indicate that the 1394 Framework was unable to reallocate * isochronous resources and the reason for the failure. * And the teardown_target() callback is called as a result of * a call to t1394_teardown_isoch_cec() to indicate that the * isochronous channel and bandwidth are being freed up. */ typedef struct t1394_isoch_cec_evts_s { int (*setup_target)( t1394_isoch_cec_handle_t t1394_isoch_cec_hdl, opaque_t isoch_cec_evts_arg, t1394_setup_target_args_t *setup_args); int (*start_target)( t1394_isoch_cec_handle_t t1394_isoch_cec_hdl, opaque_t isoch_cec_evts_arg); void (*stop_target)( t1394_isoch_cec_handle_t t1394_isoch_cec_hdl, opaque_t isoch_cec_evts_arg); void (*rsrc_fail_target)( t1394_isoch_cec_handle_t t1394_isoch_cec_hdl, opaque_t isoch_cec_evts_arg, t1394_isoch_rsrc_error_t fail_args); void (*teardown_target)( t1394_isoch_cec_handle_t t1394_isoch_cec_hdl, opaque_t isoch_cec_evts_arg); } t1394_isoch_cec_evts_t; /* * t1394_jii_options_t * is used in the t1394_join_isochinfo_t structure, passed to * t1394_join_isoch_cec(). As the jii_options field in that * structure, it is used to indicate to the 1394 Framework * that the member target is the talker on the channel. There can * be no more than one talker per Isoch CEC, and a member target * may fail in t1394_join_isoch_cec() because there is already a * talker on the Isoch CEC. */ typedef enum { T1394_TALKER = (1 << 0) } t1394_jii_options_t; /* * t1394_join_isochinfo_t * is used in calls to the t1394_join_isoch_cec() routine. The * req_channel_mask field indicate the channels that a member * target can support. If these channels are inconsistent with * the characteristics passed in at allocation or with the current * characteristics of the other members of the Isoch CEC, then the * t1394_join_isoch_cec() call will fail. * The req_max_speed field is used similarly. If the member target's * maximum speed is inconsistent with the other members of the * Isoch CEC, then the t1394_join_isoch_cec() will fail. * In addition to the above fields, a joining member target will pass * the jii_options (indicate talker or listener), the callbacks and * the callback arg (see above). */ typedef struct t1394_join_isochinfo_s { uint64_t req_channel_mask; /* target chnls supported */ uint_t req_max_speed; /* target max_speed */ t1394_jii_options_t jii_options; opaque_t isoch_cec_evts_arg; t1394_isoch_cec_evts_t isoch_cec_evts; } t1394_join_isochinfo_t; /* * t1394_targetinfo_t * is used in calls to the t1394_get_targetinfo() routine. The * structure returned to the target contains current_max_payload, * the default maximum block size that the host device will use in * asynchronous block reads and writes to the target's device. * It also contains current_max_speed, the default maximum speed at * which the host device will communicate with the target's device. * The structure also contains the target driver's target nodeID, * the number assigned to the device for the current bus * generation. It will contain T1394_INVALID_NODEID if the target * device is no longer connected to the 1394 Serial Bus. */ typedef struct t1394_targetinfo_s { uint_t current_max_payload; uint_t current_max_speed; uint_t target_nodeID; } t1394_targetinfo_t; #define T1394_INVALID_NODEID 0xFFFF /* * t1394_cfgrom_entryinfo_t * is used in calls to the t1394_add_cfgrom_entry() routine. The * t1394_cfgrom_entryinfo_t structure contains the information necessary * to add the Config ROM entry. The ce_buffer and ce_size are used to * describe the data to be added, and the ce_key is used to indicate * what type of entry in the Config ROM buffer the data represents * (see ieee1212.h fro key types). */ typedef struct t1394_cfgrom_entryinfo_s { uint_t ce_key; /* key for Root Dir. entry */ size_t ce_size; /* size of the buffer */ uint32_t *ce_buffer; /* buffer for Config ROM data */ } t1394_cfgrom_entryinfo_t; /* * ATTACH and DETACH: * These are the calls into 1394 Framework used during target driver * attach() and detach(). The t1394_attach() routine takes a dip and * a version (T1394_VERSION_V1) as its input arguments, and it fills * in and returns a t1394_attachinfo_t structure (described above) and * the t1394_handle_t. This target handle is used in all subsequent * calls into the 1394 Framework. * The t1394_detach() routine is called from a target driver's detach() * routine to unregister itself from the 1394 Framework. */ int t1394_attach(dev_info_t *dip, int version, uint_t flags, t1394_attachinfo_t *attachinfo, t1394_handle_t *t1394_hdl); /* Version value */ #define T1394_VERSION_V1 1 int t1394_detach(t1394_handle_t *t1394_hdl, uint_t flags); /* * OUTGOING ASYNCHRONOUS COMMANDS: * These are the calls into 1394 Framework used for allocating/freeing * and sending (outgoing) asynchronous requests. The t1394_alloc_cmd() * routine takes a target driver's handle as an input argument and * returns the cmd1394_cmd_t structure necessary for sending asynch * requests. The flags parameter is used to indicate whether or not the * 1394 Framework may sleep while allocating memory for the command. * The t1394_free_cmd() routine is used to free up commands allocated * by t1394_alloc_cmd(). Commands should not be in use at the time * t1394_free_cmd() is called or the call may fail (return DDI_FAILURE). * After an asynch command has been allocated and filled in (see * the cmd1394.h file for more details) to indicate the type of request, * what types of options are necessary, callback functions and/or data * (if necessary), the command is passed to either t1394_read(), * t1394_write(), or t1394_lock(). These routines will return DDI_SUCCESS * or DDI_FAILURE depending on whether the command has been successfully * accepted by the 1394 Framework. If the command is a "blocking" * command, the function will not return until the command has completed. * If, however, a callback has been specified in the command, that * function will be called when the command completes. */ int t1394_alloc_cmd(t1394_handle_t t1394_hdl, uint_t flags, cmd1394_cmd_t **cmdp); /* Flags passed to t1394_alloc_cmd() */ #define T1394_ALLOC_CMD_NOSLEEP 0x00000001 /* don't sleep in alloc */ #define T1394_ALLOC_CMD_FCP_COMMAND 0x00010000 /* FCP command */ #define T1394_ALLOC_CMD_FCP_RESPONSE 0x00020000 /* FCP response */ int t1394_free_cmd(t1394_handle_t t1394_hdl, uint_t flags, cmd1394_cmd_t **cmdp); int t1394_read(t1394_handle_t t1394_hdl, cmd1394_cmd_t *cmd); int t1394_write(t1394_handle_t t1394_hdl, cmd1394_cmd_t *cmd); int t1394_lock(t1394_handle_t t1394_hdl, cmd1394_cmd_t *cmd); /* * 1394 ADDRESS SPACE AND INCOMING ASYNCHRONOUS COMMANDS: * These are the calls into the 1394 Framework used for allocating/freeing * 1394 address space and handling incoming asynchronous requests. The * t1394_alloc_addr() routine is used to allocate 1394 address space. It * is passed the target handle and a t1394_alloc_addr_t structure * (described above). * The t1394_free_addr() routine is used to free any allocated address * space that the target may have. Typically, this will be done in a * target driver's detach() routine (before calling t1394_detach()). * The t1394_recv_request_done() routine is used after a target has * received and handled an incoming asynch request. It is used to send * a response to the request. After the command is sent to * t1394_recv_request_done(), it should not be modified or used because * the 1394 Framework may free it up without notifying the target driver. */ int t1394_alloc_addr(t1394_handle_t t1394_hdl, t1394_alloc_addr_t *addr_allocp, uint_t flags, int *result); /* Results codes returned by t1394_alloc_addr() */ #define T1394_EALLOC_ADDR (-400) #define T1394_EADDR_FIRST T1394_EALLOC_ADDR #define T1394_EADDR_LAST T1394_EALLOC_ADDR /* * NOTE: Make sure T1394_EADDR_LAST is updated if a new error code is * added. t1394_errmsg.c uses *FIRST and *LAST as bounds checks. */ int t1394_free_addr(t1394_handle_t t1394_hdl, t1394_addr_handle_t *addr_hdl, uint_t flags); int t1394_recv_request_done(t1394_handle_t t1394_hdl, cmd1394_cmd_t *resp, uint_t flags); /* * FCP SERVICES: * Function Control Protocol (FCP) is defined in IEC 61883-1 and supported * by the 1394 Framework. While target drivers could use t1394_alloc_addr() * and standard asynchronous services, only one driver could use FCP at a * time, because the FCP addresses have fixed values. To allow sharing of * FCP address space, the following Framework services should be used. * * t1394_fcp_register_controller() registers the target as an FCP controller, * which allows it to write into target's FCP command register and receive * write requests into host's FCP response register. It takes a valid * t1394_handle_t argument, hence it should be called after t1394_attach(). * t1394_fcp_unregister_controller() unregisters the target. * * t1394_fcp_register_target() and t1394_fcp_unregister_target() are * target counterparts of the above controller functions. */ int t1394_fcp_register_controller(t1394_handle_t t1394_hdl, t1394_fcp_evts_t *evts, uint_t flags); int t1394_fcp_unregister_controller(t1394_handle_t t1394_hdl); int t1394_fcp_register_target(t1394_handle_t t1394_hdl, t1394_fcp_evts_t *evts, uint_t flags); int t1394_fcp_unregister_target(t1394_handle_t t1394_hdl); /* * CMP services: * Connection Management Procedures (CMP) is defined in IEC 61883-1 and * supported by the 1394 Framework by providing the drivers with shared * access to iMPR and oMPR registers, which are created by the Framework * when t1394_cmp_register() is called and destroyed when * t1394_cmp_unregister() is called. These registers can be read using * t1394_cmp_read() function and compare-swapped using t1394_cmp_cas(). * * oPCR and iPCR registers can be allocated by the drivers using * t1394_alloc_addr() function. */ int t1394_cmp_register(t1394_handle_t t1394_hdl, t1394_cmp_evts_t *evts, uint_t flags); int t1394_cmp_unregister(t1394_handle_t t1394_hdl); int t1394_cmp_read(t1394_handle_t t1394_hdl, t1394_cmp_reg_t reg, uint32_t *valp); int t1394_cmp_cas(t1394_handle_t t1394_hdl, t1394_cmp_reg_t reg, uint32_t arg_val, uint32_t new_val, uint32_t *old_valp); /* * ISOCHRONOUS SERVICES: * These are the calls into the 1394 Framework used for isochronous * services. The t1394_alloc_isoch_single() routine takes a target * handle and a t1394_isoch_singleinfo_t structure (see above). It will * attempt to setup an isochronous channel (which will be automatically * reallocated after bus resets), and it will return the channel number * of the allocated channel in the t1394_isoch_single_out_t structure. * Additionally, it returns a t1394_isoch_single_handle_t structure * which is passed to t1394_free_isoch_single() when the isochronous * channel is no longer required. * The t1394_alloc_isoch_cec() and t1394_free_isoch_cec() are used to * allocate and free an Isoch Channel Event Coordinator (CEC). Target * drivers pass a t1394_isoch_cec_props_t structure (described above) * to specify the initial characteristics of the Isoch CEC. * Targets will subsequently join the Isoch CEC with t1394_join_isoch_cec() * before setting up the channel with t1394_setup_isoch_cec(). * Calls to t1394_join_isoch_cec() are used by targets who wish to join * the Isoch CEC and receive all of the channel event notifications. * When they want to leave target drivers call t1394_leave_isoch_cec(). * The t1394_setup_isoch_cec(), as described above, is used to setup the * the isochronous channel and bandwidth and to notify all member targets * of the allocated channel number and speed. After targets have finished * using the isoch channel, the resources can be torn down with a call to * t1394_teardown_isoch_cec(). * Additionally, the t1394_start_isoch_cec() and t1394_stop_isoch_cec() * routines can be used by member targets to coordinate additional events, * such as the starting and stopping of isochronous DMA or other resources. */ int t1394_alloc_isoch_single(t1394_handle_t t1394_hdl, t1394_isoch_singleinfo_t *sii, uint_t flags, t1394_isoch_single_out_t *output_args, t1394_isoch_single_handle_t *t1394_single_hdl, int *result); void t1394_free_isoch_single(t1394_handle_t t1394_hdl, t1394_isoch_single_handle_t *t1394_single_hdl, uint_t flags); int t1394_alloc_isoch_cec(t1394_handle_t t1394_hdl, t1394_isoch_cec_props_t *props, uint_t flags, t1394_isoch_cec_handle_t *t1394_isoch_cec_hdl); int t1394_free_isoch_cec(t1394_handle_t t1394_hdl, uint_t flags, t1394_isoch_cec_handle_t *t1394_isoch_cec_hdl); int t1394_join_isoch_cec(t1394_handle_t t1394_hdl, t1394_isoch_cec_handle_t t1394_isoch_cec_hdl, uint_t flags, t1394_join_isochinfo_t *join_isoch_info); int t1394_leave_isoch_cec(t1394_handle_t t1394_hdl, t1394_isoch_cec_handle_t t1394_isoch_cec_hdl, uint_t flags); int t1394_setup_isoch_cec(t1394_handle_t t1394_hdl, t1394_isoch_cec_handle_t t1394_isoch_cec_hdl, uint_t flags, int *result); /* Results codes returned by t1394_setup_isoch_cec() */ #define T1394_ENO_BANDWIDTH (-500) #define T1394_ENO_CHANNEL (-501) #define T1394_ETARGET (-502) #define T1394_CEC_ERR_FIRST T1394_ENO_BANDWIDTH #define T1394_CEC_ERR_LAST T1394_ETARGET /* * NOTE: Make sure T1394_ERR_LAST is updated if a new error code is * added. t1394_errmsg.c uses *FIRST and *LAST as bounds checks. */ int t1394_start_isoch_cec(t1394_handle_t t1394_hdl, t1394_isoch_cec_handle_t t1394_isoch_cec_hdl, uint_t flags); int t1394_stop_isoch_cec(t1394_handle_t t1394_hdl, t1394_isoch_cec_handle_t t1394_isoch_cec_hdl, uint_t flags); int t1394_teardown_isoch_cec(t1394_handle_t t1394_hdl, t1394_isoch_cec_handle_t t1394_isoch_cec_hdl, uint_t flags); /* * ISOCHRONOUS DMA (LOCAL ISOCH DMA) SERVICES: * These are the calls into the 1394 Framework used for local * isochronous DMA services. The t1394_alloc_isoch_dma() routine * takes a target handle and an id1394_isoch_dmainfo_t structure * (see id1394.h for details) as its input arguments and returns a * t1394_isoch_dma_handle_t that the target driver will use with all * other local host DMA calls. After allocating a local host DMA * resource, a target driver may start and stop it as often as desired * using the t1394_start_isoch_dma() and t1394_stop_isoch_dma() calls. * The t1394_start_isoch_dma() takes an id1394_isoch_dma_ctrlinfo_t * structure (also discussed in more detail in id1394.h) as an * additional argument to indicate among other things the conditions * under which the host DMA will be started. * The t1394_free_isoch_dma() is used, not surprisingly, to free up * allocate isoch DMA resources. * And the t1394_update_isoch_dma() routine is used to update a running * isochronous stream. By creating and passing a temporary IXL command * or set of commands and both the kernel virtual addresses of the * temporary and original commands, a target driver can request that the * 1394 Framework replace the original field contents with those in the * temporary command and update the corresponding hardware DMA elements. */ int t1394_alloc_isoch_dma(t1394_handle_t t1394_hdl, id1394_isoch_dmainfo_t *idi, uint_t flags, t1394_isoch_dma_handle_t *t1394_idma_hdl, int *result); /* * Results codes returned by t1394_alloc_isoch_dma(). See ixl1394.h for possible * IXL1394 compilation errors. * NOTE: Make sure T1394_IDMA_ERR_LAST is updated if a new error code is * added. */ #define T1394_EIDMA_NO_RESRCS (-600) #define T1394_EIDMA_CONFLICT (-601) #define T1394_IDMA_ERR_FIRST T1394_EIDMA_NO_RESRCS #define T1394_IDMA_ERR_LAST T1394_EIDMA_CONFLICT void t1394_free_isoch_dma(t1394_handle_t t1394_hdl, uint_t flags, t1394_isoch_dma_handle_t *t1394_idma_hdl); int t1394_start_isoch_dma(t1394_handle_t t1394_hdl, t1394_isoch_dma_handle_t t1394_idma_hdl, id1394_isoch_dma_ctrlinfo_t *idma_ctrlinfo, uint_t flags, int *result); void t1394_stop_isoch_dma(t1394_handle_t t1394_hdl, t1394_isoch_dma_handle_t t1394_idma_hdl, uint_t flags); /* See ixl1394.h for possible IXL1394 t1394_update_isoch_dma() errors. */ int t1394_update_isoch_dma(t1394_handle_t t1394_hdl, t1394_isoch_dma_handle_t t1394_idma_hdl, id1394_isoch_dma_updateinfo_t *idma_updateinfo, uint_t flags, int *result); /* * MISCELLANEOUS SERVICES: * These are the calls into the 1394 Framework used for miscellaneous * services, including getting target information and topology map, * adding to and removing from local Config ROM, initiating bus resets, * etc. The t1394_get_targetinfo() routine is used to get information * about the target driver's device and about current bus conditions * that might be useful to a target. By passing the target handle and * current bus generation, a target driver can expect to receive a filled * in t1394_targetinfo_t structure (see above) that contains the * current_max_payload, current_max_speed, and device's nodeID. * The t1394_initiate_bus_reset() routine can be used by target drivers * to initiate a bus reset. This call should be used only when it is * absolutely imperative, however, as bus resets affect all devices on * the 1394 Serial Bus and excessive use of bus resets can have an * adverse effect on overall bus performance. * The t1394_get_topology_map() will return the TOPOLOGY_MAP (see * IEEE 1394-1995, Section 8.3.2.4.1) which is a list of SelfID packets * from the current bus generation. * The t1394_CRC16() call is used to calculate cyclic redundancy checks * (CRCs) necessary for use in Config ROM buffers. * The t1394_add_cfgrom_entry() and t1394_rem_cfgrom_entry() calls are * used, respectively, to add and remove entries from the local host * Config ROM buffer. (See above for a description of the * t1394_cfgrom_entryinfo_t structure.) * And the t1394_errmsg() routine is used to convert result codes which * have been returned by the 1394 Framework into character strings for * use in error messages. */ int t1394_get_targetinfo(t1394_handle_t t1394_hdl, uint_t bus_generation, uint_t flags, t1394_targetinfo_t *targetinfo); void t1394_initiate_bus_reset(t1394_handle_t t1394_hdl, uint_t flags); int t1394_get_topology_map(t1394_handle_t t1394_hdl, uint_t bus_generation, size_t tm_length, uint_t flags, uint32_t *tm_buffer); uint_t t1394_CRC16(uint32_t *d, size_t crc_length, uint_t flags); int t1394_add_cfgrom_entry(t1394_handle_t t1394_hdl, t1394_cfgrom_entryinfo_t *cfgrom_entryinfo, uint_t flags, t1394_cfgrom_handle_t *t1394_cfgrom_hdl, int *result); /* Results codes returned by t1394_add_cfgrom_entry() */ #define T1394_ECFGROM_FULL (-700) #define T1394_EINVALID_PARAM (-701) #define T1394_EINVALID_CONTEXT (-702) #define T1394_NOERROR (-703) #define T1394_ECFG_FIRST T1394_ECFGROM_FULL #define T1394_ECFG_LAST T1394_NOERROR /* * NOTE: Make sure T1394_ECFG_LAST is updated if a new error code is * added. t1394_errmsg.c uses *FIRST and *LAST as bounds checks. */ int t1394_rem_cfgrom_entry(t1394_handle_t t1394_hdl, uint_t flags, t1394_cfgrom_handle_t *t1394_cfgrom_hdl, int *result); const char *t1394_errmsg(int result, uint_t flags); #ifdef __cplusplus } #endif #endif /* _SYS_1394_T1394_H */ /* * 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 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #ifndef _SYS_1394_TARGETS_AV1394_IMPL_H #define _SYS_1394_TARGETS_AV1394_IMPL_H /* * av1394 driver definitions */ #include #include #include #include #include #include #include #include #ifdef __cplusplus extern "C" { #endif /* * byte swapping support, stolen from SBP2 */ #ifdef _LITTLE_ENDIAN #define AV_SWAP16(data) \ ((((data) & 0xff) << 8) | ((data) >> 8)) #define AV_SWAP32(data) \ (((uint32_t)AV_SWAP16((uint16_t)((data) & 0xffff)) << 16) | \ (uint32_t)AV_SWAP16((uint16_t)((data) >> 16))) #else #define AV_SWAP16(data) (data) #define AV_SWAP32(data) (data) #endif /* * double-linked list */ typedef struct av1394_list_item_s { struct av1394_list_item_s *i_next; struct av1394_list_item_s *i_prev; } av1394_list_item_t; typedef struct av1394_list_s { av1394_list_item_t *l_head; /* first item */ av1394_list_item_t *l_tail; /* last item */ int l_cnt; /* number of items */ } av1394_list_t; /* * queue */ typedef struct av1394_queue_s { kmutex_t q_mutex; /* mutex */ av1394_list_t q_list; /* list of mblk's */ int q_size; /* current data size */ int q_max; /* max data size */ kcondvar_t q_cv; /* data cv */ } av1394_queue_t; _NOTE(MUTEX_PROTECTS_DATA(av1394_queue_s::q_mutex, av1394_queue_s)) #define AV1394_ENTERQ(q) mutex_enter(&(q)->q_mutex) #define AV1394_LEAVEQ(q) mutex_exit(&(q)->q_mutex) /* * asynchronous module definitions * * * command structure */ typedef struct av1394_fcp_cmd_s { cmd1394_cmd_t *fc_cmd; /* 1394 command */ boolean_t fc_busy; /* command is in use */ kcondvar_t fc_busy_cv; /* busy cv */ boolean_t fc_xmit; /* transmit in progress */ kcondvar_t fc_xmit_cv; /* transmit completion cv */ } av1394_fcp_cmd_t; /* * per-instance FCP structure */ typedef struct av1394_fcp_s { av1394_fcp_cmd_t fcp_cmd; /* outgoing FCP command */ av1394_fcp_cmd_t fcp_resp; /* outgoing FCP response */ } av1394_fcp_t; enum { AV1394_FCP_ARQ_LEN_MAX = 0x200 /* maximum FCP ARQ length */ }; /* * configuration ROM */ #define AV1394_CFGROM_INFO_LEN_ADDR (IEEE1394_CONFIG_ROM_ADDR + 0x00) #define AV1394_CFGROM_BUS_NAME_ADDR (IEEE1394_CONFIG_ROM_ADDR + 0x04) #define AV1394_CFGROM_EUI64_HI_ADDR (IEEE1394_CONFIG_ROM_ADDR + 0x0c) #define AV1394_CFGROM_EUI64_LO_ADDR (IEEE1394_CONFIG_ROM_ADDR + 0x10) /* offsets in quadlets */ #define AV1394_CFGROM_BUS_NAME_OFF 1 #define AV1394_CFGROM_EUI64_HI_OFF 3 #define AV1394_CFGROM_EUI64_LO_OFF 4 typedef struct av1394_cfgrom_text_leaf_s { uint64_t tl_addr; /* leaf entry address */ uint32_t tl_desc_entry; /* entry described by this leaf */ } av1394_cfgrom_text_leaf_t; typedef struct av1394_cfgrom_parsed_dir_s { av1394_cfgrom_text_leaf_t *pd_tl; /* text leaf array */ int pd_tl_size; /* total # of array entries */ int pd_tl_next; /* first unused entry index */ } av1394_cfgrom_parsed_dir_t; typedef struct av1394_cfgrom_parse_arg_s { int pa_depth; /* parser depth */ uint32_t pa_desc_entry; /* described entry */ uint8_t pa_parent_k; /* parent entry's key value */ uint64_t pa_addr; /* directory address */ uint16_t pa_len; /* directory length */ av1394_cfgrom_parsed_dir_t *pa_dir; /* current directory */ } av1394_cfgrom_parse_arg_t; enum { AV1394_CFGROM_PARSE_MAX_DEPTH = 5 /* maximum parse depth */ }; typedef struct av1394_cfgrom_s { krwlock_t cr_rwlock; /* structure lock */ boolean_t cr_parsed; /* node ConfigROM was parsed */ av1394_cfgrom_parsed_dir_t cr_root_dir; /* root directory */ av1394_cfgrom_parsed_dir_t cr_unit_dir; /* unit directory */ } av1394_cfgrom_t; /* * async command */ typedef struct av1394_async_cmd_s { kmutex_t ac_mutex; boolean_t ac_busy; kcondvar_t ac_cv; cmd1394_cmd_t *ac_cmd; } av1394_async_cmd_t; /* * per-instance soft state structure */ typedef struct av1394_async_s { kmutex_t a_mutex; /* structure mutex */ int a_nopen; /* number of opens */ int a_oflag; /* open flags */ t1394_targetinfo_t a_targetinfo; /* target info */ uint_t a_bus_generation; /* bus generation */ av1394_fcp_t a_fcp; /* FCP module */ av1394_cfgrom_t a_cfgrom; /* config ROM module */ av1394_queue_t a_rq; /* read queue */ struct pollhead a_pollhead; /* poll(2) support */ short a_pollevents; /* polled events */ } av1394_async_t; _NOTE(MUTEX_PROTECTS_DATA(av1394_async_s::a_mutex, av1394_async_s)) _NOTE(DATA_READABLE_WITHOUT_LOCK(av1394_async_s::{ a_oflag })) /* we use special message types for the read queue */ enum { AV1394_M_FCP_RESP = 0x01, /* FCP response */ AV1394_M_FCP_CMD = 0x02, /* FCP command */ AV1394_M_BUS_RESET = 0x03, /* bus reset event */ /* * For efficiency, we only store 1394 request data on the read queue. * ARQ headers (iec61883_arq_t) are generated when an application * calls read(2). Because applications may read header separately * from the data, we need to mark each mblk when its header was read * but not the data - the following flag is used for this purpose. */ AV1394_M_NOHDR = 0x80 }; #define AV1394_DBTYPE(bp) (DB_TYPE(bp) & ~AV1394_M_NOHDR) #define AV1394_MARK_NOHDR(bp) (DB_TYPE(bp) |= AV1394_M_NOHDR) #define AV1394_IS_NOHDR(bp) (DB_TYPE(bp) & AV1394_M_NOHDR) /* * device state: * * AV1394_DEV_DISCONNECTED * | | ^ * | | | * detach reconnect disconnect * | | | * v v | * AV1394_DEV_INIT ----attach---> AV1394_DEV_ONLINE * (initial state) <---detach--- | ^ * | | * cpr suspend cpr resume * | | * v | * AV1394_DEV_SUSPENDED */ typedef enum { AV1394_DEV_INIT = 0, AV1394_DEV_ONLINE, AV1394_DEV_SUSPENDED, AV1394_DEV_DISCONNECTED } av1394_dev_state_t; /* * per-instance soft state structure */ typedef struct av1394_inst_s { kmutex_t av_mutex; /* structure mutex */ dev_info_t *av_dip; /* device information */ int av_instance; /* instance number */ av1394_dev_state_t av_dev_state; /* device state */ av1394_dev_state_t av_prev_dev_state; /* previous device state */ t1394_attachinfo_t av_attachinfo; /* 1394 attach info */ t1394_handle_t av_t1394_hdl; /* 1394 handle */ av1394_async_t av_a; /* asynchronous module */ av1394_isoch_t av_i; /* isochronous module */ ddi_callback_id_t av_reset_cb; /* reset event cb id */ ddi_callback_id_t av_remove_cb; /* remove event cb id */ ddi_callback_id_t av_insert_cb; /* insert event cb id */ } av1394_inst_t; _NOTE(MUTEX_PROTECTS_DATA(av1394_inst_s::av_mutex, av1394_inst_s::{ av_dip av_instance av_attachinfo av_t1394_hdl })) /* these are set during attach (single-threaded) and don't change afterwards */ _NOTE(DATA_READABLE_WITHOUT_LOCK(av1394_inst_s::{ av_dip av_instance av_attachinfo av_t1394_hdl })) _NOTE(SCHEME_PROTECTS_DATA("one per call", msgb datab cmd1394_cmd iec61883_arq_t iec61883_isoch_init_t iec61883_plug_init_t)) /* * minor <-> instance mapping */ #define AV1394_MINOR_TYPE_MASK (1 << (NBITSMINOR32 - 1)) #define AV1394_ISOCH_INST2MINOR(inst) (inst) #define AV1394_ASYNC_INST2MINOR(inst) ((inst) | AV1394_MINOR_TYPE_MASK) #define AV1394_DEV_IS_ISOCH(dev) \ ((getminor(dev) & AV1394_MINOR_TYPE_MASK) == 0) #define AV1394_DEV_IS_ASYNC(dev) \ ((getminor(dev) & AV1394_MINOR_TYPE_MASK) != 0) #define AV1394_DEV2INST(dev) \ ((getminor(dev)) & ~AV1394_MINOR_TYPE_MASK) /* misc constants */ enum { AV1394_CLEANUP_LEVEL_MAX = 256 }; /* current interface version */ #define AV1394_IEC61883_VER IEC61883_V1_0 /* misc */ #define NELEM(a) (sizeof (a) / sizeof (*(a))) /* double-linked list */ void av1394_list_init(av1394_list_t *lp); void *av1394_list_head(av1394_list_t *lp); void av1394_list_put_tail(av1394_list_t *lp, void *item); void av1394_list_put_head(av1394_list_t *lp, void *item); void *av1394_list_get_head(av1394_list_t *lp); /* queue */ void av1394_initq(av1394_queue_t *q, ddi_iblock_cookie_t ibc, int max); void av1394_destroyq(av1394_queue_t *q); void av1394_setmaxq(av1394_queue_t *q, int max); int av1394_getmaxq(av1394_queue_t *q); void av1394_flushq(av1394_queue_t *q); int av1394_putq(av1394_queue_t *q, mblk_t *bp); int av1394_putbq(av1394_queue_t *q, mblk_t *bp); mblk_t *av1394_getq(av1394_queue_t *q); mblk_t *av1394_peekq(av1394_queue_t *q); mblk_t *av1394_peekq_locked(av1394_queue_t *q); int av1394_qwait_sig(av1394_queue_t *q); /* FCP */ int av1394_fcp_attach(av1394_inst_t *); void av1394_fcp_detach(av1394_inst_t *); int av1394_fcp_open(av1394_inst_t *, int); int av1394_fcp_close(av1394_inst_t *, int); int av1394_fcp_write(av1394_inst_t *, iec61883_arq_t *, struct uio *); /* config ROM */ int av1394_cfgrom_init(av1394_inst_t *); void av1394_cfgrom_fini(av1394_inst_t *); void av1394_cfgrom_close(av1394_inst_t *); int av1394_ioctl_node_get_bus_name(av1394_inst_t *, void *, int); int av1394_ioctl_node_get_uid(av1394_inst_t *, void *, int); int av1394_ioctl_node_get_text_leaf(av1394_inst_t *, void *, int); /* async module */ int av1394_async_attach(av1394_inst_t *); void av1394_async_detach(av1394_inst_t *); int av1394_async_cpr_suspend(av1394_inst_t *); int av1394_async_cpr_resume(av1394_inst_t *); void av1394_async_bus_reset(av1394_inst_t *); void av1394_async_disconnect(av1394_inst_t *); void av1394_async_reconnect(av1394_inst_t *); int av1394_async_open(av1394_inst_t *, int); int av1394_async_close(av1394_inst_t *, int); int av1394_async_read(av1394_inst_t *, struct uio *); int av1394_async_write(av1394_inst_t *, struct uio *); int av1394_async_ioctl(av1394_inst_t *, int, intptr_t, int, int *); int av1394_async_poll(av1394_inst_t *, short, int, short *, struct pollhead **); void av1394_async_putq_rq(av1394_inst_t *, mblk_t *); #ifdef __cplusplus } #endif #endif /* _SYS_1394_TARGETS_AV1394_IMPL_H */ /* * 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 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #ifndef _SYS_1394_TARGETS_AV1394_ISOCH_H #define _SYS_1394_TARGETS_AV1394_ISOCH_H /* * isoch module definitions */ #include #ifdef __cplusplus extern "C" { #endif #define COOKIES 100 /* * isoch DMA memory management: segments and pools * * isoch segment - a contiguous chunk of kernel memory */ typedef struct av1394_isoch_seg_s { caddr_t is_kaddr; /* segment kernel virt addr */ int is_size; /* segment size */ ddi_umem_cookie_t is_umem_cookie; /* umem cookie */ size_t is_umem_size; /* umem size (page-aligned) */ ddi_dma_handle_t is_dma_hdl; /* bind handle */ ddi_dma_cookie_t is_dma_cookie[COOKIES]; /* dma cookie */ uint_t is_dma_ncookies; /* # of cookies */ } av1394_isoch_seg_t; /* * isoch pool - a set of one or more isoch segments */ typedef struct av1394_isoch_pool_s { av1394_isoch_seg_t *ip_seg; /* array of segments */ int ip_nsegs; /* # of valid segments */ int ip_alloc_size; /* array alloc'd size */ int ip_size; /* total pool size */ int ip_umem_size; /* total alloc'd memory size */ } av1394_isoch_pool_t; /* * many members are protected because they are modified during channel * initialization or/and during isoch transfer, both of which are * single-threaded processes. after that these members remain read-only. */ _NOTE(SCHEME_PROTECTS_DATA("single-threaded", av1394_isoch_seg_s)) _NOTE(SCHEME_PROTECTS_DATA("single-threaded", av1394_isoch_pool_s)) /* * IXL receive data block (one or more RECV_BUF commands will follow the label) */ typedef struct av1394_ir_ixl_data_s { ixl1394_label_t rd_label; ixl1394_callback_t rd_cb; /* buffer completion callback */ ixl1394_jump_t rd_jump; /* next command */ } av1394_ir_ixl_data_t; _NOTE(SCHEME_PROTECTS_DATA("single-threaded", av1394_ir_ixl_data_s)) /* * isoch receive structure */ typedef struct av1394_ir_s { av1394_isoch_pool_t ir_data_pool; /* pool for data packets */ /* IXL */ ixl1394_command_t *ir_ixlp; /* IXL chain */ av1394_ir_ixl_data_t *ir_ixl_data; /* data block array */ ixl1394_xfer_buf_t *ir_ixl_buf; /* RECV_BUF command array */ int ir_ixl_nbufs; /* # of commands in array */ size_t ir_ixl_bpf; /* # of buffers per frame - 1 */ size_t ir_ixl_bufsz; /* buffer size */ size_t ir_ixl_tailsz; /* tail buffer size */ /* xfer */ int ir_nfull; /* # of full frames */ int ir_first_full; /* first full frame */ int ir_nempty; /* # of empty frames */ int ir_last_empty; /* last produced frame */ int ir_hiwat; /* high water mark */ int ir_lowat; /* low water mark */ int ir_overflow_idx; /* overflow frame index */ /* read() support */ int ir_read_idx; /* first full frame */ int ir_read_cnt; /* number of full frames */ off_t ir_read_off; /* offset into the frame */ } av1394_ir_t; _NOTE(SCHEME_PROTECTS_DATA("single-threaded", av1394_ir_s::{ ir_ixlp ir_ixl_buf ir_ixl_nbufs ir_ixl_bpf ir_ixl_bufsz ir_ixl_tailsz })) /* * IXL transmit begin block, used to get a starting point for timestamping */ enum { AV1394_IT_IXL_BEGIN_NPOST = 3 }; typedef struct av1394_it_ixl_begin_s { ixl1394_label_t be_label; ixl1394_xfer_pkt_t be_empty_pre; /* needed for next command */ ixl1394_store_timestamp_t be_store_ts; /* store timestamp */ ixl1394_callback_t be_cb; /* timestamp handling */ ixl1394_xfer_pkt_t be_empty_post[AV1394_IT_IXL_BEGIN_NPOST]; ixl1394_jump_t be_jump; /* next command */ } av1394_it_ixl_begin_t; _NOTE(SCHEME_PROTECTS_DATA("single-threaded", av1394_it_ixl_begin_s)) /* * common part of transmit commands that are in a linked list */ typedef struct av1394_it_ixl_common_s { struct av1394_it_ixl_common_s *tc_next; /* next in the list */ int tc_size; /* structure size */ } av1394_it_ixl_common_t; /* * IXL transmit data block */ typedef struct av1394_it_ixl_buf_s { av1394_it_ixl_common_t tb_common; int tb_flags; int tb_framenum; /* frame number */ struct av1394_ic_s *tb_icp; ixl1394_label_t tb_label; ixl1394_xfer_buf_t tb_buf; /* transmit packets */ ixl1394_store_timestamp_t tb_store_ts; /* cycle time feedback */ ixl1394_callback_t tb_cb; /* callback */ ixl1394_jump_t tb_jump; /* next command */ } av1394_it_ixl_buf_t; _NOTE(SCHEME_PROTECTS_DATA("single-threaded", av1394_it_ixl_buf_s)) /* tb_flags */ enum { AV1394_IT_IXL_BUF_NEXT_EMPTY = 0x01, /* followed by empty CIP */ AV1394_IT_IXL_BUF_SOF = 0x02, /* start of frame */ AV1394_IT_IXL_BUF_EOF = 0x04 /* end of frame */ }; /* * empty CIP */ typedef struct av1394_it_ixl_empty_cip_s { av1394_it_ixl_common_t te_common; ixl1394_label_t te_label; ixl1394_xfer_pkt_t te_pkt; ixl1394_jump_t te_jump; /* next command */ } av1394_it_ixl_empty_cip_t; _NOTE(SCHEME_PROTECTS_DATA("single-threaded", av1394_it_ixl_empty_cip_s)) /* * per-frame information */ typedef struct av1394_it_frame_info_s { caddr_t fi_ts_off; /* where to put a timestamp */ int fi_ncycs; /* # of bus cycles */ av1394_it_ixl_buf_t *fi_first_buf; /* first IXL buffer */ av1394_it_ixl_buf_t *fi_last_buf; /* last IXL buffer */ } av1394_it_frame_info_t; _NOTE(SCHEME_PROTECTS_DATA("single-threaded", av1394_it_frame_info_s)) /* * timestamp type */ typedef union av1394_it_ts { uint16_t ts_syt; /* SYT timestamp */ } av1394_it_ts_t; /* * isoch transmit structure */ typedef struct av1394_it_s { av1394_isoch_pool_t it_data_pool; /* pool for data packets */ /* IXL */ ixl1394_command_t *it_ixlp; /* IXL chain */ av1394_it_ixl_begin_t it_ixl_begin; /* begin block */ av1394_it_ixl_common_t *it_ixl_data; /* data block */ av1394_it_frame_info_t *it_frame_info; /* frame info array */ av1394_it_ixl_empty_cip_t *it_skipped_cip; /* last skipped CIP */ /* xfer */ int it_first_empty; /* first empty frame # */ int it_nempty; /* # of empty frames */ int it_last_full; /* last full frame # */ int it_nfull; /* # of full frames */ int it_hiwat; /* high water mark */ int it_lowat; /* low water mark */ int it_start_thre; /* xfer start threshold */ av1394_it_ts_t it_ts_init; /* initial timestamp */ /* underrun data */ int it_underrun_idx; /* underrun frame index */ ixl1394_command_t *it_saved_label; /* saved buffer label */ /* write() support */ int it_write_idx; /* first empty frame */ int it_write_cnt; /* # of empty frames */ off_t it_write_off; /* offset into the frame */ } av1394_it_t; _NOTE(SCHEME_PROTECTS_DATA("single-threaded", av1394_it_s::{ it_ixlp it_ixl_begin it_ixl_data it_frame_info it_ts_init it_skipped_cip })) /* misc channel parameters */ typedef struct av1394_ic_param_s { int cp_bus_speed; /* bus speed */ int cp_dbs; /* DBS */ int cp_fn; /* FN */ int cp_n; /* rate numerator */ int cp_d; /* rate denominator */ int cp_ts_mode; /* timestamp mode */ } av1394_ic_param_t; /* channel state */ typedef enum { AV1394_IC_IDLE, /* nothing happens */ AV1394_IC_STARTED, /* channel has been started */ AV1394_IC_DMA, /* DMA transfer is in progress */ AV1394_IC_SUSPENDED /* transfer on the channel suspended */ } av1394_ic_state_t; /* * isoch channel structure, common for both recv and xmit */ typedef struct av1394_ic_s { kmutex_t ic_mutex; /* structure mutex */ struct av1394_inst_s *ic_avp; /* backpointer to instance */ int ic_num; /* channel # */ int ic_dir; /* xfer direction */ av1394_ic_state_t ic_state; /* state */ int ic_pktsz; /* packet size */ int ic_npkts; /* # of packets/frame */ size_t ic_framesz; /* frame size (pktsz * npkts) */ int ic_nframes; /* # of frames */ av1394_ic_param_t ic_param; /* misc parameters */ size_t ic_mmap_sz; /* mmap size */ off_t ic_mmap_off; /* mmap offset */ t1394_isoch_single_handle_t ic_sii_hdl; /* isoch single handle */ t1394_isoch_dma_handle_t ic_isoch_hdl; /* 1394 isoch handle */ kcondvar_t ic_xfer_cv; /* xfer cv */ int ic_preq; /* postponed request */ av1394_ir_t ic_ir; /* recv */ av1394_it_t ic_it; /* xmit */ } av1394_ic_t; _NOTE(MUTEX_PROTECTS_DATA(av1394_ic_s::ic_mutex, av1394_ic_s)) _NOTE(SCHEME_PROTECTS_DATA("single-threaded", av1394_ic_s::{ ic_avp ic_num ic_dir ic_sii_hdl ic_isoch_hdl ic_pktsz ic_npkts ic_framesz ic_nframes ic_param ic_mmap_sz ic_mmap_off })) /* xfer directions */ enum { AV1394_IR, AV1394_IT }; /* CIP type */ enum { AV1394_CIP_FULL, AV1394_CIP_EMPTY }; /* misc constants */ enum { AV1394_IC_FRAME_SIZE_MAX = 1024 * 1024, /* max frame size */ AV1394_MEM_MAX_PERCENT = (100/10), /* max percent of physmem */ AV1394_SEGSZ_MAX_SHIFT = 16, /* maximum segment size */ AV1394_SEGSZ_MAX = (1UL << AV1394_SEGSZ_MAX_SHIFT), AV1394_SEGSZ_MAX_OFFSET = AV1394_SEGSZ_MAX - 1, AV1394_IXL_BUFSZ_MAX = 57344, /* max buf size (uint16_t) */ /* 57344 is ptob(btop(65535)) */ AV1394_IR_NFRAMES_MIN = 3, /* minimum frame count */ AV1394_IT_NFRAMES_MIN = 3, /* minimum frame count */ AV1394_CIPSZ = 8, /* CIP header size */ AV1394_DV_NTSC_FRAMESZ = 250, /* DV-NTSC frame size in pkts */ AV1394_DV_PAL_FRAMESZ = 300 /* DV-PAL frame size in pkts */ }; #define AV1394_TS_MODE_GET_OFF(mode) ((mode) & 0xff) #define AV1394_TS_MODE_GET_SIZE(mode) (((mode) >> 8) & 0xff) /* private ISOCH_INIT flag */ #define IEC61883_PRIV_ISOCH_NOALLOC 0x40000000 /* * autoxmit (isoch xmit via write(2)) support */ typedef struct av1394_isoch_autoxmit_s { uchar_t ax_ciph[AV1394_CIPSZ]; /* first CIP hdr */ boolean_t ax_copy_ciph; /* need to copy hdr */ int ax_fmt; /* data format */ } av1394_isoch_autoxmit_t; /* autoxmit formats */ enum { AV1394_ISOCH_AUTOXMIT_DV = 0x10, AV1394_ISOCH_AUTOXMIT_UNKNOWN = 0, AV1394_ISOCH_AUTOXMIT_DV_NTSC = 1 | AV1394_ISOCH_AUTOXMIT_DV, AV1394_ISOCH_AUTOXMIT_DV_PAL = 2 | AV1394_ISOCH_AUTOXMIT_DV }; /* * User processes calling mmap(2) pass the 'offset' and 'len' arguments, * returned by IEC61883_ISOCH_INIT ioctl. These arguments uniquely identify * the DMA buffer associated with a channel. For each isochronous channel * a part of this "address space" should be allocated to prevent conflicts * with other channels. */ typedef struct av1394_as_s { off_t as_end; /* address space end */ } av1394_as_t; /* * CMP (Connection Management Procedures) * * PCR address map (Ref: IEC 61883-1 Fig 14) */ #define AV1394_PCR_ADDR_START 0xFFFFF0000900 #define AV1394_PCR_ADDR_OMPR 0xFFFFF0000900 #define AV1394_PCR_ADDR_OPCR0 0xFFFFF0000904 #define AV1394_PCR_ADDR_NOPCR 31 #define AV1394_PCR_ADDR_IMPR 0xFFFFF0000980 #define AV1394_PCR_ADDR_IPCR0 0xFFFFF0000984 #define AV1394_PCR_ADDR_NIPCR 31 /* initial values and bus reset masks (Ref: IEC 61883-1 Fig 10-13) */ #define AV1394_OMPR_INIT_VAL 0xBFFFFF00 #define AV1394_IMPR_INIT_VAL 0x80FFFF00 #define AV1394_PCR_INIT_VAL 0x00000000 /* both iPCR and oPCR */ #define AV1394_OPCR_BR_CLEAR_MASK 0x7FC03C00 #define AV1394_IPCR_BR_CLEAR_MASK 0x7FC0FFFF /* * local plug control register */ typedef struct av1394_pcr_s { uint32_t pcr_val; /* value */ t1394_addr_handle_t pcr_addr_hdl; /* address handle */ } av1394_pcr_t; enum { AV1394_OMPR_IDX = 0, /* oMPR index */ AV1394_OPCR0_IDX = 1, /* oPCR0 index */ AV1394_IMPR_IDX = 32, /* iMPR index */ AV1394_IPCR0_IDX = 33, /* iPCR0 index */ AV1394_NPCR = 64 /* total number of PCRs */ }; /* plug handle manipulation */ enum { AV1394_PCR_REMOTE = 0x40000000 }; /* * per-instance CMP structure */ typedef struct av1394_cmp_s { krwlock_t cmp_pcr_rwlock; /* rwlock for PCRs */ av1394_pcr_t *cmp_pcr[AV1394_NPCR]; /* array of PCRs */ } av1394_cmp_t; _NOTE(SCHEME_PROTECTS_DATA("cmp_pcr_rwlock", av1394_cmp_s::cmp_pcr)) /* * per-instance soft state structure */ typedef struct av1394_isoch_s { kmutex_t i_mutex; /* structure mutex */ int i_nopen; /* number of opens */ av1394_cmp_t i_cmp; /* CMP information */ av1394_ic_t *i_ic[64]; /* array of channels */ av1394_as_t i_mmap_as; /* mmap virtual addr space */ ddi_softintr_t i_softintr_id; /* soft interrupt id */ uint64_t i_softintr_ch; /* channels to service */ av1394_isoch_autoxmit_t i_autoxmit; /* autoxmit support */ } av1394_isoch_t; _NOTE(MUTEX_PROTECTS_DATA(av1394_isoch_s::i_mutex, av1394_isoch_s)) _NOTE(DATA_READABLE_WITHOUT_LOCK(av1394_isoch_s::{ i_ic i_softintr_id })) _NOTE(SCHEME_PROTECTS_DATA("single-threaded", av1394_isoch_autoxmit_s)) _NOTE(LOCK_ORDER(av1394_isoch_s::i_mutex av1394_ic_s::ic_mutex)) /* postponed request types */ enum { AV1394_PREQ_IR_OVERFLOW = 0x01, AV1394_PREQ_IT_UNDERRUN = 0x02 }; /* isoch channel */ int av1394_ic_open(struct av1394_inst_s *, int); int av1394_ic_close(struct av1394_inst_s *, int); int av1394_ic_init(struct av1394_inst_s *avp, iec61883_isoch_init_t *ii, av1394_ic_t **icpp); void av1394_ic_fini(av1394_ic_t *icp); int av1394_ic_alloc_pool(av1394_isoch_pool_t *pool, size_t segsz, int cnt, int mincnt); void av1394_ic_free_pool(av1394_isoch_pool_t *pool); int av1394_ic_dma_setup(av1394_ic_t *icp, av1394_isoch_pool_t *pool); void av1394_ic_dma_cleanup(av1394_ic_t *icp, av1394_isoch_pool_t *pool); int av1394_ic_ixl_seg_decomp(size_t segsz, size_t pktsz, size_t *bufszp, size_t *tailszp); void av1394_ic_dma_sync_frames(av1394_ic_t *icp, int idx, int cnt, av1394_isoch_pool_t *pool, uint_t type); int av1394_ic_start(av1394_ic_t *icp); int av1394_ic_stop(av1394_ic_t *icp); void av1394_ic_ixl_dump(ixl1394_command_t *cmd); void av1394_ic_trigger_softintr(av1394_ic_t *icp, int num, int preq); /* isoch receive */ int av1394_ir_init(av1394_ic_t *icp, int *error); void av1394_ir_fini(av1394_ic_t *icp); int av1394_ir_start(av1394_ic_t *icp); int av1394_ir_stop(av1394_ic_t *icp); int av1394_ir_recv(av1394_ic_t *icp, iec61883_recv_t *recv); int av1394_ir_read(av1394_ic_t *icp, struct uio *uiop); void av1394_ir_overflow(av1394_ic_t *icp); /* isoch transmit */ int av1394_it_init(av1394_ic_t *icp, int *error); void av1394_it_fini(av1394_ic_t *icp); int av1394_it_start(av1394_ic_t *icp); int av1394_it_stop(av1394_ic_t *icp); int av1394_it_xmit(av1394_ic_t *icp, iec61883_xmit_t *xmit); int av1394_it_write(av1394_ic_t *icp, struct uio *uiop); void av1394_it_underrun(av1394_ic_t *icp); /* address space for mmap(2) */ void av1394_as_init(av1394_as_t *as); void av1394_as_fini(av1394_as_t *as); off_t av1394_as_alloc(av1394_as_t *as, size_t size); void av1394_as_free(av1394_as_t *as, off_t); /* CMP */ int av1394_cmp_init(struct av1394_inst_s *avp); void av1394_cmp_fini(struct av1394_inst_s *avp); void av1394_cmp_bus_reset(struct av1394_inst_s *avp); void av1394_cmp_close(struct av1394_inst_s *avp); int av1394_ioctl_plug_init(struct av1394_inst_s *, void *, int); int av1394_ioctl_plug_fini(struct av1394_inst_s *, void *, int); int av1394_ioctl_plug_reg_read(struct av1394_inst_s *, void *, int); int av1394_ioctl_plug_reg_cas(struct av1394_inst_s *, void *, int); /* isoch common */ int av1394_isoch_attach(struct av1394_inst_s *); void av1394_isoch_detach(struct av1394_inst_s *); int av1394_isoch_cpr_suspend(struct av1394_inst_s *); int av1394_isoch_cpr_resume(struct av1394_inst_s *); void av1394_isoch_bus_reset(struct av1394_inst_s *); void av1394_isoch_disconnect(struct av1394_inst_s *); void av1394_isoch_reconnect(struct av1394_inst_s *); int av1394_isoch_open(struct av1394_inst_s *, int); int av1394_isoch_close(struct av1394_inst_s *, int); int av1394_isoch_read(struct av1394_inst_s *, struct uio *); int av1394_isoch_write(struct av1394_inst_s *, struct uio *); int av1394_isoch_ioctl(struct av1394_inst_s *, int, intptr_t, int, int *); int av1394_isoch_devmap(struct av1394_inst_s *, devmap_cookie_t, offset_t, size_t, size_t *, uint_t); #ifdef __cplusplus } #endif #endif /* _SYS_1394_TARGETS_AV1394_ISOCH_H */ /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License, Version 1.0 only * (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 2005 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. * Copyright 2017 Joyent, Inc. */ #ifndef _SYS_1394_TARGETS_DCAM1394_DCAM_H #define _SYS_1394_TARGETS_DCAM1394_DCAM_H #include #include #include #include #include #include #ifdef __cplusplus extern "C" { #endif #define ILP32_PTR_SIZE 4 /* caller's data model type */ #define LP64_PTR_SIZE 8 #define DCAM_POWER_OFF 0 /* power management state */ #define DCAM_POWER_ON 1 #define DCAM1394_MINOR_CTRL 0x80 /* this is the control device */ #define DCAM1394_FLAG_ATTACH_COMPLETE 0x1 /* dcam_attach() is complete */ #define DCAM1394_FLAG_OPEN 0x2 /* driver is open */ #define DCAM1394_FLAG_OPEN_CAPTURE 0x4 /* device is open for capture */ #define DCAM1394_FLAG_OPEN_CONTROL 0x8 /* device is open for control */ #define DCAM1394_FLAG_FRAME_RCV_INIT 0x10 #define DCAM1394_FLAG_FRAME_RCVING 0x20 #define DCAM1394_FLAG_READ_REQ_PROC 0x40 #define DCAM1394_FLAG_READ_REQ_INVALID 0x80 #define IS_VALID 0x1 #define IS_PRESENT 0x2 #define CAP_GET 0x4 #define CAP_SET 0x8 #define CAP_CTRL_SET 0x10 #define MAX_STR_LEN 50 #define DEV_TO_INSTANCE(d) (getminor(d) & 0x7f) typedef uint_t dcam1394_param_attr_t[DCAM1394_NUM_PARAM][DCAM1394_NUM_SUBPARAM]; typedef struct buff_info_s { uint_t vid_mode; unsigned int seq_num; hrtime_t timestamp; caddr_t kaddr_p; /* kernel data buffer */ ddi_dma_handle_t dma_handle; /* bind handle */ ddi_acc_handle_t data_acc_handle; /* acc handle */ ddi_dma_cookie_t dma_cookie; /* cookie */ size_t real_len; /* mem len */ uint_t dma_cookie_count; /* cookie count */ } buff_info_t; #define MAX_NUM_READ_PTRS 1 typedef struct ring_buff_s { size_t num_buffs; size_t buff_num_bytes; buff_info_t *buff_info_array_p; int num_read_ptrs; int read_ptr_incr_val; size_t read_ptr_pos[MAX_NUM_READ_PTRS]; uint_t status[MAX_NUM_READ_PTRS]; size_t write_ptr_pos; } ring_buff_t; typedef struct dcam_state_s { dev_info_t *dip; int instance; int usr_model; t1394_handle_t sl_handle; t1394_attachinfo_t attachinfo; t1394_targetinfo_t targetinfo; t1394_isoch_singleinfo_t sii; t1394_isoch_single_out_t sii_output_args; t1394_isoch_single_handle_t sii_hdl; t1394_isoch_dma_handle_t isoch_handle; kmutex_t softc_mutex; kmutex_t dcam_frame_is_done_mutex; dcam1394_param_attr_t param_attr; ixl1394_command_t *ixlp; ring_buff_t *ring_buff_p; unsigned int seq_count; uint_t reader_flags[MAX_NUM_READ_PTRS]; uint_t flags; int cur_vid_mode; int cur_frame_rate; int cur_ring_buff_capacity; int param_status; int camera_online; int pm_open_count; int pm_cable_power; int suspended; ddi_callback_id_t event_id; } dcam_state_t; int _init(void); int _info(struct modinfo *modinfop); int _fini(void); int dcam_attach(dev_info_t *dip, ddi_attach_cmd_t cmd); int dcam_power(dev_info_t *dip, int component, int level); int dcam_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg, void **result); int dcam_identify(dev_info_t *dip); int dcam_detach(dev_info_t *dip, ddi_detach_cmd_t cmd); int dcam_open(dev_t *devp, int flag, int otyp, cred_t *credp); int dcam_close(dev_t dev, int flags, int otyp, cred_t *credp); int dcam_read(dev_t dev, struct uio *uio, cred_t *credp); int dcam_write(dev_t dev, struct uio *uio, cred_t *credp); int dcam_mmap(dev_t dev, off_t off, int prot); int dcam_devmap(dev_t dev, devmap_cookie_t dhp, offset_t off, size_t len, size_t *maplen, uint_t model); int dcam_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *credp, int *rvalp); int dcam_chpoll(dev_t dev, short events, int anyyet, short *reventsp, struct pollhead **phpp); int dcam_intr(caddr_t dcam_softc_p); void dcam_bus_reset_notify(dev_info_t *dip, ddi_eventcookie_t ev_cookie, void *arg, void *impl_data); ring_buff_t *ring_buff_create(dcam_state_t *softc_p, size_t num_buffs, size_t buff_num_bytes); void ring_buff_free(dcam_state_t *softc_p, ring_buff_t *ring_buff_p); int ring_buff_reader_add(ring_buff_t *ring_buff_p); int ring_buff_reader_remove(ring_buff_t *ring_buff_p, int reader_id); buff_info_t *ring_buff_read_ptr_buff_get(ring_buff_t *ring_buff_p, int reader_id); size_t ring_buff_read_ptr_pos_get(ring_buff_t *ring_buff_p, int read_ptr_id); void ring_buff_read_ptr_incr(ring_buff_t *ring_buff_p, int read_ptr_id); size_t ring_buff_write_ptr_pos_get(ring_buff_t *ring_buff_p); void ring_buff_write_ptr_incr(ring_buff_t *ring_buff_p); int dcam_frame_rcv_stop(dcam_state_t *softc_p); int dcam1394_ioctl_frame_rcv_start(dcam_state_t *softc_p); #ifdef __cplusplus } #endif #endif /* _SYS_1394_TARGETS_DCAM1394_DCAM_H */ /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License, Version 1.0 only * (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 2005 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #ifndef _SYS_1394_TARGETS_DCAM1394_FRAME_H #define _SYS_1394_TARGETS_DCAM1394_FRAME_H #ifdef __cplusplus extern "C" { #endif int dcam1394_ioctl_frame_rcv_start(dcam_state_t *softc_p); int dcam_frame_rcv_init(dcam_state_t *softc_p, int vid_mode, int frame_rate, int ring_buff_num_frames); int dcam_frame_rcv_fini(dcam_state_t *softc_p); int dcam_frame_rcv_start(dcam_state_t *softc_p); int dcam_frame_rcv_stop(dcam_state_t *softc_p); void dcam_frame_is_done(void *ssp, ixl1394_callback_t *ixlp); #ifdef __cplusplus } #endif #endif /* _SYS_1394_TARGETS_DCAM1394_FRAME_H */ /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License, Version 1.0 only * (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 2005 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #ifndef _SYS_1394_TARGETS_DCAM1394_PARAM_H #define _SYS_1394_TARGETS_DCAM1394_PARAM_H #ifdef __cplusplus extern "C" { #endif #define IS_VALID 0x1 #define IS_PRESENT 0x2 #define CAP_GET 0x4 #define CAP_SET 0x8 #define CAP_CTRL_SET 0x10 int param_attr_init(dcam_state_t *softc_p, dcam1394_param_attr_t param_attr); void param_attr_set(dcam1394_param_attr_t param_attr, uint_t param, uint_t subparam, uint_t attr_bmap); int dcam1394_ioctl_param_get(dcam_state_t *softc_p, dcam1394_param_list_t param_list); int dcam1394_ioctl_param_set(dcam_state_t *softc_p, int is_ctrl_file, dcam1394_param_list_t param_list); int dcam1394_param_get(dcam_state_t *softc_p, uint_t param, uint_t subparam, uint_t *val_p); int dcam1394_param_set(dcam_state_t *softc_p, uint_t param, uint_t subparam, uint_t val); int feature_get(dcam_state_t *softc_p, uint_t feature_csr_offs, uint_t feature_elm_inq_reg_offs, uint_t subparam, uint_t *val_p); int feature_set(dcam_state_t *softc_p, uint_t feature_csr_offs, uint_t subparam, uint_t val); int param_cap_power_ctrl_get(dcam_state_t *softc_p, uint_t *val_p); int param_cap_vid_mode_get(dcam_state_t *softc_p, uint_t subparam, uint_t *val_p); int param_cap_frame_rate_get(dcam_state_t *softc_p, uint_t param, uint_t subparam, uint_t *val_p); int param_power_get(dcam_state_t *softc_p, uint_t *val_p); int param_power_set(dcam_state_t *softc_p, uint_t val); int param_vid_mode_get(dcam_state_t *softc_p, uint_t *val_p); int param_vid_mode_set(dcam_state_t *softc_p, uint_t val); int param_frame_rate_get(dcam_state_t *softc_p, uint_t *val_p); int param_frame_rate_set(dcam_state_t *softc_p, uint_t val); int param_ring_buff_capacity_get(dcam_state_t *softc_p, uint_t *val_p); int param_ring_buff_capacity_set(dcam_state_t *softc_p, uint_t val); int param_ring_buff_num_frames_ready_get(dcam_state_t *softc_p, uint_t *val_p); int param_ring_buff_read_ptr_incr_get(dcam_state_t *softc_p, uint_t *val_p); int param_ring_buff_read_ptr_incr_set(dcam_state_t *softc_p, uint_t val); int param_frame_num_bytes_get(dcam_state_t *softc_p, uint_t *val_p); int param_status_get(dcam_state_t *softc_p, uint_t *val_p); int param_brightness_get(dcam_state_t *softc_p, uint_t subparam, uint_t *val_p); int param_brightness_set(dcam_state_t *softc_p, uint_t subparam, uint_t val); int param_exposure_get(dcam_state_t *softc_p, uint_t subparam, uint_t *val_p); int param_exposure_set(dcam_state_t *softc_p, uint_t subparam, uint_t val); int param_sharpness_get(dcam_state_t *softc_p, uint_t subparam, uint_t *val_p); int param_sharpness_set(dcam_state_t *softc_p, uint_t subparam, uint_t val); int param_white_balance_get(dcam_state_t *softc_p, uint_t subparam, uint_t *val_p); int param_white_balance_set(dcam_state_t *softc_p, uint_t subparam, uint_t val); int param_hue_get(dcam_state_t *softc_p, uint_t subparam, uint_t *val_p); int param_hue_set(dcam_state_t *softc_p, uint_t subparam, uint_t val); int param_saturation_get(dcam_state_t *softc_p, uint_t subparam, uint_t *val_p); int param_saturation_set(dcam_state_t *softc_p, uint_t subparam, uint_t val); int param_gamma_get(dcam_state_t *softc_p, uint_t subparam, uint_t *val_p); int param_gamma_set(dcam_state_t *softc_p, uint_t subparam, uint_t val); int param_shutter_get(dcam_state_t *softc_p, uint_t subparam, uint_t *val_p); int param_shutter_set(dcam_state_t *softc_p, uint_t subparam, uint_t val); int param_gain_get(dcam_state_t *softc_p, uint_t subparam, uint_t *val_p); int param_gain_set(dcam_state_t *softc_p, uint_t subparam, uint_t val); int param_iris_get(dcam_state_t *softc_p, uint_t subparam, uint_t *val_p); int param_iris_set(dcam_state_t *softc_p, uint_t subparam, uint_t val); int param_focus_get(dcam_state_t *softc_p, uint_t subparam, uint_t *val_p); int param_focus_set(dcam_state_t *softc_p, uint_t subparam, uint_t val); int param_zoom_get(dcam_state_t *softc_p, uint_t subparam, uint_t *val_p); int param_zoom_set(dcam_state_t *softc_p, uint_t subparam, uint_t val); int param_pan_get(dcam_state_t *softc_p, uint_t subparam, uint_t *val_p); int param_pan_set(dcam_state_t *softc_p, uint_t subparam, uint_t val); int param_tilt_get(dcam_state_t *softc_p, uint_t subparam, uint_t *val_p); int param_tilt_set(dcam_state_t *softc_p, uint_t subparam, uint_t val); #ifdef __cplusplus } #endif #endif /* _SYS_1394_TARGETS_DCAM1394_PARAM_H */ /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License, Version 1.0 only * (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 2005 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #ifndef _SYS_1394_TARGETS_DCAM1394_REG_H #define _SYS_1394_TARGETS_DCAM1394_REG_H #include #ifdef __cplusplus extern "C" { #endif /* * dcam spec: Sec 1.1 Camera Initialize Register */ #define DCAM1394_REG_OFFS_INITIALIZE 0x0 #define DCAM1394_REG_VAL_INITIALIZE_ASSERT 0x80000000 /* * dcam spec: Sec 1.2.1.1 Inquiry Register for Video Mode */ #define DCAM1394_REG_OFFS_VID_MODE_INQ 0x180 /* * dcam spec: Sec 1.2.2 Inquiry Register for Video Frame Rate */ #define DCAM1394_REG_OFFS_FRAME_RATE_INQ_BASE 0x200 /* * dcam spec: basic function inquiry registers, sec 1.3 */ #define DCAM1394_REG_OFFS_BASIC_FUNC_INQ 0x400 #define DCAM1394_MASK_CAM_POWER_CTRL 0x8000 #define DCAM1394_SHIFT_CAM_POWER_CTRL 15 /* * dcam spec: Sec 1.5 Inquiry Register for Feature Elements */ #define DCAM1394_REG_OFFS_FEATURE_ELM_INQ_BASE 0x500 #define DCAM1394_REG_OFFS_BRIGHTNESS_INQ 0x0 #define DCAM1394_REG_OFFS_EXPOSURE_INQ 0x4 #define DCAM1394_REG_OFFS_SHARPNESS_INQ 0x8 #define DCAM1394_REG_OFFS_WHITE_BALANCE_INQ 0xC #define DCAM1394_REG_OFFS_HUE_INQ 0x10 #define DCAM1394_REG_OFFS_SATURATION_INQ 0x14 #define DCAM1394_REG_OFFS_GAMMA_INQ 0x18 #define DCAM1394_REG_OFFS_SHUTTER_INQ 0x1C #define DCAM1394_REG_OFFS_GAIN_INQ 0x20 #define DCAM1394_REG_OFFS_IRIS_INQ 0x24 #define DCAM1394_REG_OFFS_FOCUS_INQ 0x28 #define DCAM1394_REG_OFFS_ZOOM_INQ 0x80 #define DCAM1394_REG_OFFS_PAN_INQ 0x84 #define DCAM1394_REG_OFFS_TILT_INQ 0x88 /* * "presence of feature" bit is located in Feature Presence Inquiry * Register(Sec 1.4) Feature Element Inquiry Register(Sec 1.5) and Feature * Status and Control Register(Sec 1.7); driver will use later. */ #define DCAM1394_MASK_READOUT_INQ 0x8000000 #define DCAM1394_SHIFT_READOUT_INQ 27 #define DCAM1394_MASK_ON_OFF_INQ 0x4000000 #define DCAM1394_SHIFT_ON_OFF_INQ 26 #define DCAM1394_MASK_AUTO_INQ 0x2000000 #define DCAM1394_SHIFT_AUTO_INQ 25 #define DCAM1394_MASK_MANUAL_INQ 0x1000000 #define DCAM1394_SHIFT_MANUAL_INQ 24 #define DCAM1394_MASK_MIN_VAL 0xFFF000 #define DCAM1394_SHIFT_MIN_VAL 12 #define DCAM1394_MASK_MAX_VAL 0xFFF #define DCAM1394_SHIFT_MAX_VAL 0 /* * dcam spec: Sec 1.6 */ #define DCAM1394_REG_OFFS_CUR_V_FRM_RATE 0x600 #define DCAM1394_SHIFT_CUR_V_FRM_RATE 29 #define DCAM1394_REG_OFFS_CUR_V_MODE 0x604 #define DCAM1394_SHIFT_CUR_V_MODE 29 #define DCAM1394_REG_OFFS_CUR_V_FORMAT 0x608 #define DCAM1394_REG_OFFS_CUR_ISO_CHANNEL 0x60C #define DCAM1394_REG_OFFS_CAMERA_POWER 0x610 #define DCAM1394_SHIFT_CAMERA_POWER 31 #define DCAM1394_REG_OFFS_ISO_EN 0x614 #define DCAM1394_REG_OFFS_MEMORY_SAVE 0x618 #define DCAM1394_REG_OFFS_ONE_SHOT 0x61C #define DCAM1394_REG_OFFS_MEM_SAVE_CH 0x620 #define DCAM1394_REG_OFFS_CUR_MEM_CH 0x624 #define DCAM1394_REG_OFFS_FEATURE_CSR_BASE 0x800 #define DCAM1394_REG_OFFS_BRIGHTNESS_CSR 0x0 #define DCAM1394_REG_OFFS_EXPOSURE_CSR 0x4 #define DCAM1394_REG_OFFS_SHARPNESS_CSR 0x8 #define DCAM1394_REG_OFFS_WHITE_BALANCE_CSR 0xC #define DCAM1394_REG_OFFS_HUE_CSR 0x10 #define DCAM1394_REG_OFFS_SATURATION_CSR 0x14 #define DCAM1394_REG_OFFS_GAMMA_CSR 0x18 #define DCAM1394_REG_OFFS_SHUTTER_CSR 0x1C #define DCAM1394_REG_OFFS_GAIN_CSR 0x20 #define DCAM1394_REG_OFFS_IRIS_CSR 0x24 #define DCAM1394_REG_OFFS_FOCUS_CSR 0x28 #define DCAM1394_REG_OFFS_ZOOM_CSR 0x80 #define DCAM1394_REG_OFFS_PAN_CSR 0x84 #define DCAM1394_REG_OFFS_TILT_CSR 0x88 #define DCAM1394_MASK_PRESENCE_INQ 0x80000000 #define DCAM1394_SHIFT_PRESENCE_INQ 31 #define DCAM1394_MASK_ON_OFF 0x2000000 #define DCAM1394_SHIFT_ON_OFF 25 #define DCAM1394_MASK_A_M_MODE 0x1000000 #define DCAM1394_SHIFT_A_M_MODE 24 #define DCAM1394_MASK_VALUE 0xFFF /* XXX: chk vals */ #define DCAM1394_SHIFT_VALUE 0 /* * white balance feature's u and v values */ #define DCAM1394_MASK_U_VALUE 0xFFF000 #define DCAM1394_SHIFT_U_VALUE 12 #define DCAM1394_MASK_V_VALUE 0xFFF #define DCAM1394_SHIFT_V_VALUE 0 int dcam_reg_read(dcam_state_t *soft_state, dcam1394_reg_io_t *arg); int dcam_reg_write(dcam_state_t *soft_state, dcam1394_reg_io_t *arg); #ifdef __cplusplus } #endif #endif /* _SYS_1394_TARGETS_DCAM1394_REG_H */ /* * 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 _SYS_1394_TARGETS_SCSA1394_CMD_H #define _SYS_1394_TARGETS_SCSA1394_CMD_H /* * scsa1394 command */ #include #include #include #ifdef __cplusplus extern "C" { #endif /* preferred pkt_private length in 64-bit quantities */ #ifdef _LP64 #define SCSA1394_CMD_PRIV_SIZE 2 #else /* _ILP32 */ #define SCSA1394_CMD_PRIV_SIZE 1 #endif #define SCSA1394_CMD_PRIV_LEN (SCSA1394_CMD_PRIV_SIZE * sizeof (uint64_t)) /* entry describing a page table segment */ typedef struct scsa1394_cmd_seg { size_t ss_len; uint64_t ss_daddr; uint64_t ss_baddr; t1394_addr_handle_t ss_addr_hdl; } scsa1394_cmd_seg_t; /* command packet structure */ typedef struct scsa1394_cmd { sbp2_task_t sc_task; /* corresponding SBP-2 task */ struct scsa1394_lun *sc_lun; /* lun it belongs to */ int sc_state; /* command state */ int sc_flags; /* command flags */ struct buf *sc_bp; /* data buffer */ struct scsi_pkt *sc_pkt; /* corresponding scsi pkt */ size_t sc_cdb_len; size_t sc_cdb_actual_len; size_t sc_scb_len; size_t sc_priv_len; uchar_t sc_cdb[SCSI_CDB_SIZE]; uchar_t sc_pkt_cdb[SCSI_CDB_SIZE]; struct scsi_arq_status sc_scb; uint64_t sc_priv[SCSA1394_CMD_PRIV_SIZE]; clock_t sc_start_time; int sc_timeout; /* DMA: command ORB */ ddi_dma_handle_t sc_orb_dma_hdl; ddi_acc_handle_t sc_orb_acc_hdl; ddi_dma_cookie_t sc_orb_dmac; t1394_addr_handle_t sc_orb_addr_hdl; /* DMA: data buffer */ ddi_dma_handle_t sc_buf_dma_hdl; uint_t sc_buf_nsegs; /* # of segments/cookies */ uint_t sc_buf_nsegs_alloc; /* # of entries allocated */ scsa1394_cmd_seg_t *sc_buf_seg; /* segment array */ scsa1394_cmd_seg_t sc_buf_seg_mem; /* backstore for one segment */ uint_t sc_nwin; /* # windows */ uint_t sc_curwin; /* current window */ off_t sc_win_offset; /* current window offset */ size_t sc_win_len; /* current window length */ size_t sc_xfer_bytes; /* current xfer byte count */ size_t sc_xfer_blks; /* current xfer blk count */ /* DMA: page table */ ddi_dma_handle_t sc_pt_dma_hdl; ddi_acc_handle_t sc_pt_acc_hdl; ddi_dma_cookie_t sc_pt_dmac; caddr_t sc_pt_kaddr; uint64_t sc_pt_baddr; t1394_addr_handle_t sc_pt_addr_hdl; size_t sc_pt_ent_alloc; /* # allocated entries */ int sc_pt_cmd_size; /* for symbios mode only */ int sc_lba; /* start LBA */ int sc_blk_size; /* xfer block size */ size_t sc_total_blks; /* total xfer blocks */ size_t sc_resid_blks; /* blocks left */ struct scsi_pkt sc_scsi_pkt; /* must be last */ /* embedded SCSI packet */ /* ... scsi_pkt_size() */ } scsa1394_cmd_t; #define SCSA1394_CMD_SIZE (sizeof (struct scsa1394_cmd) - \ sizeof (struct scsi_pkt) + scsi_pkt_size()) _NOTE(SCHEME_PROTECTS_DATA("unique per task", { scsa1394_cmd scsa1394_cmd_seg scsi_pkt scsi_inquiry scsi_extended_sense scsi_cdb scsi_arq_status })) #define PKT2CMD(pktp) ((scsa1394_cmd_t *)((pktp)->pkt_ha_private)) #define CMD2PKT(cmdp) ((struct scsi_pkt *)((cmdp)->sc_pkt)) #define TASK2CMD(task) ((scsa1394_cmd_t *)(task)->ts_drv_priv) #define CMD2TASK(cmdp) ((sbp2_task_t *)&(cmdp)->sc_task) /* state */ enum { SCSA1394_CMD_INIT, SCSA1394_CMD_START, SCSA1394_CMD_STATUS }; /* flags */ enum { SCSA1394_CMD_CDB_EXT = 0x0001, SCSA1394_CMD_PRIV_EXT = 0x0002, SCSA1394_CMD_SCB_EXT = 0x0004, SCSA1394_CMD_EXT = (SCSA1394_CMD_CDB_EXT | SCSA1394_CMD_PRIV_EXT | SCSA1394_CMD_SCB_EXT), SCSA1394_CMD_DMA_CDB_VALID = 0x0008, SCSA1394_CMD_DMA_BUF_BIND_VALID = 0x0010, SCSA1394_CMD_DMA_BUF_PT_VALID = 0x0020, SCSA1394_CMD_DMA_BUF_ADDR_VALID = 0x0040, SCSA1394_CMD_DMA_BUF_VALID = (SCSA1394_CMD_DMA_BUF_BIND_VALID | SCSA1394_CMD_DMA_BUF_ADDR_VALID | SCSA1394_CMD_DMA_BUF_PT_VALID), SCSA1394_CMD_DMA_BUF_MAPIN = 0x0080, SCSA1394_CMD_READ = 0x0100, SCSA1394_CMD_WRITE = 0x0200, SCSA1394_CMD_RDWR = (SCSA1394_CMD_READ | SCSA1394_CMD_WRITE), SCSA1394_CMD_SYMBIOS_BREAKUP = 0x400 }; #ifdef __cplusplus } #endif #endif /* _SYS_1394_TARGETS_SCSA1394_CMD_H */ /* * 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 _SYS_1394_TARGETS_SCSA1394_IMPL_H #define _SYS_1394_TARGETS_SCSA1394_IMPL_H /* * scsa1394 definitions */ #include #include #include #include #include #ifdef __cplusplus extern "C" { #endif /* * each lun uses a worker thread for various deferred processing */ typedef enum { SCSA1394_THR_INIT, /* initial state */ SCSA1394_THR_RUN, /* thread is running */ SCSA1394_THR_EXIT /* thread exited */ } scsa1394_thr_state_t; /* thread requests */ enum { SCSA1394_THREQ_EXIT = 0x1, /* thread has to exit */ SCSA1394_THREQ_TASK_STATUS = 0x2, /* task status received */ SCSA1394_THREQ_NUDGE = 0x4, /* nudge SBP-2 layer */ SCSA1394_THREQ_BUS_RESET = 0x8, SCSA1394_THREQ_DISCONNECT = 0x10, SCSA1394_THREQ_RECONNECT = 0x20 }; typedef struct scsa1394_thread { void (*thr_func)(void *); /* function to be run */ void *thr_arg; /* function argument */ struct scsa1394_lun *thr_lun; /* lun we belong to */ scsa1394_thr_state_t thr_state; /* state */ kcondvar_t thr_cv; /* cv for request wait */ int thr_req; /* request mask */ } scsa1394_thread_t; /* 1394 device state */ typedef enum { SCSA1394_DEV_INIT = 0, SCSA1394_DEV_ONLINE, SCSA1394_DEV_BUS_RESET, SCSA1394_DEV_DISCONNECTED, SCSA1394_DEV_PWRED_DOWN, SCSA1394_DEV_SUSPENDED } scsa1394_dev_state_t; enum { SCSA1394_STAT_NCMD_LAST = 8 }; /* per-lun statistics */ typedef struct scsa1394_lun_stat { /* * ring buffer of the last N failed commands. stat_cmd_fail_last_idx * is an index into stat_cmd_fail_last the array and points to the * entry to be written next. The first 16 bytes are CDB bytes, * the last 8 bytes are a timestamp (lbolt). */ uint64_t stat_cmd_last_fail[SCSA1394_STAT_NCMD_LAST][3]; int stat_cmd_last_fail_idx; uint_t stat_cmd_cnt; /* # of commands submitted */ uint_t stat_cmd_buf_max_nsegs; uint_t stat_cmd_buf_dma_partial; /* * errors */ uint_t stat_err_pkt_kmem_alloc; uint_t stat_err_cmd_cdb_dmem_alloc; uint_t stat_err_cmd_cdb_dbind; uint_t stat_err_cmd_cdb_addr_alloc; uint_t stat_err_cmd_buf_dbind; uint_t stat_err_cmd_buf_addr_alloc; uint_t stat_err_cmd_pt_kmem_alloc; uint_t stat_err_cmd_pt_dmem_alloc; uint_t stat_err_cmd_pt_addr_alloc; uint_t stat_err_status_tran_err; uint_t stat_err_status_conv; uint_t stat_err_status_resp; } scsa1394_lun_stat_t; /* logical unit */ typedef struct scsa1394_lun { kmutex_t l_mutex; /* structure lock */ struct scsa1394_state *l_sp; /* soft state */ sbp2_lun_t *l_lun; /* SBP2 lun */ sbp2_ses_t *l_ses; /* login session */ dev_info_t *l_cdip; /* child devinfo */ scsa1394_thread_t l_worker_thread; /* worker thread */ ddi_softintr_t l_softintr_id; /* soft interrupt */ boolean_t l_softintr_triggered; /* trigger indicator */ int l_softintr_req; /* soft intr request mask */ /* workarounds */ int l_lba_size; /* LBA size */ int l_dtype_orig; /* original DTYPE value */ int l_rmb_orig; /* original RMB value */ int l_start_stop_fail_cnt; /* start/stop failures */ boolean_t l_start_stop_fake; /* fake start/stop unit */ int l_mode_sense_fail_cnt; /* mode sense failures */ boolean_t l_mode_sense_fake; /* fake mode sense command */ boolean_t l_nosup_tur; boolean_t l_nosup_start_stop; boolean_t l_nosup_inquiry; struct scsi_inquiry l_fake_inq; scsa1394_lun_stat_t l_stat; /* statistics */ } scsa1394_lun_t; _NOTE(MUTEX_PROTECTS_DATA(scsa1394_lun::l_mutex, scsa1394_lun)) _NOTE(SCHEME_PROTECTS_DATA("stable data", scsa1394_lun::{ l_sp l_lun l_ses l_cdip l_worker_thread l_softintr_id l_nosup_tur l_nosup_start_stop l_nosup_inquiry })) _NOTE(SCHEME_PROTECTS_DATA("statistics", scsa1394_lun::l_stat)) /* l_softintr_req */ enum { SCSA1394_SOFTINTR_STATUS_RCVD = 0x1, /* task status received */ SCSA1394_SOFTINTR_RECONNECT = 0x2 /* perform reconnect */ }; /* per-instance statistics */ typedef struct scsa1394_inst_stat { uint_t stat_bus_reset_cnt; uint_t stat_disconnect_cnt; uint_t stat_reconnect_cnt; /* * errors */ } scsa1394_inst_stat_t; /* per-instance soft state structure */ typedef struct scsa1394_state { kmutex_t s_mutex; /* structure mutex */ dev_info_t *s_dip; /* device information */ int s_instance; /* instance number */ scsa1394_dev_state_t s_dev_state; /* device state */ t1394_handle_t s_t1394_hdl; /* 1394 handle */ t1394_attachinfo_t s_attachinfo; /* 1394 attach info */ t1394_targetinfo_t s_targetinfo; /* 1394 target info */ ddi_callback_id_t s_reset_cb_id; /* reset event cb id */ ddi_callback_id_t s_remove_cb_id; /* remove event cb id */ ddi_callback_id_t s_insert_cb_id; /* insert event cb id */ boolean_t s_event_entered; /* event serialization */ kcondvar_t s_event_cv; /* event serialization cv */ ddi_dma_attr_t s_buf_dma_attr; /* data buffer DMA attrs */ ddi_dma_attr_t s_pt_dma_attr; /* page table DMA attrs */ scsi_hba_tran_t *s_tran; /* SCSA HBA tran structure */ sbp2_tgt_t *s_tgt; /* SBP-2 target */ sbp2_cfgrom_t *s_cfgrom; /* Config ROM */ int s_nluns; /* # of logical units */ scsa1394_lun_t *s_lun; /* logical units */ kmem_cache_t *s_cmd_cache; /* command kmem cache */ ddi_taskq_t *s_taskq; /* common taskq for all luns */ boolean_t s_symbios; /* need Symbios workaround? */ boolean_t s_disconnect_warned; /* disconnect warning */ size_t s_totalsec; /* total sectors */ size_t s_secsz; /* sector size */ scsa1394_inst_stat_t s_stat; /* statistics */ } scsa1394_state_t; _NOTE(MUTEX_PROTECTS_DATA(scsa1394_state::s_mutex, scsa1394_state)) _NOTE(SCHEME_PROTECTS_DATA("stable data", scsa1394_state::{ s_dip s_instance s_t1394_hdl s_attachinfo s_reset_cb_id s_remove_cb_id s_insert_cb_id s_buf_dma_attr s_pt_dma_attr s_tran s_tgt s_cfgrom s_nluns s_lun s_cmd_cache s_taskq s_symbios s_targetinfo s_totalsec s_secsz})) _NOTE(SCHEME_PROTECTS_DATA("statistics", scsa1394_state::s_stat)) _NOTE(LOCK_ORDER(scsa1394_state::s_mutex scsa1394_lun::l_mutex)) /* for sbp2_bus_buf.bb_hdl */ typedef struct scsa1394_bus_buf { scsa1394_state_t *sbb_state; /* soft state */ t1394_addr_handle_t sbb_addr_hdl; /* 1394 address handle */ ddi_dma_handle_t sbb_dma_hdl; /* DMA handle */ ddi_acc_handle_t sbb_acc_hdl; /* access handle */ } scsa1394_bus_buf_t; _NOTE(SCHEME_PROTECTS_DATA("unique per task", scsa1394_bus_buf)) _NOTE(SCHEME_PROTECTS_DATA("dev_info::devi_lock", dev_info::devi_state)) /* various translation macros */ #define ADDR2TRAN(ap) ((ap)->a_hba_tran) #define TRAN2STATE(hba) ((scsa1394_state_t *)(hba)->tran_hba_private) #define ADDR2STATE(ap) (TRAN2STATE(ADDR2TRAN(ap))) #define SCSA1394_NODEID(sp) ((sp)->s_attachinfo.localinfo.local_nodeID) #define SCSA1394_BUSGEN(sp) ((sp)->s_attachinfo.localinfo.bus_generation) #define SCSA1394_ORB_SIZE_ROUNDUP(sp, sz) SBP2_ORB_SIZE_ROUNDUP(sp->s_tgt, sz) #define SCSA1394_ADDR_SET(sp, var, addr) \ SBP2_ADDR_SET(var, addr, SCSA1394_NODEID(sp)) /* macros to calculate LBA for 6/10/12-byte commands */ #define SCSA1394_LBA_6BYTE(pkt) \ (((pkt)->pkt_cdbp[1] & 0x1f) << 16) + \ ((pkt)->pkt_cdbp[2] << 8) + (pkt)->pkt_cdbp[3] #define SCSA1394_LEN_6BYTE(pkt) \ (pkt)->pkt_cdbp[4] #define SCSA1394_LEN_10BYTE(pkt) \ ((pkt)->pkt_cdbp[7] << 8) + (pkt)->pkt_cdbp[8] #define SCSA1394_LBA_10BYTE(pkt) \ ((pkt)->pkt_cdbp[2] << 24) + ((pkt)->pkt_cdbp[3] << 16) + \ ((pkt)->pkt_cdbp[4] << 8) + (pkt)->pkt_cdbp[5] #define SCSA1394_LEN_12BYTE(pkt) \ ((pkt)->pkt_cdbp[6] << 24) + ((pkt)->pkt_cdbp[7] << 16) + \ ((pkt)->pkt_cdbp[8] << 8) + (pkt)->pkt_cdbp[9] #define SCSA1394_LBA_12BYTE(pkt) \ ((pkt)->pkt_cdbp[2] << 24) + ((pkt)->pkt_cdbp[3] << 16) + \ ((pkt)->pkt_cdbp[4] << 8) + (pkt)->pkt_cdbp[5] /* macro to calculate LEN for SCMD_READ_CD command */ #define SCSA1394_LEN_READ_CD(pkt) \ (((pkt)->pkt_cdbp[6] << 16) + ((pkt)->pkt_cdbp[7] << 8) + \ (pkt)->pkt_cdbp[8]) /* calculate block size for CD-RW writes */ #define SCSA1394_CDRW_BLKSZ(bcount, len) ((bcount) / (len)) #define SCSA1394_VALID_CDRW_BLKSZ(blksz) \ (((blksz) == CDROM_BLK_2048) || ((blksz) == CDROM_BLK_2352) || \ ((blksz) == CDROM_BLK_2336) || ((blksz) == CDROM_BLK_2324)) /* black/white list */ typedef struct scsa1394_bw_list { int vid_match; int vid; } scsa1394_bw_list_t; /* match type */ enum { SCSA1394_BW_ONE, SCSA1394_BW_ALL }; #define NELEM(a) (sizeof (a) / sizeof (*(a))) /* misc constants */ enum { SCSA1394_COMPAT_MAX = 1, /* max @ of compatible names */ SCSA1394_CLEANUP_LEVEL_MAX = 256, SCSA1394_START_STOP_FAIL_MAX = 3, /* max start/stop failures */ SCSA1394_MODE_SENSE_FAIL_MAX = 3, /* max mode sense failures */ SCSA1394_START_STOP_TIMEOUT_MAX = 30, SCSA1394_MAPIN_SIZE_MAX = 512, SCSA1394_PROBE_TIMEOUT = 15, /* in seconds */ SCSA1394_DTYPE_RBC = 0x0E }; /* SBP-2 routines */ int scsa1394_sbp2_attach(scsa1394_state_t *); void scsa1394_sbp2_detach(scsa1394_state_t *); void scsa1394_sbp2_fake_inquiry(scsa1394_state_t *, struct scsi_inquiry *); int scsa1394_sbp2_threads_init(scsa1394_state_t *); void scsa1394_sbp2_threads_fini(scsa1394_state_t *); int scsa1394_sbp2_get_lun_type(scsa1394_lun_t *); int scsa1394_sbp2_login(scsa1394_state_t *, int); void scsa1394_sbp2_logout(scsa1394_state_t *, int, boolean_t); void scsa1394_sbp2_req(scsa1394_state_t *, int, int); void scsa1394_sbp2_disconnect(scsa1394_state_t *); void scsa1394_sbp2_seg2pt(scsa1394_lun_t *, scsa1394_cmd_t *); void scsa1394_sbp2_cmd2orb(scsa1394_lun_t *, scsa1394_cmd_t *); int scsa1394_sbp2_start(scsa1394_lun_t *, scsa1394_cmd_t *); void scsa1394_sbp2_nudge(scsa1394_lun_t *); int scsa1394_sbp2_reset(scsa1394_lun_t *, int, scsa1394_cmd_t *); void scsa1394_sbp2_flush_cmds(scsa1394_lun_t *, int, int, int); /* HBA public routines */ int scsa1394_thr_dispatch(scsa1394_thread_t *); void scsa1394_thr_cancel(scsa1394_thread_t *); void scsa1394_thr_wake(scsa1394_thread_t *, int); void scsa1394_thr_clear_req(scsa1394_thread_t *, int); void scsa1394_cmd_status_proc(scsa1394_lun_t *, scsa1394_cmd_t *); boolean_t scsa1394_dev_is_online(scsa1394_state_t *); void scsa1394_sbp2_req_bus_reset(scsa1394_lun_t *); void scsa1394_sbp2_req_reconnect(scsa1394_lun_t *); #ifdef __cplusplus } #endif #endif /* _SYS_1394_TARGETS_SCSA1394_IMPL_H */ /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License, Version 1.0 only * (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 2004 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #ifndef _SYS_1394_TARGETS_SCSA1394_SBP2_H #define _SYS_1394_TARGETS_SCSA1394_SBP2_H /* * SCSI command and status encapsulation in SBP-2 * * References are to ANSI NCITS 325-1998 unless specified otherwise */ #include #ifdef __cplusplus extern "C" { #endif /* SCSI command block ORB (ref: B.1) */ typedef struct scsa1394_cmd_orb { sbp2_orbp_t co_next_orb; /* next ORB pointer */ uint32_t co_data_descr[2]; /* data descriptor */ uint16_t co_params; /* parameters */ uint16_t co_data_size; /* parameters */ uint8_t co_cdb[12]; /* CDB */ } scsa1394_cmd_orb_t; /* status block with SCSI sense data (ref: B.1) */ typedef struct scsa1394_status { uint8_t st_param; /* parameters */ uint8_t st_sbp_status; /* SBP status */ uint16_t st_orb_offset_hi; /* ORB offset hi */ uint32_t st_orb_offset_lo; /* ORB offset lo */ uint8_t st_status; /* SCSI status */ uint8_t st_sense_bits; /* misc sense bits */ uint8_t st_sense_code; /* sense code */ uint8_t st_sense_qual; /* sense qualifier */ uint8_t st_info[4]; /* information bytes */ uint8_t st_cdb[4]; /* CDB-dependent */ uint8_t st_fru; /* FRU code */ uint8_t st_sks[3]; /* sense_key-dependent */ uint32_t st_vendor[2]; /* vendor-dependent */ } scsa1394_status_t; /* st_status */ #define SCSA1394_ST_SFMT 0xC0 /* status block format */ #define SCSA1394_ST_SFMT_SHIFT 6 #define SCSA1394_ST_STATUS 0x3F /* SCSI status */ /* status block formats */ #define SCSA1394_ST_SFMT_CURRENT 0x00 /* current error */ #define SCSA1394_ST_SFMT_DEFERRED 0x40 /* deferred error */ #define SCSA1394_ST_SFMT_VENDOR 0xC0 /* vendor-dependent */ /* st_sense_bits */ #define SCSA1394_ST_VALID 0x80 /* valid bit */ #define SCSA1394_ST_VALID_SHIFT 7 #define SCSA1394_ST_MARK 0x40 /* filemark */ #define SCSA1394_ST_MARK_SHIFT 6 #define SCSA1394_ST_EOM 0x20 /* EOM */ #define SCSA1394_ST_EOM_SHIFT 5 #define SCSA1394_ST_ILI 0x10 /* ILI */ #define SCSA1394_ST_ILI_SHIFT 4 #define SCSA1394_ST_SENSE_KEY 0x0F /* sense key */ /* st_extra */ #define SCSA1394_ST_FRU 0xFF000000 /* FRU */ #define SCSA1394_ST_FRU_SHIFT 24 #define SCSA1394_ST_SKEY_DEP 0x00FFFFFF /* sense key-dependent */ #define SCSA1394_ST_SKEY_DEP_SHIFT 0 #ifdef __cplusplus } #endif #endif /* _SYS_1394_TARGETS_SCSA1394_SBP2_H */