📄 aic79xx.h
字号:
* The driver keeps up to MAX_SCB scb structures per card in memory. The SCB * consists of a "hardware SCB" mirroring the fields available on the card * and additional information the kernel stores for each transaction. * * To minimize space utilization, a portion of the hardware scb stores * different data during different portions of a SCSI transaction. * As initialized by the host driver for the initiator role, this area * contains the SCSI cdb (or a pointer to the cdb) to be executed. After * the cdb has been presented to the target, this area serves to store * residual transfer information and the SCSI status byte. * For the target role, the contents of this area do not change, but * still serve a different purpose than for the initiator role. See * struct target_data for details. *//* * Status information embedded in the shared poriton of * an SCB after passing the cdb to the target. The kernel * driver will only read this data for transactions that * complete abnormally. */struct initiator_status { uint32_t residual_datacnt; /* Residual in the current S/G seg */ uint32_t residual_sgptr; /* The next S/G for this transfer */ uint8_t scsi_status; /* Standard SCSI status byte */};struct target_status { uint32_t residual_datacnt; /* Residual in the current S/G seg */ uint32_t residual_sgptr; /* The next S/G for this transfer */ uint8_t scsi_status; /* SCSI status to give to initiator */ uint8_t target_phases; /* Bitmap of phases to execute */ uint8_t data_phase; /* Data-In or Data-Out */ uint8_t initiator_tag; /* Initiator's transaction tag */};/* * Initiator mode SCB shared data area. * If the embedded CDB is 12 bytes or less, we embed * the sense buffer address in the SCB. This allows * us to retrieve sense information without interrupting * the host in packetized mode. */typedef uint32_t sense_addr_t;#define MAX_CDB_LEN 16#define MAX_CDB_LEN_WITH_SENSE_ADDR (MAX_CDB_LEN - sizeof(sense_addr_t))union initiator_data { struct { uint64_t cdbptr; uint8_t cdblen; } cdb_from_host; uint8_t cdb[MAX_CDB_LEN]; struct { uint8_t cdb[MAX_CDB_LEN_WITH_SENSE_ADDR]; sense_addr_t sense_addr; } cdb_plus_saddr;};/* * Target mode version of the shared data SCB segment. */struct target_data { uint32_t spare[2]; uint8_t scsi_status; /* SCSI status to give to initiator */ uint8_t target_phases; /* Bitmap of phases to execute */ uint8_t data_phase; /* Data-In or Data-Out */ uint8_t initiator_tag; /* Initiator's transaction tag */};struct hardware_scb {/*0*/ union { union initiator_data idata; struct target_data tdata; struct initiator_status istatus; struct target_status tstatus; } shared_data;/* * A word about residuals. * The scb is presented to the sequencer with the dataptr and datacnt * fields initialized to the contents of the first S/G element to * transfer. The sgptr field is initialized to the bus address for * the S/G element that follows the first in the in core S/G array * or'ed with the SG_FULL_RESID flag. Sgptr may point to an invalid * S/G entry for this transfer (single S/G element transfer with the * first elements address and length preloaded in the dataptr/datacnt * fields). If no transfer is to occur, sgptr is set to SG_LIST_NULL. * The SG_FULL_RESID flag ensures that the residual will be correctly * noted even if no data transfers occur. Once the data phase is entered, * the residual sgptr and datacnt are loaded from the sgptr and the * datacnt fields. After each S/G element's dataptr and length are * loaded into the hardware, the residual sgptr is advanced. After * each S/G element is expired, its datacnt field is checked to see * if the LAST_SEG flag is set. If so, SG_LIST_NULL is set in the * residual sg ptr and the transfer is considered complete. If the * sequencer determines that there is a residual in the tranfer, or * there is non-zero status, it will set the SG_STATUS_VALID flag in * sgptr and dma the scb back into host memory. To sumarize: * * Sequencer: * o A residual has occurred if SG_FULL_RESID is set in sgptr, * or residual_sgptr does not have SG_LIST_NULL set. * * o We are transfering the last segment if residual_datacnt has * the SG_LAST_SEG flag set. * * Host: * o A residual can only have occurred if a completed scb has the * SG_STATUS_VALID flag set. Inspection of the SCSI status field, * the residual_datacnt, and the residual_sgptr field will tell * for sure. * * o residual_sgptr and sgptr refer to the "next" sg entry * and so may point beyond the last valid sg entry for the * transfer. */ #define SG_PTR_MASK 0xFFFFFFF8/*16*/ uint16_t tag; /* Reused by Sequencer. *//*18*/ uint8_t control; /* See SCB_CONTROL in aic79xx.reg for details *//*19*/ uint8_t scsiid; /* * Selection out Id * Our Id (bits 0-3) Their ID (bits 4-7) *//*20*/ uint8_t lun;/*21*/ uint8_t task_attribute;/*22*/ uint8_t cdb_len;/*23*/ uint8_t task_management;/*24*/ uint64_t dataptr;/*32*/ uint32_t datacnt; /* Byte 3 is spare. *//*36*/ uint32_t sgptr;/*40*/ uint32_t hscb_busaddr;/*44*/ uint32_t next_hscb_busaddr;/********** Long lun field only downloaded for full 8 byte lun support ********//*48*/ uint8_t pkt_long_lun[8];/******* Fields below are not Downloaded (Sequencer may use for scratch) ******//*56*/ uint8_t spare[8];};/************************ Kernel SCB Definitions ******************************//* * Some fields of the SCB are OS dependent. Here we collect the * definitions for elements that all OS platforms need to include * in there SCB definition. *//* * Definition of a scatter/gather element as transfered to the controller. * The aic7xxx chips only support a 24bit length. We use the top byte of * the length to store additional address bits and a flag to indicate * that a given segment terminates the transfer. This gives us an * addressable range of 512GB on machines with 64bit PCI or with chips * that can support dual address cycles on 32bit PCI busses. */struct ahd_dma_seg { uint32_t addr; uint32_t len;#define AHD_DMA_LAST_SEG 0x80000000#define AHD_SG_HIGH_ADDR_MASK 0x7F000000#define AHD_SG_LEN_MASK 0x00FFFFFF};struct ahd_dma64_seg { uint64_t addr; uint32_t len; uint32_t pad;};struct map_node { bus_dmamap_t dmamap; dma_addr_t physaddr; uint8_t *vaddr; SLIST_ENTRY(map_node) links;};/* * The current state of this SCB. */typedef enum { SCB_FLAG_NONE = 0x00000, SCB_TRANSMISSION_ERROR = 0x00001,/* * We detected a parity or CRC * error that has effected the * payload of the command. This * flag is checked when normal * status is returned to catch * the case of a target not * responding to our attempt * to report the error. */ SCB_OTHERTCL_TIMEOUT = 0x00002,/* * Another device was active * during the first timeout for * this SCB so we gave ourselves * an additional timeout period * in case it was hogging the * bus. */ SCB_DEVICE_RESET = 0x00004, SCB_SENSE = 0x00008, SCB_CDB32_PTR = 0x00010, SCB_RECOVERY_SCB = 0x00020, SCB_AUTO_NEGOTIATE = 0x00040,/* Negotiate to achieve goal. */ SCB_NEGOTIATE = 0x00080,/* Negotiation forced for command. */ SCB_ABORT = 0x00100, SCB_ACTIVE = 0x00200, SCB_TARGET_IMMEDIATE = 0x00400, SCB_PACKETIZED = 0x00800, SCB_EXPECT_PPR_BUSFREE = 0x01000, SCB_PKT_SENSE = 0x02000, SCB_CMDPHASE_ABORT = 0x04000, SCB_ON_COL_LIST = 0x08000, SCB_SILENT = 0x10000 /* * Be quiet about transmission type * errors. They are expected and we * don't want to upset the user. This * flag is typically used during DV. */} scb_flag;struct scb { struct hardware_scb *hscb; union { SLIST_ENTRY(scb) sle; LIST_ENTRY(scb) le; TAILQ_ENTRY(scb) tqe; } links; union { SLIST_ENTRY(scb) sle; LIST_ENTRY(scb) le; TAILQ_ENTRY(scb) tqe; } links2;#define pending_links links2.le#define collision_links links2.le struct scb *col_scb; ahd_io_ctx_t io_ctx; struct ahd_softc *ahd_softc; scb_flag flags;#ifndef __linux__ bus_dmamap_t dmamap;#endif struct scb_platform_data *platform_data; struct map_node *hscb_map; struct map_node *sg_map; struct map_node *sense_map; void *sg_list; uint8_t *sense_data; dma_addr_t sg_list_busaddr; dma_addr_t sense_busaddr; u_int sg_count;/* How full ahd_dma_seg is */#define AHD_MAX_LQ_CRC_ERRORS 5 u_int crc_retry_count;};TAILQ_HEAD(scb_tailq, scb);LIST_HEAD(scb_list, scb);struct scb_data { /* * TAILQ of lists of free SCBs grouped by device * collision domains. */ struct scb_tailq free_scbs; /* * Per-device lists of SCBs whose tag ID would collide * with an already active tag on the device. */ struct scb_list free_scb_lists[AHD_NUM_TARGETS * AHD_NUM_LUNS_NONPKT]; /* * SCBs that will not collide with any active device. */ struct scb_list any_dev_free_scb_list; /* * Mapping from tag to SCB. */ struct scb *scbindex[AHD_SCB_MAX]; /* * "Bus" addresses of our data structures. */ bus_dma_tag_t hscb_dmat; /* dmat for our hardware SCB array */ bus_dma_tag_t sg_dmat; /* dmat for our sg segments */ bus_dma_tag_t sense_dmat; /* dmat for our sense buffers */ SLIST_HEAD(, map_node) hscb_maps; SLIST_HEAD(, map_node) sg_maps; SLIST_HEAD(, map_node) sense_maps; int scbs_left; /* unallocated scbs in head map_node */ int sgs_left; /* unallocated sgs in head map_node */ int sense_left; /* unallocated sense in head map_node */ uint16_t numscbs; uint16_t maxhscbs; /* Number of SCBs on the card */ uint8_t init_level; /* * How far we've initialized * this structure. */};/************************ Target Mode Definitions *****************************//* * Connection desciptor for select-in requests in target mode. */struct target_cmd { uint8_t scsiid; /* Our ID and the initiator's ID */ uint8_t identify; /* Identify message */ uint8_t bytes[22]; /* * Bytes contains any additional message * bytes terminated by 0xFF. The remainder * is the cdb to execute. */ uint8_t cmd_valid; /* * When a command is complete, the firmware * will set cmd_valid to all bits set. * After the host has seen the command, * the bits are cleared. This allows us * to just peek at host memory to determine * if more work is complete. cmd_valid is on * an 8 byte boundary to simplify setting * it on aic7880 hardware which only has * limited direct access to the DMA FIFO. */ uint8_t pad[7];};/* * Number of events we can buffer up if we run out * of immediate notify ccbs. */#define AHD_TMODE_EVENT_BUFFER_SIZE 8struct ahd_tmode_event { uint8_t initiator_id; uint8_t event_type; /* MSG type or EVENT_TYPE_BUS_RESET */#define EVENT_TYPE_BUS_RESET 0xFF uint8_t event_arg;};/* * Per enabled lun target mode state. * As this state is directly influenced by the host OS'es target mode * environment, we let the OS module define it. Forward declare the * structure here so we can store arrays of them, etc. in OS neutral * data structures. */#ifdef AHD_TARGET_MODE struct ahd_tmode_lstate { struct cam_path *path; struct ccb_hdr_slist accept_tios; struct ccb_hdr_slist immed_notifies; struct ahd_tmode_event event_buffer[AHD_TMODE_EVENT_BUFFER_SIZE]; uint8_t event_r_idx; uint8_t event_w_idx;};#elsestruct ahd_tmode_lstate;#endif/******************** Transfer Negotiation Datastructures *********************/#define AHD_TRANS_CUR 0x01 /* Modify current neogtiation status */#define AHD_TRANS_ACTIVE 0x03 /* Assume this target is on the bus */#define AHD_TRANS_GOAL 0x04 /* Modify negotiation goal */#define AHD_TRANS_USER 0x08 /* Modify user negotiation settings */#define AHD_PERIOD_10MHz 0x19#define AHD_WIDTH_UNKNOWN 0xFF#define AHD_PERIOD_UNKNOWN 0xFF#define AHD_OFFSET_UNKNOWN 0xFF#define AHD_PPR_OPTS_UNKNOWN 0xFF/* * Transfer Negotiation Information. */struct ahd_transinfo { uint8_t protocol_version; /* SCSI Revision level */ uint8_t transport_version; /* SPI Revision level */ uint8_t width; /* Bus width */ uint8_t period; /* Sync rate factor */ uint8_t offset; /* Sync offset */ uint8_t ppr_options; /* Parallel Protocol Request options */};/* * Per-initiator current, goal and user transfer negotiation information. */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -