📄 aic94xx_seq.c
字号:
udelay(PAUSE_DELAY); } } reg = asd_read_reg_dword(asd_ha, COMSTAT); if (!(reg & OVLYDMADONE) || (reg & OVLYERR) || (asd_read_reg_dword(asd_ha, CHIMINT) & DEVEXCEPT_MASK)){ asd_printk("%s: error DMA-ing sequencer code\n", pci_name(asd_ha->pcidev)); err = -ENODEV; } asd_free_coherent(asd_ha, token); out: asd_write_reg_dword(asd_ha, COMSTATEN, comstaten); return err ? : asd_verify_seq(asd_ha, prog, size, lseq_mask);}#else /* ASD_DMA_MODE_DOWNLOAD */static int asd_download_seq(struct asd_ha_struct *asd_ha, const u8 *_prog, u32 size, u8 lseq_mask){ int i; u32 reg = 0; const u32 *prog = (u32 *) _prog; if (size % 4) { asd_printk("sequencer program not multiple of 4\n"); return -1; } asd_pause_cseq(asd_ha); asd_pause_lseq(asd_ha, 0xFF); reg |= (lseq_mask ? (((u32)lseq_mask) << 8) : OVLYCSEQ); reg |= PIOCMODE; asd_write_reg_dword(asd_ha, OVLYDMACNT, size); asd_write_reg_dword(asd_ha, OVLYDMACTL, reg); ASD_DPRINTK("downloading %s sequencer%s in PIO mode...\n", lseq_mask ? "LSEQ" : "CSEQ", lseq_mask ? "s" : ""); for (i = 0; i < size; i += 4, prog++) asd_write_reg_dword(asd_ha, SPIODATA, *prog); reg = (reg & ~PIOCMODE) | OVLYHALTERR; asd_write_reg_dword(asd_ha, OVLYDMACTL, reg); return asd_verify_seq(asd_ha, _prog, size, lseq_mask);}#endif /* ASD_DMA_MODE_DOWNLOAD *//** * asd_seq_download_seqs - download the sequencer microcode * @asd_ha: pointer to host adapter structure * * Download the central and link sequencer microcode. */static int asd_seq_download_seqs(struct asd_ha_struct *asd_ha){ int err; if (!asd_ha->hw_prof.enabled_phys) { asd_printk("%s: no enabled phys!\n", pci_name(asd_ha->pcidev)); return -ENODEV; } /* Download the CSEQ */ ASD_DPRINTK("downloading CSEQ...\n"); err = asd_download_seq(asd_ha, cseq_code, cseq_code_size, 0); if (err) { asd_printk("CSEQ download failed:%d\n", err); return err; } /* Download the Link Sequencers code. All of the Link Sequencers * microcode can be downloaded at the same time. */ ASD_DPRINTK("downloading LSEQs...\n"); err = asd_download_seq(asd_ha, lseq_code, lseq_code_size, asd_ha->hw_prof.enabled_phys); if (err) { /* Try it one at a time */ u8 lseq; u8 lseq_mask = asd_ha->hw_prof.enabled_phys; for_each_sequencer(lseq_mask, lseq_mask, lseq) { err = asd_download_seq(asd_ha, lseq_code, lseq_code_size, 1<<lseq); if (err) break; } } if (err) asd_printk("LSEQs download failed:%d\n", err); return err;}/* ---------- Initializing the chip, chip memory, etc. ---------- *//** * asd_init_cseq_mip - initialize CSEQ mode independent pages 4-7 * @asd_ha: pointer to host adapter structure */static void asd_init_cseq_mip(struct asd_ha_struct *asd_ha){ /* CSEQ Mode Independent, page 4 setup. */ asd_write_reg_word(asd_ha, CSEQ_Q_EXE_HEAD, 0xFFFF); asd_write_reg_word(asd_ha, CSEQ_Q_EXE_TAIL, 0xFFFF); asd_write_reg_word(asd_ha, CSEQ_Q_DONE_HEAD, 0xFFFF); asd_write_reg_word(asd_ha, CSEQ_Q_DONE_TAIL, 0xFFFF); asd_write_reg_word(asd_ha, CSEQ_Q_SEND_HEAD, 0xFFFF); asd_write_reg_word(asd_ha, CSEQ_Q_SEND_TAIL, 0xFFFF); asd_write_reg_word(asd_ha, CSEQ_Q_DMA2CHIM_HEAD, 0xFFFF); asd_write_reg_word(asd_ha, CSEQ_Q_DMA2CHIM_TAIL, 0xFFFF); asd_write_reg_word(asd_ha, CSEQ_Q_COPY_HEAD, 0xFFFF); asd_write_reg_word(asd_ha, CSEQ_Q_COPY_TAIL, 0xFFFF); asd_write_reg_word(asd_ha, CSEQ_REG0, 0); asd_write_reg_word(asd_ha, CSEQ_REG1, 0); asd_write_reg_dword(asd_ha, CSEQ_REG2, 0); asd_write_reg_byte(asd_ha, CSEQ_LINK_CTL_Q_MAP, 0); { u8 con = asd_read_reg_byte(asd_ha, CCONEXIST); u8 val = hweight8(con); asd_write_reg_byte(asd_ha, CSEQ_MAX_CSEQ_MODE, (val<<4)|val); } asd_write_reg_word(asd_ha, CSEQ_FREE_LIST_HACK_COUNT, 0); /* CSEQ Mode independent, page 5 setup. */ asd_write_reg_dword(asd_ha, CSEQ_EST_NEXUS_REQ_QUEUE, 0); asd_write_reg_dword(asd_ha, CSEQ_EST_NEXUS_REQ_QUEUE+4, 0); asd_write_reg_dword(asd_ha, CSEQ_EST_NEXUS_REQ_COUNT, 0); asd_write_reg_dword(asd_ha, CSEQ_EST_NEXUS_REQ_COUNT+4, 0); asd_write_reg_word(asd_ha, CSEQ_Q_EST_NEXUS_HEAD, 0xFFFF); asd_write_reg_word(asd_ha, CSEQ_Q_EST_NEXUS_TAIL, 0xFFFF); asd_write_reg_word(asd_ha, CSEQ_NEED_EST_NEXUS_SCB, 0); asd_write_reg_byte(asd_ha, CSEQ_EST_NEXUS_REQ_HEAD, 0); asd_write_reg_byte(asd_ha, CSEQ_EST_NEXUS_REQ_TAIL, 0); asd_write_reg_byte(asd_ha, CSEQ_EST_NEXUS_SCB_OFFSET, 0); /* CSEQ Mode independent, page 6 setup. */ asd_write_reg_word(asd_ha, CSEQ_INT_ROUT_RET_ADDR0, 0); asd_write_reg_word(asd_ha, CSEQ_INT_ROUT_RET_ADDR1, 0); asd_write_reg_word(asd_ha, CSEQ_INT_ROUT_SCBPTR, 0); asd_write_reg_byte(asd_ha, CSEQ_INT_ROUT_MODE, 0); asd_write_reg_byte(asd_ha, CSEQ_ISR_SCRATCH_FLAGS, 0); asd_write_reg_word(asd_ha, CSEQ_ISR_SAVE_SINDEX, 0); asd_write_reg_word(asd_ha, CSEQ_ISR_SAVE_DINDEX, 0); asd_write_reg_word(asd_ha, CSEQ_Q_MONIRTT_HEAD, 0xFFFF); asd_write_reg_word(asd_ha, CSEQ_Q_MONIRTT_TAIL, 0xFFFF); /* Calculate the free scb mask. */ { u16 cmdctx = asd_get_cmdctx_size(asd_ha); cmdctx = (~((cmdctx/128)-1)) >> 8; asd_write_reg_byte(asd_ha, CSEQ_FREE_SCB_MASK, (u8)cmdctx); } asd_write_reg_word(asd_ha, CSEQ_BUILTIN_FREE_SCB_HEAD, first_scb_site_no); asd_write_reg_word(asd_ha, CSEQ_BUILTIN_FREE_SCB_TAIL, last_scb_site_no); asd_write_reg_word(asd_ha, CSEQ_EXTENDED_FREE_SCB_HEAD, 0xFFFF); asd_write_reg_word(asd_ha, CSEQ_EXTENDED_FREE_SCB_TAIL, 0xFFFF); /* CSEQ Mode independent, page 7 setup. */ asd_write_reg_dword(asd_ha, CSEQ_EMPTY_REQ_QUEUE, 0); asd_write_reg_dword(asd_ha, CSEQ_EMPTY_REQ_QUEUE+4, 0); asd_write_reg_dword(asd_ha, CSEQ_EMPTY_REQ_COUNT, 0); asd_write_reg_dword(asd_ha, CSEQ_EMPTY_REQ_COUNT+4, 0); asd_write_reg_word(asd_ha, CSEQ_Q_EMPTY_HEAD, 0xFFFF); asd_write_reg_word(asd_ha, CSEQ_Q_EMPTY_TAIL, 0xFFFF); asd_write_reg_word(asd_ha, CSEQ_NEED_EMPTY_SCB, 0); asd_write_reg_byte(asd_ha, CSEQ_EMPTY_REQ_HEAD, 0); asd_write_reg_byte(asd_ha, CSEQ_EMPTY_REQ_TAIL, 0); asd_write_reg_byte(asd_ha, CSEQ_EMPTY_SCB_OFFSET, 0); asd_write_reg_word(asd_ha, CSEQ_PRIMITIVE_DATA, 0); asd_write_reg_dword(asd_ha, CSEQ_TIMEOUT_CONST, 0);}/** * asd_init_cseq_mdp - initialize CSEQ Mode dependent pages * @asd_ha: pointer to host adapter structure */static void asd_init_cseq_mdp(struct asd_ha_struct *asd_ha){ int i; int moffs; moffs = CSEQ_PAGE_SIZE * 2; /* CSEQ Mode dependent, modes 0-7, page 0 setup. */ for (i = 0; i < 8; i++) { asd_write_reg_word(asd_ha, i*moffs+CSEQ_LRM_SAVE_SINDEX, 0); asd_write_reg_word(asd_ha, i*moffs+CSEQ_LRM_SAVE_SCBPTR, 0); asd_write_reg_word(asd_ha, i*moffs+CSEQ_Q_LINK_HEAD, 0xFFFF); asd_write_reg_word(asd_ha, i*moffs+CSEQ_Q_LINK_TAIL, 0xFFFF); asd_write_reg_byte(asd_ha, i*moffs+CSEQ_LRM_SAVE_SCRPAGE, 0); } /* CSEQ Mode dependent, mode 0-7, page 1 and 2 shall be ignored. */ /* CSEQ Mode dependent, mode 8, page 0 setup. */ asd_write_reg_word(asd_ha, CSEQ_RET_ADDR, 0xFFFF); asd_write_reg_word(asd_ha, CSEQ_RET_SCBPTR, 0); asd_write_reg_word(asd_ha, CSEQ_SAVE_SCBPTR, 0); asd_write_reg_word(asd_ha, CSEQ_EMPTY_TRANS_CTX, 0); asd_write_reg_word(asd_ha, CSEQ_RESP_LEN, 0); asd_write_reg_word(asd_ha, CSEQ_TMF_SCBPTR, 0); asd_write_reg_word(asd_ha, CSEQ_GLOBAL_PREV_SCB, 0); asd_write_reg_word(asd_ha, CSEQ_GLOBAL_HEAD, 0); asd_write_reg_word(asd_ha, CSEQ_CLEAR_LU_HEAD, 0); asd_write_reg_byte(asd_ha, CSEQ_TMF_OPCODE, 0); asd_write_reg_byte(asd_ha, CSEQ_SCRATCH_FLAGS, 0); asd_write_reg_word(asd_ha, CSEQ_HSB_SITE, 0); asd_write_reg_word(asd_ha, CSEQ_FIRST_INV_SCB_SITE, (u16)last_scb_site_no+1); asd_write_reg_word(asd_ha, CSEQ_FIRST_INV_DDB_SITE, (u16)asd_ha->hw_prof.max_ddbs); /* CSEQ Mode dependent, mode 8, page 1 setup. */ asd_write_reg_dword(asd_ha, CSEQ_LUN_TO_CLEAR, 0); asd_write_reg_dword(asd_ha, CSEQ_LUN_TO_CLEAR + 4, 0); asd_write_reg_dword(asd_ha, CSEQ_LUN_TO_CHECK, 0); asd_write_reg_dword(asd_ha, CSEQ_LUN_TO_CHECK + 4, 0); /* CSEQ Mode dependent, mode 8, page 2 setup. */ /* Tell the sequencer the bus address of the first SCB. */ asd_write_reg_addr(asd_ha, CSEQ_HQ_NEW_POINTER, asd_ha->seq.next_scb.dma_handle); ASD_DPRINTK("First SCB dma_handle: 0x%llx\n", (unsigned long long)asd_ha->seq.next_scb.dma_handle); /* Tell the sequencer the first Done List entry address. */ asd_write_reg_addr(asd_ha, CSEQ_HQ_DONE_BASE, asd_ha->seq.actual_dl->dma_handle); /* Initialize the Q_DONE_POINTER with the least significant * 4 bytes of the first Done List address. */ asd_write_reg_dword(asd_ha, CSEQ_HQ_DONE_POINTER, ASD_BUSADDR_LO(asd_ha->seq.actual_dl->dma_handle)); asd_write_reg_byte(asd_ha, CSEQ_HQ_DONE_PASS, ASD_DEF_DL_TOGGLE); /* CSEQ Mode dependent, mode 8, page 3 shall be ignored. */}/** * asd_init_cseq_scratch -- setup and init CSEQ * @asd_ha: pointer to host adapter structure * * Setup and initialize Central sequencers. Initialiaze the mode * independent and dependent scratch page to the default settings. */static void asd_init_cseq_scratch(struct asd_ha_struct *asd_ha){ asd_init_cseq_mip(asd_ha); asd_init_cseq_mdp(asd_ha);}/** * asd_init_lseq_mip -- initialize LSEQ Mode independent pages 0-3 * @asd_ha: pointer to host adapter structure */static void asd_init_lseq_mip(struct asd_ha_struct *asd_ha, u8 lseq){ int i; /* LSEQ Mode independent page 0 setup. */ asd_write_reg_word(asd_ha, LmSEQ_Q_TGTXFR_HEAD(lseq), 0xFFFF); asd_write_reg_word(asd_ha, LmSEQ_Q_TGTXFR_TAIL(lseq), 0xFFFF); asd_write_reg_byte(asd_ha, LmSEQ_LINK_NUMBER(lseq), lseq); asd_write_reg_byte(asd_ha, LmSEQ_SCRATCH_FLAGS(lseq), ASD_NOTIFY_ENABLE_SPINUP); asd_write_reg_dword(asd_ha, LmSEQ_CONNECTION_STATE(lseq),0x08000000); asd_write_reg_word(asd_ha, LmSEQ_CONCTL(lseq), 0); asd_write_reg_byte(asd_ha, LmSEQ_CONSTAT(lseq), 0); asd_write_reg_byte(asd_ha, LmSEQ_CONNECTION_MODES(lseq), 0); asd_write_reg_word(asd_ha, LmSEQ_REG1_ISR(lseq), 0); asd_write_reg_word(asd_ha, LmSEQ_REG2_ISR(lseq), 0); asd_write_reg_word(asd_ha, LmSEQ_REG3_ISR(lseq), 0); asd_write_reg_dword(asd_ha, LmSEQ_REG0_ISR(lseq), 0); asd_write_reg_dword(asd_ha, LmSEQ_REG0_ISR(lseq)+4, 0); /* LSEQ Mode independent page 1 setup. */ asd_write_reg_word(asd_ha, LmSEQ_EST_NEXUS_SCBPTR0(lseq), 0xFFFF); asd_write_reg_word(asd_ha, LmSEQ_EST_NEXUS_SCBPTR1(lseq), 0xFFFF); asd_write_reg_word(asd_ha, LmSEQ_EST_NEXUS_SCBPTR2(lseq), 0xFFFF); asd_write_reg_word(asd_ha, LmSEQ_EST_NEXUS_SCBPTR3(lseq), 0xFFFF); asd_write_reg_byte(asd_ha, LmSEQ_EST_NEXUS_SCB_OPCODE0(lseq), 0); asd_write_reg_byte(asd_ha, LmSEQ_EST_NEXUS_SCB_OPCODE1(lseq), 0); asd_write_reg_byte(asd_ha, LmSEQ_EST_NEXUS_SCB_OPCODE2(lseq), 0); asd_write_reg_byte(asd_ha, LmSEQ_EST_NEXUS_SCB_OPCODE3(lseq), 0); asd_write_reg_byte(asd_ha, LmSEQ_EST_NEXUS_SCB_HEAD(lseq), 0); asd_write_reg_byte(asd_ha, LmSEQ_EST_NEXUS_SCB_TAIL(lseq), 0); asd_write_reg_byte(asd_ha, LmSEQ_EST_NEXUS_BUF_AVAIL(lseq), 0); asd_write_reg_dword(asd_ha, LmSEQ_TIMEOUT_CONST(lseq), 0); asd_write_reg_word(asd_ha, LmSEQ_ISR_SAVE_SINDEX(lseq), 0); asd_write_reg_word(asd_ha, LmSEQ_ISR_SAVE_DINDEX(lseq), 0); /* LSEQ Mode Independent page 2 setup. */ asd_write_reg_word(asd_ha, LmSEQ_EMPTY_SCB_PTR0(lseq), 0xFFFF); asd_write_reg_word(asd_ha, LmSEQ_EMPTY_SCB_PTR1(lseq), 0xFFFF); asd_write_reg_word(asd_ha, LmSEQ_EMPTY_SCB_PTR2(lseq), 0xFFFF); asd_write_reg_word(asd_ha, LmSEQ_EMPTY_SCB_PTR3(lseq), 0xFFFF); asd_write_reg_byte(asd_ha, LmSEQ_EMPTY_SCB_OPCD0(lseq), 0); asd_write_reg_byte(asd_ha, LmSEQ_EMPTY_SCB_OPCD1(lseq), 0); asd_write_reg_byte(asd_ha, LmSEQ_EMPTY_SCB_OPCD2(lseq), 0); asd_write_reg_byte(asd_ha, LmSEQ_EMPTY_SCB_OPCD3(lseq), 0); asd_write_reg_byte(asd_ha, LmSEQ_EMPTY_SCB_HEAD(lseq), 0); asd_write_reg_byte(asd_ha, LmSEQ_EMPTY_SCB_TAIL(lseq), 0); asd_write_reg_byte(asd_ha, LmSEQ_EMPTY_BUFS_AVAIL(lseq), 0); for (i = 0; i < 12; i += 4) asd_write_reg_dword(asd_ha, LmSEQ_ATA_SCR_REGS(lseq) + i, 0); /* LSEQ Mode Independent page 3 setup. */ /* Device present timer timeout */ asd_write_reg_dword(asd_ha, LmSEQ_DEV_PRES_TMR_TOUT_CONST(lseq), ASD_DEV_PRESENT_TIMEOUT); /* SATA interlock timer disabled */ asd_write_reg_dword(asd_ha, LmSEQ_SATA_INTERLOCK_TIMEOUT(lseq), ASD_SATA_INTERLOCK_TIMEOUT); /* STP shutdown timer timeout constant, IGNORED by the sequencer, * always 0. */ asd_write_reg_dword(asd_ha, LmSEQ_STP_SHUTDOWN_TIMEOUT(lseq), ASD_STP_SHUTDOWN_TIMEOUT); asd_write_reg_dword(asd_ha, LmSEQ_SRST_ASSERT_TIMEOUT(lseq), ASD_SRST_ASSERT_TIMEOUT); asd_write_reg_dword(asd_ha, LmSEQ_RCV_FIS_TIMEOUT(lseq), ASD_RCV_FIS_TIMEOUT); asd_write_reg_dword(asd_ha, LmSEQ_ONE_MILLISEC_TIMEOUT(lseq), ASD_ONE_MILLISEC_TIMEOUT); /* COM_INIT timer */ asd_write_reg_dword(asd_ha, LmSEQ_TEN_MS_COMINIT_TIMEOUT(lseq), ASD_TEN_MILLISEC_TIMEOUT); asd_write_reg_dword(asd_ha, LmSEQ_SMP_RCV_TIMEOUT(lseq), ASD_SMP_RCV_TIMEOUT);}/** * asd_init_lseq_mdp -- initialize LSEQ mode dependent pages. * @asd_ha: pointer to host adapter structure */static void asd_init_lseq_mdp(struct asd_ha_struct *asd_ha, int lseq){ int i; u32 moffs; u16 ret_addr[] = { 0xFFFF, /* mode 0 */ 0xFFFF, /* mode 1 */ mode2_task, /* mode 2 */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -