From mboxrd@z Thu Jan 1 00:00:00 1970 From: Luben Tuikov Subject: [ANNOUNCE] Adaptec SAS/SATA device driver [10/27] Date: Thu, 17 Feb 2005 12:36:25 -0500 Message-ID: <4214D619.20400@adaptec.com> Mime-Version: 1.0 Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit Received: from magic.adaptec.com ([216.52.22.17]:46481 "EHLO magic.adaptec.com") by vger.kernel.org with ESMTP id S262324AbVBQRga (ORCPT ); Thu, 17 Feb 2005 12:36:30 -0500 Received: from redfish.adaptec.com (redfish.adaptec.com [162.62.50.11]) by magic.adaptec.com (8.11.6/8.11.6) with ESMTP id j1HHaTr30903 for ; Thu, 17 Feb 2005 09:36:29 -0800 Received: from rtpe2k01.adaptec.com (rtpe2k01.adaptec.com [10.110.12.40]) by redfish.adaptec.com (8.11.6/8.11.6) with ESMTP id j1HHaSb21087 for ; Thu, 17 Feb 2005 09:36:28 -0800 Sender: linux-scsi-owner@vger.kernel.org List-Id: linux-scsi@vger.kernel.org To: SCSI Mailing List Hardware interface header file. diff -Nru a/drivers/scsi/adp94xx/adp94xx_hwi.h b/drivers/scsi/adp94xx/adp94xx_hwi.h --- /dev/null Wed Dec 31 16:00:00 196900 +++ b/drivers/scsi/adp94xx/adp94xx_hwi.h 2005-02-16 16:08:12 -05:00 @@ -0,0 +1,1242 @@ +/* + * Adaptec ADP94xx SAS HBA device driver for Linux. + * + * Written by : David Chaw + * Modified by : Naveen Chandrasekaran + * + * Copyright (c) 2004 Adaptec Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + * + * $Id: //depot/razor/linux/src/adp94xx_hwi.h#113 $ + * + */ + +#ifndef ADP94XX_HWI_H +#define ADP94XX_HWI_H + +#include "adp94xx_sas.h" +#include "adp94xx_reg.h" + +struct asd_softc; +struct asd_platform_data; +struct asd_target; +struct asd_device; +struct asd_conn_desc_format; +struct asd_nd_phydesc_format; + +/* CHIP Revision ID */ +#define AIC9410_DEV_REV_A0 0 +#define AIC9410_DEV_REV_A1 1 +#define AIC9410_DEV_REV_B0 8 +#define COMSTOCK_LATEST_RTL 26 + +/* Controller profile */ +#define ASD_MAX_WWN_LEN SAS_ADDR_LEN /* World Wide Name size */ + +#if SAS_COMSTOCK_SUPPORT +#define ASD_MAX_PHYS 1 /* Max supported phys */ +#define ASD_MAX_PORTS ASD_MAX_PHYS /* Max supported ports */ +#else +#define ASD_MAX_PHYS 8 /* Max supported phys */ +#define ASD_MAX_PORTS ASD_MAX_PHYS /* Max supported ports */ +#endif + +#define ASD_MAX_SCB_SITES 512 /* + * Max supported built-in + * SCB sites + */ +#define ASD_RSVD_SCBS 11 /* Reserved SCBs */ +#define ASD_MAX_EDBS_PER_SCB 7 /* + * Max number of Empty + * data buffers that can + * be queued in a single SCB. + */ +#define ASD_MAX_EDBS 21 /* + * Max number of Empty + * data buffers. + */ + +/* + * There is a workaround fix required by the sequencer to skip + * using the free scb sites that ended with FF. + */ +static inline u_int +asd_calc_free_scb_sites(u_int max_scbs) +{ + uint16_t site_no; + u_int usable_scb_sites; + + usable_scb_sites = max_scbs; + for (site_no = 0; site_no < max_scbs; site_no++) { + if ((site_no & 0xF0FF) == 0x00FF) + usable_scb_sites--; + } + + return (usable_scb_sites); +} + +#define ASD_USABLE_SCB_SITES asd_calc_free_scb_sites(ASD_MAX_SCB_SITES) + +#define ASD_MAX_ALLOCATED_SCBS \ + (ASD_USABLE_SCB_SITES - (ASD_MAX_EDBS/ASD_MAX_EDBS_PER_SCB)) + +#define ASD_MAX_USABLE_SCBS ASD_USABLE_SCB_SITES + +#define ASD_MAX_DEVICES 128 /* Max supported devices */ +#define ASD_MAX_EXPANDERS 16 /* Max supported expanders */ +#define ASD_MAX_TARGETS (ASD_MAX_DEVICES - ASD_MAX_EXPANDERS) +#define ASD_MAX_DDBS 128 /* Max number of HW DDB sites */ +#define ASD_MIN_DLS 4 /* Minimum DL amount allowed */ +#define ASD_MAX_DLS 16384 /* Maximum DL amount allowed */ +#define ASD_SCB_SIZE sizeof(union hardware_scb) +#define ASD_DDB_SIZE sizeof(struct asd_ddb) +#define ASD_DL_SIZE sizeof(struct asd_done_list) + +#define ASD_QDONE_PASS_DEF 1 + +/* Controller Delay */ +#define ASD_DELAY_COUNT 5 /* Set to 5 microseconds */ +#define ASD_REG_TIMEOUT_VAL 2000 +#define ASD_REG_TIMEOUT_TICK ((ASD_REG_TIMEOUT_VAL * 1000) / ASD_DELAY_COUNT) + +/* Controller functionality */ +#define ASD_PIO_DOWNLOAD_SEQS 1 /* + * Download the SEQS code using + * PIO mode. + */ +#define ASD_DMA_DOWNLOAD_SEQS 0 /* + * Download the SEQS code using + * Overlay DMA mode. + */ + +/* Tunable constant. */ +#define SAS_NOTIFY_TIMER_TIMEOUT_CONST 500 /* + * The default value 500 (in + * msecs) for time interval for + * transmission interval between + * successive NOTIFY + * (ENABLE_SPINUP) primitive. + */ + +/* Available activity LED bits in GPIOx registers */ +#define ASD_MAX_XDEVLED_BITS 8 + +typedef enum { + SCB_EH_NONE = 0x0000, + SCB_EH_INITIATED = 0x0001, + SCB_EH_IN_PROGRESS = 0x0002, + SCB_EH_TIMEDOUT = 0x0004, + SCB_EH_DONE = 0x0008, + SCB_EH_ABORT_REQ = 0x0010, + SCB_EH_LU_RESET_REQ = 0x0020, + SCB_EH_DEV_RESET_REQ = 0x0040, + SCB_EH_PORT_RESET_REQ = 0x0080, + SCB_EH_CLR_NXS_REQ = 0x0100, + SCB_EH_SUSPEND_SENDQ = 0x0200, + SCB_EH_RESUME_SENDQ = 0x0400, + SCB_EH_PHY_NO_OP_REQ = 0x0800, + SCB_EH_PHY_REPORT_REQ = 0x1000 +} scb_eh_state; + +#define SCB_EH_LEVEL_MASK 0x00F0 + +typedef enum { + SCB_EH_SUCCEED, + SCB_EH_FAILED +} scb_eh_status; + +typedef enum { + SCB_FLAG_NONE = 0x00, + SCB_ACTIVE = 0x01, + SCB_DEV_QFRZN = 0x02, + SCB_TIMEDOUT = 0x04, + SCB_PENDING = 0x08, + SCB_INTERNAL = 0x10, + SCB_RECOVERY = 0x20, + SCB_RESERVED = 0x40 +} scb_flag; + +/* Data structures used to manage CSMI commands */ +struct asd_ctl_mgmt { + wait_queue_head_t waitq; + struct semaphore sem; + struct timer_list timer; + u_long busy; + int err; +}; + +struct asd_ctl_internal_data { + struct asd_ctl_mgmt mgmt; +}; + +typedef void asd_scb_post_t(struct asd_softc *, struct scb *, + struct asd_done_list *); +typedef void asd_scb_eh_post_t(struct asd_softc *, struct scb *); + +#define SCB_POST_STACK_DEPTH 5 + +struct asd_scb_post_stack { + /* + * Completion callback. + */ + asd_scb_post_t *post; + + /* + * OS per I/O context structure. + */ + asd_io_ctx_t io_ctx; +}; + +/* + * SCB buffer descriptor. Contains HWI layer information + * pertaining to SCB data DMAed to and from the controller. + */ +struct scb { + /* + * Links for chaining SCBs onto the pending, or free list. + */ + struct list_head hwi_links; + /* + * Links for use by the owner (e.g. originator) of the SCB. + */ + struct list_head owner_links; + /* + * Links for chaining SCBs onto the timedout SCB list. + */ + struct list_head timedout_links; + /* + * Completion callback. + */ + asd_scb_post_t *post; + /* + * OS per I/O context structure. + */ + asd_io_ctx_t io_ctx; + /* + * OSM specific, per-context data. + */ + struct asd_scb_platform_data *platform_data; + /* + * Per-context, hardware specific, data that is + * actually DMA'ed to the controller. + */ + union hardware_scb *hscb; + struct map_node *hscb_map; + dma_addr_t hscb_busaddr; + /* + * Index to the Device Descriptor Block representing + * the device to which this transaction is targeted. + */ + uint16_t conn_handle; + /* + * Scatter/Gather list data structures. + */ + struct map_node *sg_map; + struct sg_element *sg_list; + dma_addr_t sg_list_busaddr; + u_int sg_count; + /* + * Pointer back to our per-controller instance. + * Used only in timer callbacks where the SCB + * is the saved argument to the timer callback. + */ + struct asd_softc *softc; + /* + * Misc Flags. + */ + scb_flag flags; + /* + * Error Recovery state and status info. + */ + scb_eh_state eh_state; + scb_eh_status eh_status; + asd_scb_eh_post_t *eh_post; + + uint32_t post_stack_depth; + struct asd_scb_post_stack post_stack[SCB_POST_STACK_DEPTH]; +}; + +#define SCB_GET_INDEX(SCB) (asd_le16toh((SCB)->hscb->header.index)) +#define SCB_GET_OPCODE(SCB) ((SCB)->hscb->header.opcode) +#define SCB_GET_SRC_PORT(SCB) ((SCB)->platform_data->targ->src_port) + +/* Common attributes for Phy and Port. */ +typedef enum { + ASD_SSP_INITIATOR = 0x01, + ASD_SMP_INITIATOR = 0x02, + ASD_STP_INITIATOR = 0x04, + ASD_SATA_SPINUP_HOLD = 0x08, + ASD_SAS_MODE = 0x10, + ASD_SATA_MODE = 0x20, + ASD_DEVICE_PRESENT = 0x40 +} asd_attrib; + +typedef enum { + ASD_IDLE = 0x00, + ASD_RESP_PENDING = 0x01, + ASD_ID_ADDR_RCVD = 0x02, + ASD_DISCOVERY_REQ = 0x04, + ASD_DISCOVERY_PROCESS = 0x08, + ASD_DISCOVERY_EVENT = 0x10, + ASD_VALIDATION_REQ = 0x20, + ASD_LOSS_OF_SIGNAL = 0X40, + ASD_DISCOVERY_RETRY = 0X80 +} asd_event; + +/* + * Port structure. + * It is used to reference a SCSI or SATA initiator port for the adapter. + */ +typedef enum { + ASD_PORT_UNUSED, + ASD_PORT_ONLINE, + ASD_PORT_OFFLINE +} asd_port_state; + +struct discover_context { + struct asd_softc *asd; + struct asd_port *port; + uint8_t openStatus; + unsigned resid_len; + + /* + * ------------------------------------- + * DMA-able memory used for SMP request + */ + struct SMPRequest *SMPRequestFrame; + dma_addr_t SMPRequestBusAddr; + bus_dma_tag_t smp_req_dmat; + struct map_node smp_req_map; + + /* + * ------------------------------------- + * DMA-able memory used for SMP response + */ + struct SMPResponse *SMPResponseFrame; + dma_addr_t SMPResponseBusAddr; + bus_dma_tag_t smp_resp_dmat; + struct map_node smp_resp_map; + + /* + * ------------------------------------- + * DMA-able memory used for Report LUNS and Unit Serial Number + */ + uint8_t *SASInfoFrame; + dma_addr_t SASInfoBusAddr; + unsigned sas_info_len; + bus_dma_tag_t sas_info_dmat; + struct map_node sas_info_map; + + /* + * For state machine + * ------------------------------------- + */ + struct state_machine_context sm_context; +}; + +struct asd_port { + struct list_head phys_attached; + struct list_head targets; + struct list_head targets_to_validate; + void *softc; + uint8_t sas_addr[SAS_ADDR_LEN]; + uint8_t hashed_sas_addr[HASHED_SAS_ADDR_LEN]; + uint8_t attached_sas_addr[SAS_ADDR_LEN]; + u_char num_phys; + uint8_t conn_rate; + /* + * Bit field indicating which phy id belongs to this port. + */ + uint8_t conn_mask; + uint8_t reset_mask; + u_char id; + asd_port_state state; + asd_attrib attr; + asd_event events; + LINK_TYPE link_type; + MANAGEMENT_TYPE management_type; + struct discover_context dc; + struct asd_target *tree_root; +}; + +/* + * Phy structure. + * It is used to reference a service delivery subsystem for the adapter. + */ +typedef enum { + ASD_PHY_UNUSED, + ASD_PHY_WAITING_FOR_ID_ADDR, + ASD_PHY_ONLINE, + ASD_PHY_OFFLINE, + ASD_PHY_CONNECTED +} asd_phy_state; + +#define PRODUCT_SERIAL_NUMBER_LEN 64 + +struct asd_phy { + struct list_head pending_scbs; + struct list_head links; + void *softc; + struct asd_port *src_port; + uint8_t sas_addr[SAS_ADDR_LEN]; + u_int max_link_rate; + u_int min_link_rate; + u_int conn_rate; + uint8_t id; + asd_phy_state state; + asd_attrib attr; + asd_event events; + + /* Phy Error information. */ + uint8_t brdcst_rcvd_cnt; + + /* Phy control register info */ + uint8_t phy_state; + uint8_t phy_ctl0; + uint8_t phy_ctl1; + uint8_t phy_ctl2; + uint8_t phy_ctl3; + + /* Identify Address frame buffer. */ + bus_dma_tag_t id_addr_dmat; + struct map_node id_addr_map; + union sas_bytes_dmaed bytes_dmaed_rcvd; + + u_int link_rst_cnt; +#define MAX_LINK_RESET_RETRY 2 + + /* TBD: Temp var, should remove after checking with HW */ + uint8_t pat_gen; +}; + +#define PHY_GET_ID_SAS_ADDR(PHY) \ + ((PHY)->bytes_dmaed_rcvd.id_addr_rcvd.sas_addr) + +typedef enum { + ASD_IO_SPACE, + ASD_MEMORY_SPACE +} asd_mem_space_type; + +struct asd_io_handle { + union { + uint8_t *membase; + unsigned long iobase; + } baseaddr; + uint32_t bar_base; + uint32_t length; + uint32_t swb_base; + uint8_t index; /* BAR index */ + asd_mem_space_type type; +}; + +struct asd_host_profile { + uint16_t max_cmds_per_lun; + uint16_t can_queue; + uint8_t initiator_id; + uint8_t max_luns; + uint8_t max_scsi_ids; + uint8_t max_channels; + uint8_t irq; + uint8_t unit; + uint8_t dma64_addr; + dma_addr_t dma_mask; + char *name; +}; + +/* + * Controller specific information. + */ +struct asd_hw_profile { + /* HW info. */ + uint8_t wwn[ASD_MAX_WWN_LEN]; + uint8_t max_ports; + uint8_t ports_allocated; + uint8_t max_phys; + uint8_t enabled_phys; + int rev_id; + /* Target info. */ + uint16_t max_devices; + uint16_t max_targets; + uint8_t max_expanders; + /* Runtime info. */ + uint16_t max_scbs; + uint16_t max_ddbs; + /* Queue info. */ + uint16_t scbpro_cnt; + /* NVRAM info */ + uint8_t flash_present; + uint16_t flash_manuf_id; + uint16_t flash_dev_id; + uint32_t flash_wr_prot; + u_char nv_exist; + uint32_t nv_cookie_addr; + u_int nv_cookie_found; + uint32_t nv_segment_type; + uint32_t nv_flash_bar; + uint32_t bios_bld_num; + uint8_t bios_maj_ver; + uint8_t bios_min_ver; +}; + +typedef enum { + ASD_SCB_RESOURCE_SHORTAGE = 0x01, + ASD_RUNNING_DONE_LIST = 0x02, + ASD_WAITING_FOR_RESOURCE = 0x04 +} asd_softc_flags; + +struct asd_softc { + /* + * The next hardware SCB already known to the sequencer. + */ + union hardware_scb *next_queued_hscb; + struct map_node *next_queued_hscb_map; + uint64_t next_queued_hscb_busaddr; + /* + * Pool of SCBs available to execute new commands. + */ + struct list_head free_scbs; + /* + * Pool of reserved SCBS to be used for error recovery. + */ + struct list_head rsvd_scbs; + /* + * SCBs that have been sent to the controller + */ + struct list_head pending_scbs; + /* + * Mapping from 16bit scb index to SCB. + */ + struct scb **scbindex; + /* + * Platform specific data. + */ + struct asd_platform_data *platform_data; + /* + * Command Queues info + */ + struct asd_done_list *done_list; + uint16_t dl_next; + uint16_t dl_valid; + uint16_t dl_wrap_mask; + uint16_t qinfifonext; + uint16_t *qinfifo; +#define ASD_QIN_WRAP(asd) ((asd)->qinfifonext & (asd->hw_profile.max_scbs - 1)) + + /* + * Free Device Descriptor Block bitmap. + */ + u_long *free_ddb_bitmap; + u_int ddb_bitmap_size; +#define ASD_INVALID_DDB_INDEX 0xFFFF + + /* + * Misc controller state flags. + */ + asd_softc_flags flags; + /* + * SCBs whose timeout routine has been called. + */ + struct list_head timedout_scbs; + /* + * SCBs that have been sent to the controller + */ + struct list_head empty_scbs; + /* + * "Bus" addresses of our data structures. + */ + bus_dma_tag_t shared_data_dmat; + struct map_node shared_data_map; + + /* dmat for our hardware SCB array */ + bus_dma_tag_t hscb_dmat; + /* dmat for our sg segments */ + bus_dma_tag_t sg_dmat; + struct list_head hscb_maps; + struct list_head sg_maps; + /* Unallocated scbs in head map_node */ + int scbs_left; + /* Unallocated sgs in head map_node */ + int sgs_left; + /* Allocated edbs */ + int edbs; + uint16_t numscbs; + /* + * Platform specific device information. + */ + asd_dev_t dev; + /* + * Used to chain all controller instances + * managed by this driver. + */ + struct list_head link; + struct list_head *old_discover_listp; + struct list_head *discover_listp; + struct asd_port *port_list[ASD_MAX_PORTS]; + struct asd_phy *phy_list[ASD_MAX_PHYS]; + struct asd_host_profile profile; + struct asd_hw_profile hw_profile; + const struct pci_device_id *pci_entry; + struct asd_io_handle **io_handle; + struct asd_ctl_internal_data asd_ctl_internal; + uint32_t asd_hba_index; + uint8_t io_handle_cnt; + uint8_t init_level; + + unsigned num_discovery; + unsigned num_unit_elements; + struct asd_unit_element_format *unit_elements; +}; + + +/* Scatter/Gather list Handling */ +#define asd_sglist_size(asd) (ASD_NSEG * sizeof(struct sg_element)) + + +/* + * Hardware Interface functions prototypes. + */ +void asd_intr_enable(struct asd_softc *asd, int enable); +int asd_hwi_init_hw(struct asd_softc *asd); +int asd_hwi_process_irq(struct asd_softc *asd); +struct asd_softc * asd_alloc_softc(asd_dev_t dev); +void asd_free_softc(struct asd_softc *asd); + +/* + * Device Descriptor Block resource management. + */ +uint16_t asd_alloc_ddb(struct asd_softc *asd); +void asd_free_ddb(struct asd_softc *asd, uint16_t ddb_index); +int asd_hwi_setup_ddb_site(struct asd_softc *asd, + struct asd_target *target); + +/* + * Function prototypes for interfacing with Sequencers. + */ +int asd_hwi_pause_cseq(struct asd_softc *asd); +int asd_hwi_pause_lseq(struct asd_softc *asd, uint8_t lseq_mask); +int asd_hwi_unpause_cseq(struct asd_softc *asd); +int asd_hwi_unpause_lseq(struct asd_softc *asd, uint8_t lseq_mask); +int asd_hwi_download_seqs(struct asd_softc *asd); +void asd_hwi_setup_seqs(struct asd_softc *asd); +int asd_hwi_start_cseq(struct asd_softc *asd); +int asd_hwi_start_lseq(struct asd_softc *asd, uint8_t link_num); +struct scb * asd_hwi_get_scb(struct asd_softc *asd, int rsvd_pool); +void asd_hwi_post_scb(struct asd_softc *asd, struct scb *scb); +union edb * asd_hwi_indexes_to_edb(struct asd_softc *asd, struct scb **pscb, + u_int escb_index, u_int edb_index); +void asd_hwi_free_edb(struct asd_softc *asd, + struct scb *scb, int edb_index); +void asd_hwi_init_internal_ddb(struct asd_softc *asd); +void asd_hwi_build_ddb_site(struct asd_softc *asd, + struct asd_target *target); +void asd_hwi_update_sata(struct asd_softc *asd, + struct asd_target *target); +void asd_hwi_update_conn_mask(struct asd_softc *asd, + struct asd_target *target); +int asd_hwi_enable_phy(struct asd_softc *asd, struct asd_phy *phy); +void asd_hwi_release_sata_spinup_hold(struct asd_softc *asd, + struct asd_phy *phy); + +/* + * Error handling function prototypes. + */ +int asd_hwi_post_eh_scb(struct asd_softc *asd, struct scb *scb); +void asd_hwi_build_ssp_tmf(struct scb *scb, struct asd_target *targ, + uint8_t *lun, u_int tmf_opcode); +void asd_hwi_build_clear_nexus(struct scb *scb, u_int nexus_ind, + u_int parm, u_int context); +void asd_hwi_build_abort_task(struct scb *scb, + struct scb *scb_to_abort); +void asd_hwi_build_query_task(struct scb *scb, + struct scb *scb_to_query); +void asd_hwi_build_control_phy(struct scb *scb, struct asd_phy *phy, + uint8_t sub_func); +void asd_hwi_map_tmf_resp(struct scb *scb, u_int resp_code); + +/* SCB build routines */ +void asd_hwi_build_smp_task(struct scb *scb, struct asd_target *targ, + uint64_t req_bus_addr, u_int req_len, + uint64_t resp_bus_addr, u_int resp_len); +void asd_hwi_build_ssp_task(struct scb *scb, struct asd_target *targ, + uint8_t *saslun, uint8_t *cdb, + uint32_t cdb_len, uint8_t addl_cdb_len, + uint32_t data_len); +void asd_hwi_build_stp_task(struct scb *scb, struct asd_target *targ, + uint32_t data_len); + +int asd_hwi_get_nv_conn_info(struct asd_softc *asd, uint8_t **pconn, + uint32_t *pconn_size, uint8_t **pnoded, + uint32_t *pnoded_size); + +int asd_hwi_control_activity_leds(struct asd_softc *asd, + uint8_t phy_id, + uint32_t asd_phy_ctl_func); + +int asd_hwi_search_nv_segment(struct asd_softc *asd, + u_int segment_id, uint32_t *offset, + uint32_t *pad_size, + uint32_t *image_size, + uint32_t *attr); +int asd_hwi_write_nv_segment(struct asd_softc *asd, + void *src, u_int segment_id, + uint32_t dest_offset, + uint32_t bytes_to_write); + +int asd_hwi_read_nv_segment(struct asd_softc *asd, uint32_t segment_id, + void *dest, uint32_t src_offset, + uint32_t bytes_to_read, + uint32_t *bytes_read); + + +/* Debug function prototypes. */ +#ifdef ASD_DEBUG +void asd_hwi_dump_seq_state(struct asd_softc *asd, uint8_t lseq_mask); +void asd_hwi_dump_ddb_site(struct asd_softc *asd, u_int site_no); +#endif + + +#if ASD_PIO_DOWNLOAD_SEQS +/* PIO Mode */ +int asd_hwi_pio_load_seqs(struct asd_softc *asd, uint8_t *code, + uint32_t code_size, uint8_t lseq_mask); + +#define ASD_HWI_DOWNLOAD_SEQS(asd, code, code_size, lseq_mask) \ + asd_hwi_pio_load_seqs(asd, (uint8_t *) code, \ + (uint32_t) code_size, (uint8_t) lseq_mask) +#else +/* Overlay DMA Mode */ +int asd_hwi_dma_load_seqs(struct asd_softc *asd, uint8_t *code, + uint32_t code_size, uint8_t lseq_mask); + +#define ASD_HWI_DOWNLOAD_SEQS(asd, code, code_size, lseq_mask) \ + asd_hwi_dma_load_seqs(asd, (uint8_t *) code, \ + (uint32_t) code_size, (uint8_t) lseq_mask) + +#endif /* ASD_DMA_DOWNLOAD_SEQS */ + + +/********** External Memory (NVRAM, SEEPROM, etc) strucutres layout ***********/ + +#define NVRAM_SUPPORT 1 + +#if NVRAM_SUPPORT + +#define NVRAM_RESET 0xF0 +#define NVRAM_NO_SEGMENT_ID 0xFF +#define NVRAM_INVALID_SIZE 0xFFFFFFFF +#define NVRAM_COOKIE_SIZE 0x20 +#define NVRAM_FIRST_DIR_ENTRY 0x90 +#define NVRAM_NEXT_ENTRY_OFFSET 0x2000 +#define NVRAM_MAX_ENTRIES 0x20 +#define NVRAM_SEGMENT_ATTR_ERASEWRITE 1 + +/* NVRAM Entry Type Values. */ +#define NVRAM_FLASH_DIR 0x00000000 +#define NVRAM_BIOS_CORE 0x00000020 +#define NVRAM_BIOS_UTILS 0x00000040 +#define NVRAM_BIOS_CHIM 0x00000060 +#define NVRAM_CTRL_A_SETTING 0x000000E0 +#define NVRAM_CTRL_A_DEFAULT 0x00000100 +#define NVRAM_MANUF_TYPE 0x00000120 + + +#define SAS_ADDR_WWID_MASK 0xF0 + +/* OCM directory entry format */ +struct asd_ocm_entry_format { + uint8_t type; +#define OCM_DE_OCM_DIR 0x00 +#define OCM_DE_WIN_DRVR 0x01 +#define OCM_DE_BIOS_CHIM 0x02 +#define OCM_DE_RAID_ENGN 0x03 +#define OCM_DE_BIOS_INTL 0x04 +#define OCM_DE_BIOS_CHIM_OSM 0x05 +#define OCM_DE_BIOS_CHIM_DYNAMIC 0x06 +#define OCM_DE_ADDC2C_RES0 0x07 +#define OCM_DE_ADDC2C_RES1 0x08 +#define OCM_DE_ADDC2C_RES2 0x09 +#define OCM_DE_ADDC2C_RES3 0x0A + + uint8_t offset[3]; +/* retrieves offset/size from the 3 byte array */ +#define OCM_DE_OFFSET_SIZE_CONV(x) ((x[2] << 16) | (x[1] << 8) | x[0]) + + uint8_t res1; + uint8_t size[3]; +} __packed; + +/* OCM directory format */ +struct asd_ocm_dir_format { + /* 'O'n-chip memory 'D'irectory */ + uint16_t signature; +#define OCM_DIR_SIGN 0x4F4D + + uint16_t res1; + uint8_t maj_ver; + uint8_t min_ver; + uint8_t res2; + uint8_t num_entries; +#define OCM_NUM_ENTRIES_MASK 0x0f + + //struct asd_ocm_entry_format entry[1]; +} __packed; + +#if 0 +//TBD: check and remove +struct asd_unit_id_direct_attached_sata { + uint8_t phy_id; + uint8_t res[15]; +} __packed; + +struct asd_unit_id_logical_unit { + uint8_t sas_address[SAS_ADDR_LEN]; + uint8_t lun[8]; +} __packed; + +struct asd_unit_id_volume_set { + uint8_t volume_set_uid[8]; + uint8_t res[8]; +} __packed; + +/* unit element */ +struct asd_unit_element_format { + uint8_t id[16]; +#define UNIT_ELEMENT_DIRECT_ATTACHED_SATA 0x00 +#define UNIT_ELEMENT_LOGICAL_UNIT 0x01 +#define UNIT_ELEMENT_VOLUME_SET 0x02 + uint8_t type; + uint8_t res1; + uint8_t dos_drv_num; + uint8_t removable; + uint32_t res2; +} __packed; +#endif + +struct asd_uid_lu_naa_wwn { + uint8_t naa; + /* length specified by unit_id_len */ +} __packed; + +struct asd_uid_lu_sata_model_num { + uint32_t id; /* "ata." */ +#define UNITID_SATA_ID 0x6174612E + + uint8_t model[40]; + uint8_t serial[20]; + uint32_t null_data; + /* length specified by unit_id_len */ +} __packed; + + +struct asd_uid_vol_set { +#define UNITID_VOLUME_SET_UID_LEN 24 + uint8_t vol_set_uid[UNITID_VOLUME_SET_UID_LEN]; + /* length specified by unit_id_len */ +} __packed; + +struct asd_uid_lu_sgpio { + uint8_t conn_idx; + uint8_t box_id; + uint8_t bay_id; + uint32_t res1[5]; + uint8_t lun[8]; + /* length specified by unit_id_len */ +} __packed; + +struct asd_uid_lu_sas_topology { + uint8_t exp_dev_name[8]; + uint8_t lun[8]; + uint8_t phy_id; + /* length specified by unit_id_len */ +} __packed; + +/* unit element */ +struct asd_unit_element_format { + uint8_t id; +#define UNITELEM_LU_NAA_WWN 0x00 +#define UNITELEM_LU_SATA_MOD_SERIAL_NUM 0x01 +#define UNITELEM_VOLUME_SET_DDF_GUID 0x02 +#define UNITELEM_LU_SGPIO 0x03 +#define UNITELEM_LU_SAS_TOPOLOGY 0x04 + + uint8_t dos_drv_num; + uint8_t removable_unit; +#define UNITELEM_REMOVABLE_UNIT_MASK 0x01 + + uint32_t res1; + uint8_t unit_id_len; + uint8_t res2[8]; +} __packed; + +/* BIOS CHIM section */ +struct asd_bios_chim_format { + uint32_t signature; /* 'BIOS' or 'ASPI' */ +#define OCM_BC_BIOS_SIGN 0x42494F53 +#define OCM_BC_ASPI_SIGN 0x41535049 + + uint8_t maj_ver; /* 0x01 */ + uint8_t min_ver; /* 0x00 */ + uint8_t bios_maj_ver; + uint8_t bios_min_ver; + uint32_t bios_bld_num; + uint8_t bios_present; +#define OCM_BC_BBS_MASK 0x04 +#define OCM_BC_BIOS_INSLD_MASK 0x02 +#define OCM_BC_BIOS_PRSNT_MASK 0x01 + + uint8_t pci_slot_num; + uint16_t num_elements; + uint16_t size_unit_elem; + uint8_t res1[14]; + struct asd_unit_element_format unit_elm[1]; +} __packed; + +/* + * These macros take a 8 byte base SAS address and get/set + * it's constituent elements. + */ + +/* Default: 0x5 */ +#define ASD_BSAR_GET_NAA(x) ((x[0] >> 4) & 0x0f) + +/* Default: 0x0000D1 - 3 byte IEEE Id assigned to Adaptec */ +#define ASD_BSAR_GET_IEEE_ID(x) \ +(((x[0] & 0x0f) << 20) | (x[1] << 12) | (x[2] << 4) | ((x[3] >> 4) & 0x0f)) + +/* get the 4 byte Razor serial number */ +#define ASD_BSAR_GET_SN(x) \ +(((x[3] & 0x0f) << 28) | (x[4] << 20) | (x[5] << 12) \ +| (x[6] << 4) | (((x[7] >> 5) & 0x07) << 1)) + +/*Default: 00000b - configurable using Ctrl-A */ +#define ASD_BSAR_GET_LSB(x) (x[7] & 0x1f) +#define ASD_BSAR_SET_LSB(x, y) (x[7] = ((x[7] & 0x1f) & (y & 0x1f))) + +struct asd_manuf_seg_sign { + uint16_t signature; +#define NVRAM_MNF_BASE_SEG_SIGN 0x4D53 /* 'M'anufacturing 'S'egment */ +#define NVRAM_MNF_PHY_PARAM_SIGN 0x4D50 /* 'M'anufacturing 'P'hy Parameters */ +#define NVRAM_MNF_CONN_MAP 0x434D /* 'C'onnector 'M'ap */ + + uint16_t next_seg_ptr; +} __packed; + +/* Manufacturing Base Segment Layout. */ +struct asd_manuf_base_seg_layout { + struct asd_manuf_seg_sign seg_sign; + uint8_t major_ver; /* 0x00 */ + uint8_t minor_ver; /* 0x00 */ + uint16_t checksum; + uint16_t sector_size; + uint8_t res1[6]; + uint8_t base_sas_addr[8]; + uint8_t pcba_sn[12]; +} __packed; + +/* Phy Descriptor sub structure */ +struct asd_phy_desc_format { + uint8_t state; +#define NVRAM_PHY_ENABLEABLE 0x00 +#define NVRAM_PHY_REPORTED 0x01 +#define NVRAM_PHY_HIDDEN 0x02 +#define PHY_STATE_MASK 0x0F +#define PHY_STATE_DEFAULT NVRAM_PHY_ENABLEABLE + + uint8_t phy_id; + uint16_t res1; + uint8_t ctl0; +#define PHY_CTL0_DEFAULT 0xF6 +#define PHY_CTL0_MASK 0x1C + + uint8_t ctl1; +#define PHY_CTL1_DEFAULT 0x10 + + uint8_t ctl2; +#define PHY_CTL2_DEFAULT 0x43 + + uint8_t ctl3; +#define PHY_CTL3_DEFAULT 0x83 + +} __packed; + +/* Manufacturing Phy Parameters Layout */ +struct asd_manuf_phy_param_layout { + struct asd_manuf_seg_sign seg_sign; + uint8_t major_ver; /* 0x00 */ + uint8_t minor_ver; /* 0x02 */ + uint8_t num_phy_desc; /* 0x08 */ + uint8_t phy_desc_size; /* 0x08 */ + uint8_t res1[3]; + uint8_t usage_model_id; + uint8_t res2[4]; +} __packed; + + +/* Phy Descriptor Unattached Layout */ +struct asd_pd_ua_format { + uint16_t res1; + uint8_t rel_phy_id; + /* size is specified by the node_desc format */ +} __packed; + +/* Phy Descriptor connector attached Layout */ +struct asd_pd_ca_format { + uint8_t idx; + uint8_t lane; + uint8_t rel_phy_id; + /* size is specified by the node_desc format */ +} __packed; + +/* Phy Descriptor node attached Layout */ +struct asd_pd_na_format { + uint8_t idx; + uint8_t att_phy_id; + uint8_t rel_phy_id; + /* size is specified by the node_desc format */ +} __packed; + +/* Node descriptor's Phy descriptor entries */ +struct asd_nd_phydesc_format { + uint8_t type; +#define NV_PD_UATTACH 0x00 +#define NV_PD_CONATTACH 0x01 +#define NV_PD_NODEATTACH 0x02 + + union { + struct asd_pd_ua_format uatt; + struct asd_pd_ca_format catt; + struct asd_pd_na_format natt; + }att_type; +} __packed; + +/* Node Descriptor Layout */ +struct asd_node_desc_format { + uint8_t type; +#define NV_NODET_IOP 0x00 +#define NV_NODET_IOCTLR 0x01 +#define NV_NODET_EXPANDER 0x02 +#define NV_NODET_PORT_MUL 0x03 +#define NV_NODET_PORT_MUX 0x04 +#define NV_NODET_PORT_MDI2C_BUS 0x05 + + uint8_t num_phy_desc; + uint8_t phy_desc_size; + uint8_t res1; + +#define NV_NODED_INST_NAME_SIZE 16 + uint8_t inst_name[NV_NODED_INST_NAME_SIZE]; +} __packed; + +/* SideBand Descriptor Layout */ +struct asd_sb_desc_format { + uint8_t type; +#define NV_SBT_UNKNOWN 0x00 +#define NV_SBT_SGPIO 0x01 +#define NV_SBT_ADPTI2C 0x80 +#define NV_SBT_VEN_UNQ01 0x81 +#define NV_SBT_VEN_UNQ7F 0xFF + + uint8_t node_desc_idx; + uint8_t conn_desc_idx; + uint8_t res1; + /* size is specified by the conn_desc format */ +} __packed; + +/* Connector Descriptor Layout */ +struct asd_conn_desc_format { + uint8_t type; +#define NV_CONNT_UNKNOWN 0x00 +#define NV_CONNT_SFF8470 0x08 +#define NV_CONNT_SFF8482 0x09 +#define NV_CONNT_SFF8484 0x0A +#define NV_CONNT_PCIX_D0 0x80 +#define NV_CONNT_SAS_D0 0x81 +#define NV_CONNT_VEN_UNQ02 0x82 +#define NV_CONNT_VEN_UNQ7F 0xFF + + uint8_t location; +#define NV_CONNL_UNKNOWN 0x00 +#define NV_CONNL_INTERNAL 0x01 +#define NV_CONNL_EXTERNAL 0x02 +#define NV_CONNL_B2B 0x03 + + uint8_t num_sb_desc; + uint8_t sb_desc_size; + uint32_t res1; + +#define NV_CONND_INST_NAME_SIZE 16 + uint8_t inst_name[NV_CONND_INST_NAME_SIZE]; +} __packed; + +/* Connector Map Layout */ +struct asd_conn_map_format { + struct asd_manuf_seg_sign seg_sign; + uint8_t major_ver; /* 0x00 */ + uint8_t minor_ver; /* 0x00 */ + uint16_t size; + uint8_t num_conn_desc; + uint8_t conn_desc_size; + uint8_t num_node_desc; + uint8_t usage_model_id; + uint32_t res1; +} __packed; + +struct asd_settings_layout { + uint8_t id; +#define NVRAM_PHY_SETTINGS_ID 0x68 +#define NVRAM_BOOT_UNIT_SETTINGS_ID 0x42 +#define NVRAM_BOOTLUN_SETTINGS_ID 0x4c + + uint8_t res; + uint16_t next_ptr; +} __packed; + + +/* + * The size of Flash directory structure must be 64 bytes for backward + * compatibility. + */ +struct asd_fd_entry_layout { + uint32_t attr; +#define FD_ENTRYTYPE_CODE 0x3FFFFFFF +#define FD_SEGMENT_ATTR 0x40000000 + + uint32_t offset; + uint32_t pad_size; + uint32_t image_size; + uint32_t checksum; + uint8_t res[12]; + uint8_t ver_data[32]; +} __packed; + +struct asd_flash_dir_layout { + + uint8_t cookie[32]; /* "*** ADAPTEC FLASH DIRECTORY *** " */ + uint32_t rev; /* 0x00000002 */ + uint32_t wchk_sum; + uint32_t wchk_sum_antidote; + uint32_t build_num; + uint8_t build_id[32]; + uint8_t ver_data[32]; + uint32_t ae_mask; + uint32_t v_mask; + uint32_t oc_mask; + uint8_t res1[20]; + //struct asd_fd_entry_layout entry[1]; +} __packed; + +struct asd_phy_settings_entry_layout { + uint8_t sas_addr[SAS_ADDR_LEN]; + uint8_t link_rate; /* + * bits 0-3: minimum link rate + * bits 4-7: maximum link rate + */ +#define PHY_MIN_LINK_RATE_15 0x08 +#define PHY_MIN_LINK_RATE_30 0x09 +#define PHY_MIN_LINK_RATE_MASK 0x0F + +#define PHY_MAX_LINK_RATE_15 0x80 +#define PHY_MAX_LINK_RATE_30 0x90 +#define PHY_MAX_LINK_RATE_MASK 0xF0 + + uint8_t attr; /* + * bit 0: disable CRC checking + * bit 1: SATA spinup hold + */ + uint8_t res1[6]; +} __packed; + +struct asd_phy_settings_layout { + struct asd_settings_layout settings; + uint8_t num_phys; + uint8_t res2[3]; + //struct asd_phy_settings_entry_layout entry[1]; +} __packed; + +struct asd_boot_lu_layout { + uint8_t serial_no[4]; /* Adapter serial number */ + /* Boot device's SAS address */ + uint8_t dev_port_sas_addr[SAS_ADDR_LEN]; + uint8_t lun[8]; /* Boot device LUN */ + uint8_t phy_id; /* + * Phy ID of the attached boot + * device (direct attached + * SATA only). + */ + uint8_t res1; + uint16_t attr; + uint8_t conn_rate; /* + * bit 0: force connection + * bit 4-7: connection rate + */ +#define BOOT_FORCE_CONN 0x01 +#define BOOT_CONN_RATE_15 0x80 +#define BOOT_CONN_RATE_30 0x90 +#define BOOT_CONN_RATE_MASK 0xF0 + + uint8_t res2[7]; +} __packed; + +struct asd_pci_layout { + uint8_t id; + uint8_t res; + uint16_t next_ptr; + uint8_t major_ver; + uint8_t minor_ver; + uint16_t checksum; + uint16_t image_size; +} __packed; + +/************************ Flash part related macros ***********************/ +#define FLASH_MANUF_ID_AMD 0x01 +#define FLASH_MANUF_ID_UNKNOWN 0xFF + +#define FLASH_DEV_ID_AM29LV008B 0x3E +#define FLASH_DEV_ID_AM29LV800D 0xDA +#define FLASH_DEV_ID_UNKNOWN 0xFF + +/* status bit mask values */ +#define FLASH_STATUS_BIT_MASK_DQ6 0x40 +#define FLASH_STATUS_BIT_MASK_DQ5 0x20 +#define FLASH_STATUS_BIT_MASK_DQ2 0x04 + +/* minimum value in micro seconds needed for checking status */ +#define FLASH_STATUS_ERASE_DELAY_COUNT 50 +#define FLASH_STATUS_WRITE_DELAY_COUNT 25 + +#endif /* NVRAM_SUPPORT */ + +#endif /* ADP94XX_HWI_H */ +