📄 sym_hipd.h
字号:
* These values are assumed to have been set by BIOS, and may * be used to probe adapter implementation differences. */ u_char sv_scntl0, sv_scntl3, sv_dmode, sv_dcntl, sv_ctest3, sv_ctest4, sv_ctest5, sv_gpcntl, sv_stest2, sv_stest4, sv_scntl4, sv_stest1; /* * Actual initial value of IO register bits used by the * driver. They are loaded at initialisation according to * features that are to be enabled/disabled. */ u_char rv_scntl0, rv_scntl3, rv_dmode, rv_dcntl, rv_ctest3, rv_ctest4, rv_ctest5, rv_stest2, rv_ccntl0, rv_ccntl1, rv_scntl4; /* * Target data. */ struct sym_tcb target[SYM_CONF_MAX_TARGET]; /* * Target control block bus address array used by the SCRIPT * on reselection. */ u32 *targtbl; u32 targtbl_ba; /* * DMA pool handle for this HBA. */ m_pool_ident_t bus_dmat; /* * O/S specific data structure */ struct sym_shcb s; /* * Physical bus addresses of the chip. */ u32 mmio_ba; /* MMIO 32 bit BUS address */ int mmio_ws; /* MMIO Window size */ u32 ram_ba; /* RAM 32 bit BUS address */ int ram_ws; /* RAM window size */ /* * SCRIPTS virtual and physical bus addresses. * 'script' is loaded in the on-chip RAM if present. * 'scripth' stays in main memory for all chips except the * 53C895A, 53C896 and 53C1010 that provide 8K on-chip RAM. */ u_char *scripta0; /* Copy of scripts A, B, Z */ u_char *scriptb0; u_char *scriptz0; u32 scripta_ba; /* Actual scripts A, B, Z */ u32 scriptb_ba; /* 32 bit bus addresses. */ u32 scriptz_ba; u_short scripta_sz; /* Actual size of script A, B, Z*/ u_short scriptb_sz; u_short scriptz_sz; /* * Bus addresses, setup and patch methods for * the selected firmware. */ struct sym_fwa_ba fwa_bas; /* Useful SCRIPTA bus addresses */ struct sym_fwb_ba fwb_bas; /* Useful SCRIPTB bus addresses */ struct sym_fwz_ba fwz_bas; /* Useful SCRIPTZ bus addresses */ void (*fw_setup)(struct sym_hcb *np, struct sym_fw *fw); void (*fw_patch)(struct sym_hcb *np); char *fw_name; /* * General controller parameters and configuration. */ u_short device_id; /* PCI device id */ u_char revision_id; /* PCI device revision id */ u_int features; /* Chip features map */ u_char myaddr; /* SCSI id of the adapter */ u_char maxburst; /* log base 2 of dwords burst */ u_char maxwide; /* Maximum transfer width */ u_char minsync; /* Min sync period factor (ST) */ u_char maxsync; /* Max sync period factor (ST) */ u_char maxoffs; /* Max scsi offset (ST) */ u_char minsync_dt; /* Min sync period factor (DT) */ u_char maxsync_dt; /* Max sync period factor (DT) */ u_char maxoffs_dt; /* Max scsi offset (DT) */ u_char multiplier; /* Clock multiplier (1,2,4) */ u_char clock_divn; /* Number of clock divisors */ u32 clock_khz; /* SCSI clock frequency in KHz */ u32 pciclk_khz; /* Estimated PCI clock in KHz */ /* * Start queue management. * It is filled up by the host processor and accessed by the * SCRIPTS processor in order to start SCSI commands. */ volatile /* Prevent code optimizations */ u32 *squeue; /* Start queue virtual address */ u32 squeue_ba; /* Start queue BUS address */ u_short squeueput; /* Next free slot of the queue */ u_short actccbs; /* Number of allocated CCBs */ /* * Command completion queue. * It is the same size as the start queue to avoid overflow. */ u_short dqueueget; /* Next position to scan */ volatile /* Prevent code optimizations */ u32 *dqueue; /* Completion (done) queue */ u32 dqueue_ba; /* Done queue BUS address */ /* * Miscellaneous buffers accessed by the scripts-processor. * They shall be DWORD aligned, because they may be read or * written with a script command. */ u_char msgout[8]; /* Buffer for MESSAGE OUT */ u_char msgin [8]; /* Buffer for MESSAGE IN */ u32 lastmsg; /* Last SCSI message sent */ u32 scratch; /* Scratch for SCSI receive */ /* Also used for cache test */ /* * Miscellaneous configuration and status parameters. */ u_char usrflags; /* Miscellaneous user flags */ u_char scsi_mode; /* Current SCSI BUS mode */ u_char verbose; /* Verbosity for this controller*/ /* * CCB lists and queue. */ struct sym_ccb **ccbh; /* CCBs hashed by DSA value */ /* CCB_HASH_SIZE lists of CCBs */ SYM_QUEHEAD free_ccbq; /* Queue of available CCBs */ SYM_QUEHEAD busy_ccbq; /* Queue of busy CCBs */ /* * During error handling and/or recovery, * active CCBs that are to be completed with * error or requeued are moved from the busy_ccbq * to the comp_ccbq prior to completion. */ SYM_QUEHEAD comp_ccbq;#ifdef SYM_OPT_HANDLE_DEVICE_QUEUEING SYM_QUEHEAD dummy_ccbq;#endif /* * IMMEDIATE ARBITRATION (IARB) control. * * We keep track in 'last_cp' of the last CCB that has been * queued to the SCRIPTS processor and clear 'last_cp' when * this CCB completes. If last_cp is not zero at the moment * we queue a new CCB, we set a flag in 'last_cp' that is * used by the SCRIPTS as a hint for setting IARB. * We donnot set more than 'iarb_max' consecutive hints for * IARB in order to leave devices a chance to reselect. * By the way, any non zero value of 'iarb_max' is unfair. :) */#ifdef SYM_CONF_IARB_SUPPORT u_short iarb_max; /* Max. # consecutive IARB hints*/ u_short iarb_count; /* Actual # of these hints */ struct sym_ccb * last_cp;#endif /* * Command abort handling. * We need to synchronize tightly with the SCRIPTS * processor in order to handle things correctly. */ u_char abrt_msg[4]; /* Message to send buffer */ struct sym_tblmove abrt_tbl; /* Table for the MOV of it */ struct sym_tblsel abrt_sel; /* Sync params for selection */ u_char istat_sem; /* Tells the chip to stop (SEM) */ /* * 64 bit DMA handling. */#if SYM_CONF_DMA_ADDRESSING_MODE != 0 u_char use_dac; /* Use PCI DAC cycles */#if SYM_CONF_DMA_ADDRESSING_MODE == 2 u_char dmap_dirty; /* Dma segments registers dirty */ u32 dmap_bah[SYM_DMAP_SIZE];/* Segment registers map */#endif#endif};#define HCB_BA(np, lbl) (np->hcb_ba + offsetof(struct sym_hcb, lbl))/* * FIRMWARES (sym_fw.c) */struct sym_fw * sym_find_firmware(struct sym_chip *chip);void sym_fw_bind_script(struct sym_hcb *np, u32 *start, int len);/* * Driver methods called from O/S specific code. */char *sym_driver_name(void);void sym_print_xerr(struct scsi_cmnd *cmd, int x_status);int sym_reset_scsi_bus(struct sym_hcb *np, int enab_int);struct sym_chip *sym_lookup_chip_table(u_short device_id, u_char revision);void sym_put_start_queue(struct sym_hcb *np, struct sym_ccb *cp);#ifdef SYM_OPT_HANDLE_DEVICE_QUEUEINGvoid sym_start_next_ccbs(struct sym_hcb *np, struct sym_lcb *lp, int maxn);#endifvoid sym_start_up(struct sym_hcb *np, int reason);void sym_interrupt(struct sym_hcb *np);int sym_clear_tasks(struct sym_hcb *np, int cam_status, int target, int lun, int task);struct sym_ccb *sym_get_ccb(struct sym_hcb *np, struct scsi_cmnd *cmd, u_char tag_order);void sym_free_ccb(struct sym_hcb *np, struct sym_ccb *cp);struct sym_lcb *sym_alloc_lcb(struct sym_hcb *np, u_char tn, u_char ln);int sym_queue_scsiio(struct sym_hcb *np, struct scsi_cmnd *csio, struct sym_ccb *cp);int sym_abort_scsiio(struct sym_hcb *np, struct scsi_cmnd *ccb, int timed_out);int sym_reset_scsi_target(struct sym_hcb *np, int target);void sym_hcb_free(struct sym_hcb *np);int sym_hcb_attach(struct Scsi_Host *shost, struct sym_fw *fw, struct sym_nvram *nvram);/* * Build a scatter/gather entry. * * For 64 bit systems, we use the 8 upper bits of the size field * to provide bus address bits 32-39 to the SCRIPTS processor. * This allows the 895A, 896, 1010 to address up to 1 TB of memory. */#if SYM_CONF_DMA_ADDRESSING_MODE == 0#define sym_build_sge(np, data, badd, len) \do { \ (data)->addr = cpu_to_scr(badd); \ (data)->size = cpu_to_scr(len); \} while (0)#elif SYM_CONF_DMA_ADDRESSING_MODE == 1#define sym_build_sge(np, data, badd, len) \do { \ (data)->addr = cpu_to_scr(badd); \ (data)->size = cpu_to_scr((((badd) >> 8) & 0xff000000) + len); \} while (0)#elif SYM_CONF_DMA_ADDRESSING_MODE == 2int sym_lookup_dmap(struct sym_hcb *np, u32 h, int s);static __inline void sym_build_sge(struct sym_hcb *np, struct sym_tblmove *data, u64 badd, int len){ u32 h = (badd>>32); int s = (h&SYM_DMAP_MASK); if (h != np->dmap_bah[s]) goto bad;good: (data)->addr = cpu_to_scr(badd); (data)->size = cpu_to_scr((s<<24) + len); return;bad: s = sym_lookup_dmap(np, h, s); goto good;}#else#error "Unsupported DMA addressing mode"#endif/* * Set up data pointers used by SCRIPTS. * Called from O/S specific code. */static inline void sym_setup_data_pointers(struct sym_hcb *np, struct sym_ccb *cp, int dir){ u32 lastp, goalp; /* * No segments means no data. */ if (!cp->segments) dir = DMA_NONE; /* * Set the data pointer. */ switch(dir) {#ifdef SYM_OPT_HANDLE_DIR_UNKNOWN case DMA_BIDIRECTIONAL:#endif case DMA_TO_DEVICE: goalp = SCRIPTA_BA(np, data_out2) + 8; lastp = goalp - 8 - (cp->segments * (2*4));#ifdef SYM_OPT_HANDLE_DIR_UNKNOWN cp->wgoalp = cpu_to_scr(goalp); if (dir != DMA_BIDIRECTIONAL) break; cp->phys.head.wlastp = cpu_to_scr(lastp); /* fall through */#else break;#endif case DMA_FROM_DEVICE: cp->host_flags |= HF_DATA_IN; goalp = SCRIPTA_BA(np, data_in2) + 8; lastp = goalp - 8 - (cp->segments * (2*4)); break; case DMA_NONE: default:#ifdef SYM_OPT_HANDLE_DIR_UNKNOWN cp->host_flags |= HF_DATA_IN;#endif lastp = goalp = SCRIPTB_BA(np, no_data); break; } /* * Set all pointers values needed by SCRIPTS. */ cp->phys.head.lastp = cpu_to_scr(lastp); cp->phys.head.savep = cpu_to_scr(lastp); cp->startp = cp->phys.head.savep; cp->goalp = cpu_to_scr(goalp);#ifdef SYM_OPT_HANDLE_DIR_UNKNOWN /* * If direction is unknown, start at data_io. */ if (dir == DMA_BIDIRECTIONAL) cp->phys.head.savep = cpu_to_scr(SCRIPTB_BA(np, data_io));#endif}/* * MEMORY ALLOCATOR. */#define sym_get_mem_cluster() \ (void *) __get_free_pages(GFP_ATOMIC, SYM_MEM_PAGE_ORDER)#define sym_free_mem_cluster(p) \ free_pages((unsigned long)p, SYM_MEM_PAGE_ORDER)/* * Link between free memory chunks of a given size. */typedef struct sym_m_link { struct sym_m_link *next;} *m_link_p;/* * Virtual to bus physical translation for a given cluster. * Such a structure is only useful with DMA abstraction. */typedef struct sym_m_vtob { /* Virtual to Bus address translation */ struct sym_m_vtob *next; void *vaddr; /* Virtual address */ dma_addr_t baddr; /* Bus physical address */} *m_vtob_p;/* Hash this stuff a bit to speed up translations */#define VTOB_HASH_SHIFT 5#define VTOB_HASH_SIZE (1UL << VTOB_HASH_SHIFT)#define VTOB_HASH_MASK (VTOB_HASH_SIZE-1)#define VTOB_HASH_CODE(m) \ ((((unsigned long)(m)) >> SYM_MEM_CLUSTER_SHIFT) & VTOB_HASH_MASK)/* * Memory pool of a given kind. * Ideally, we want to use: * 1) 1 pool for memory we donnot need to involve in DMA. * 2) The same pool for controllers that require same DMA * constraints and features. * The OS specific m_pool_id_t thing and the sym_m_pool_match() * method are expected to tell the driver about. */typedef struct sym_m_pool { m_pool_ident_t dev_dmat; /* Identifies the pool (see above) */ void * (*get_mem_cluster)(struct sym_m_pool *);#ifdef SYM_MEM_FREE_UNUSED void (*free_mem_cluster)(struct sym_m_pool *, void *);#endif#define M_GET_MEM_CLUSTER() mp->get_mem_cluster(mp)#define M_FREE_MEM_CLUSTER(p) mp->free_mem_cluster(mp, p) int nump; m_vtob_p vtob[VTOB_HASH_SIZE]; struct sym_m_pool *next; struct sym_m_link h[SYM_MEM_CLUSTER_SHIFT - SYM_MEM_SHIFT + 1];} *m_pool_p;/* * Alloc, free and translate addresses to bus physical * for DMAable memory. */void *__sym_calloc_dma(m_pool_ident_t dev_dmat, int size, char *name);void __sym_mfree_dma(m_pool_ident_t dev_dmat, void *m, int size, char *name);dma_addr_t __vtobus(m_pool_ident_t dev_dmat, void *m);/* * Verbs used by the driver code for DMAable memory handling. * The _uvptv_ macro avoids a nasty warning about pointer to volatile * being discarded. */#define _uvptv_(p) ((void *)((u_long)(p)))#define _sym_calloc_dma(np, l, n) __sym_calloc_dma(np->bus_dmat, l, n)#define _sym_mfree_dma(np, p, l, n) \ __sym_mfree_dma(np->bus_dmat, _uvptv_(p), l, n)#define sym_calloc_dma(l, n) _sym_calloc_dma(np, l, n)#define sym_mfree_dma(p, l, n) _sym_mfree_dma(np, p, l, n)#define vtobus(p) __vtobus(np->bus_dmat, _uvptv_(p))/* * We have to provide the driver memory allocator with methods for * it to maintain virtual to bus physical address translations. */#define sym_m_pool_match(mp_id1, mp_id2) (mp_id1 == mp_id2)static __inline void *sym_m_get_dma_mem_cluster(m_pool_p mp, m_vtob_p vbp){ void *vaddr = NULL; dma_addr_t baddr = 0; vaddr = dma_alloc_coherent(mp->dev_dmat, SYM_MEM_CLUSTER_SIZE, &baddr, GFP_ATOMIC); if (vaddr) { vbp->vaddr = vaddr; vbp->baddr = baddr; } return vaddr;}static __inline void sym_m_free_dma_mem_cluster(m_pool_p mp, m_vtob_p vbp){ dma_free_coherent(mp->dev_dmat, SYM_MEM_CLUSTER_SIZE, vbp->vaddr, vbp->baddr);}#endif /* SYM_HIPD_H */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -