Commit 4bf4f348 authored by Andrey Filippov's avatar Andrey Filippov

continue on sequencer code and related changes

parent 927f8201
......@@ -37,9 +37,6 @@ module ahci_fis_receive#(
// Control Interface
output reg fis_first_vld, // fis_first contains valid FIS header, reset by get_*
// Receiving FIS
input set_update_sig, // when set, enables get_sig (and resets itself)
output pUpdateSig, // state variable
input get_sig, // update signature
input get_dsfis,
input get_psfis,
input get_rfis,
......@@ -52,7 +49,11 @@ module ahci_fis_receive#(
output reg fis_ok, // FIS done, checksum OK reset by starting a new get FIS
output reg fis_err, // FIS done, checksum ERROR reset by starting a new get FIS
output fis_ferr, // FIS done, fatal error - FIS too long
input set_update_sig,// when set, enables update_sig (and resets itself)
output pUpdateSig, // state variable
output reg sig_available, // device signature a ailable
// next commands use register address/data/we for 1 clock cycle - after next to command (commnd - t0, we - t2)
input update_sig, // update signature - now after get_rfis, after FIS is already received
input update_err_sts,// update PxTFD.STS and PxTFD.ERR from the last received regs d2h
input update_pio, // update PxTFD.STS and PxTFD.ERR from pio_* (entry PIO:Update)
input update_prdbc, // update PRDBC in registers
......@@ -168,7 +169,7 @@ localparam DATA_TYPE_ERR = 3;
wire reg_we_w;
reg [3:0] update_sig;
reg [3:0] store_sig;
reg [5:0] reg_ds;
reg [4:0] reg_ps;
reg reg_d2h;
......@@ -179,6 +180,7 @@ localparam DATA_TYPE_ERR = 3;
reg [15:0] tf_err_sts;
reg update_err_sts_r;
reg update_sig_r;
// reg update_pio_r;
reg update_prdbc_r;
reg get_fis_busy_r;
......@@ -187,7 +189,8 @@ localparam DATA_TYPE_ERR = 3;
reg [7:0] pio_es_r; // value of PIO E_Status
reg [7:0] pio_err_r;
reg pUpdateSig_r = 1; // state variable
reg pUpdateSig_r = 1; // state variable
reg [31:0] sig_r; // signature register, save at
// Forward data to DMA (dev->mem) engine
assign dma_in_valid = dma_in_ready && (hba_data_in_type == DATA_TYPE_DMA) && data_in_ready && !too_long_err;
......@@ -226,27 +229,24 @@ localparam DATA_TYPE_ERR = 3;
(wreg_we_r && dwords_over)) too_long_err <= 1;
if (get_fis) begin
reg_addr_r <= ({ADDRESS_BITS{get_sig}} & (PXSIG_OFFS32)) |
({ADDRESS_BITS{get_dsfis}} & (FB_OFFS32 + DSFIS32)) |
reg_addr_r <= ({ADDRESS_BITS{get_dsfis}} & (FB_OFFS32 + DSFIS32)) |
({ADDRESS_BITS{get_psfis}} & (FB_OFFS32 + PSFIS32)) |
({ADDRESS_BITS{get_rfis}} & (FB_OFFS32 + RFIS32)) |
({ADDRESS_BITS{get_sdbfis}} & (FB_OFFS32 + SDBFIS32)) |
({ADDRESS_BITS{get_ufis}} & (FB_OFFS32 + UFIS32));
fis_dcount <= ({4{get_sig}} & RFIS32_LENM1) |
({4{get_dsfis}} & DSFIS32_LENM1) |
fis_dcount <= ({4{get_dsfis}} & DSFIS32_LENM1) |
({4{get_psfis}} & PSFIS32_LENM1) |
({4{get_rfis}} & RFIS32_LENM1) |
({4{get_sdbfis}} & SDBFIS32_LENM1) |
({4{get_ufis}} & UFIS32_LENM1 ) |
({4{get_data_fis}} & DMAH_LENM1) |
({4{get_ignore}} & IGNORE_LENM1 );
// fis_save <= pcmd_fre && !get_data_fis && !get_ignore && !get_sig;
// save signature FIS to memory if waiting (if not - ignore FIS)
// for non-signature /non-data - obey pcmd_fre
fis_save <= get_sig? pUpdateSig_r : (pcmd_fre && !get_data_fis && !get_ignore);
fis_save <= (pUpdateSig_r || get_rfis) || (pcmd_fre && !get_data_fis && !get_ignore);
is_data_fis <= get_data_fis;
update_sig <= ((get_sig && pUpdateSig_r)? 1 : 0);
store_sig <= (get_rfis)? 1 : 0;
reg_ds <= get_dsfis ? 1 : 0;
reg_ps <= get_psfis ? 1 : 0;
reg_d2h <= get_rfis ? 1 : 0;
......@@ -254,7 +254,7 @@ localparam DATA_TYPE_ERR = 3;
end else if (wreg_we_r && !dwords_over) begin
fis_dcount <= fis_dcount - 1; // update even if not writing to registers
if (fis_save) reg_addr_r <= reg_addr_r + 1; // update only when writing to registers
update_sig <= update_sig << 1;
store_sig <= store_sig << 1;
reg_ds <= reg_ds << 1;
reg_ps <= reg_ps << 1;
reg_d2h <= 0;
......@@ -289,19 +289,16 @@ localparam DATA_TYPE_ERR = 3;
if (hba_rst || get_fis) fis_err <= 0;
else if (fis_end_w) fis_err <= hba_data_in_type != DATA_TYPE_OK;
if (reg_we_w) reg_data[31:8] <= hba_data_in[31:8];
else if (update_sig[1]) reg_data[31:8] <= hba_data_in[23:0];
else if (update_err_sts_r) reg_data[31:8] <= {16'b0,tf_err_sts[15:8]};
// else if (update_pio_r) reg_data[31:8] <= {16'b0,pio_err_r[7:0]};
else if (update_prdbc_r) reg_data[31:8] <= {xfer_cntr_r[31:8]};
if (reg_we_w) reg_data[ 7:0] <= hba_data_in[ 7:0];
else if (update_sig[3]) reg_data[ 7:0] <= hba_data_in[ 7:0];
else if (update_err_sts_r) reg_data[ 7:0] <= tf_err_sts [ 7:0];
// else if (update_pio_r) reg_data[ 7:0] <= pio_es_r [ 7:0];
else if (update_prdbc_r) reg_data[ 7:0] <= {xfer_cntr_r[ 7:2],2'b0};
if (reg_we_w) reg_data <= hba_data_in;
else if (update_err_sts_r) reg_data <= {16'b0,tf_err_sts};
else if (update_sig_r) reg_data <= sig_r;
else if (update_prdbc_r) reg_data <= {xfer_cntr_r[31:2],2'b0};
if (store_sig[1]) sig_r[31:8] <= hba_data_in[23:0];
if (store_sig[3]) sig_r[ 7:0] <= hba_data_in[ 7:0];
if (reg_d2h || update_sig[0]) tf_err_sts <= hba_data_in[15:0];
if (reg_d2h) tf_err_sts <= hba_data_in[15:0];
// Sets pPioErr[pPmpCur] to Error field of the FIS
// Updates PxTFD.STS.ERR with pPioErr[pPmpCur] ??
else if (reg_ps[0]) tf_err_sts <= {hba_data_in[31:24],hba_data_in[23:16]};
......@@ -311,12 +308,13 @@ localparam DATA_TYPE_ERR = 3;
tf_err_sts <= tf_err_sts & {8'hff,clear_bsy_drq,3'h7,clear_bsy_drq,3'h7} | {8'h0,set_bsy,3'h0,clear_bsy_set_drq,3'h0};
else if (set_sts_7f || set_sts_80) tf_err_sts <= {tf_err_sts[15:8],set_sts_80,{7{set_sts_7f}}} ;
reg_we <= reg_we_w || update_sig[3] || update_err_sts_r || update_prdbc_r;
reg_we <= reg_we_w || update_sig_r || update_err_sts_r || update_prdbc_r;
if (reg_we_w || update_sig[3]) reg_addr <= reg_addr_r;
if (reg_we_w) reg_addr <= reg_addr_r;
else if (update_err_sts_r) reg_addr <= PXTFD_OFFS32;
else if (update_sig_r) reg_addr <= PXSIG_OFFS32;
else if (update_prdbc_r) reg_addr <= CLB_OFFS32 + 1; // location of PRDBC
if (reg_d2h || reg_sdb || reg_ds[0]) fis_i <= hba_data_in[14];
if (reg_sdb) sdb_n <= hba_data_in[15];
if (reg_ds[0]) {dma_a,dma_d} <= {hba_data_in[15],hba_data_in[13]};
......@@ -341,13 +339,16 @@ localparam DATA_TYPE_ERR = 3;
update_err_sts_r <= update_pio || update_err_sts || clear_bsy_drq || set_bsy || set_sts_7f || set_sts_80;
// update_pio_r <= update_pio;
update_prdbc_r <= update_prdbc; // same latency as update_err_sts
update_sig_r <= update_sig && pUpdateSig_r; // do not update if not requested
if (hba_rst || update_pio) pPioXfer <= 0;
else if (reg_ps[4]) pPioXfer <= 1;
if (hba_rst || update_pio) pPioXfer <= 0;
else if (reg_ps[4]) pPioXfer <= 1;
if (hba_rst || set_update_sig) pUpdateSig_r <= 1;
else if (update_sig[3]) pUpdateSig_r <= 0;
else if (update_sig) pUpdateSig_r <= 0;
if (hba_rst || update_sig) sig_available <= 0;
else if (store_sig[3]) sig_available <= 1;
// Maybe it is not needed if the fsm will send this pulse?
// data_in_words_apply <= dma_in_stop && (hba_data_in_type == DATA_TYPE_OK);
......
......@@ -35,7 +35,7 @@ module ahci_fis_transmit #(
input cfis_xmit, // transmit command (wait for dma_ct_busy == 0)
input dx_transmit, // send FIS header DWORD, (just 0x46), then forward DMA data
// transmit until error, 2048DWords or pDmaXferCnt
input atapi_xmit, // tarsmit ATAPI command FIS
input atapi_xmit, // trasmit ATAPI command FIS
output reg done,
......@@ -233,9 +233,12 @@ module ahci_fis_transmit #(
ch_r_r <= reg_rdata[ 8];
ch_p_r <= reg_rdata[ 7];
ch_w_r <= reg_rdata[ 6];
ch_a_r <= reg_rdata[ 5];
// ch_a_r <= reg_rdata[ 5];
ch_cmd_len_r<= reg_rdata[ 4: 0];
end
//ch_a
if (hba_rst || atapi_xmit) ch_a_r <= 0;
else if (fetch_chead_stb_r[0]) ch_a_r <= reg_rdata[ 5];
if (hba_rst) pCmdToIssue_r <= 0;
else if (chead_done_w) pCmdToIssue_r <= 1;
......
......@@ -44,8 +44,10 @@ module ahci_fsm
// direct communication with transposrt, link and phy layers
input phy_ready, // goes up after comreset,cominit, align, ...
output syncesc_send, // Send sync escape
input syncesc_send_done, // "SYNC escape until the interface is quiescent..."
input cominit_got, // asynchronously jumps to P:Cominit state
output set_offline, // electrically idle
input x_rdy_collision, // X_RDY/X_RDY collision on interface
output send_R_OK, // Should it be originated in this layer SM?
output send_R_ERR,
......@@ -153,11 +155,9 @@ module ahci_fsm
// Communication with ahci_fis_receive (some are unused
input fis_first_vld, // fis_first contains valid FIS header, reset by 'get_*'
input [7:0] fis_type, // FIS type (low byte in the first FIS DWORD), valid with 'fis_first_vld'
// Receiving FIS
output set_update_sig, // when set, enables get_sig (and resets itself)
input pUpdateSig, // state variable
input [7:0] bist_bits, // bits that define built-in self test
output get_sig, // update signature
// Receiving FIS
output get_dsfis,
output get_psfis,
output get_rfis,
......@@ -170,6 +170,13 @@ module ahci_fsm
input fis_ok, // FIS done, checksum OK reset by starting a new get FIS
input fis_err, // FIS done, checksum ERROR reset by starting a new get FIS
input fis_ferr, // FIS done, fatal error - FIS too long
output set_update_sig, // when set, enables get_sig (and resets itself)
input pUpdateSig, // state variable
input sig_available, // device signature available
output update_sig, // update signature
// next commands use register address/data/we for 1 clock cycle - after next to command (commnd - t0, we - t2)
output update_err_sts,// update PxTFD.STS and PxTFD.ERR from the last received regs d2h
output update_pio, // update PxTFD.STS and PxTFD.ERR from pio_* (entry PIO:Update)
......@@ -260,7 +267,7 @@ module ahci_fsm
reg async_from_st; // chnge to multi-bit if there will be more sources for async transitions
wire asynq_rq = cominit_got || pcmd_st_cleared;
wire async_ackn = !fsm_preload && async_pend_r[0] && ((fsm_actions && !update_busy && !fsm_act_busy) || fsm_transitions[0]); // OK to process async jump
reg x_rdy_collision_pend;
assign fsm_next = (fsm_preload || (fsm_actions && !update_busy && !fsm_act_busy) || fsm_transitions[0]) && !async_pend_r[0]; // quiet if received cominit is pending
......@@ -316,6 +323,11 @@ module ahci_fsm
if (hba_rst) async_pend_r <= 0;
else async_pend_r <= {async_pend_r[0], asynq_rq | (async_pend_r[0] & ~async_ackn)};
if (hba_rst || pcmd_cr_set) x_rdy_collision_pend <= 0;
else if (x_rdy_collision) x_rdy_collision_pend <= 1;
end
/*
......
......@@ -146,8 +146,10 @@ module ahci_top#(
input syncesc_recv, // These two inputs interrupt transmit
input xmit_err, // Error during sending of a FIS
output syncesc_send, // Send sync escape
input syncesc_send_done, // "SYNC escape until the interface is quiescent..."
input cominit_got,
output set_offline, // electrically idle
input x_rdy_collision, // X_RDY/X_RDY collision on interface
output send_R_OK, // Should it be originated in this layer SM?
output send_R_ERR,
......@@ -222,10 +224,6 @@ module ahci_top#(
// fsm <-> ahc_fis_receive
// fsm ->
wire frcv_first_vld;
wire frcv_set_update_sig; // when set, enables get_sig (and resets itself)
wire frcv_pUpdateSig; // state variable
wire frcv_get_sig; // update signature
wire frcv_get_dsfis;
wire frcv_get_psfis;
wire frcv_get_rfis;
......@@ -254,6 +252,12 @@ module ahci_top#(
wire frcv_ok; // FIS done, checksum OK reset by starting a new get FIS
wire frcv_err; // FIS done, checksum ERROR reset by starting a new get FIS
wire frcv_ferr; // FIS done, fatal error - FIS too long
wire frcv_set_update_sig; // when set, enables get_sig (and resets itself)
wire frcv_pUpdateSig; // state variable
wire frcv_sig_available; // signature data available
wire frcv_update_sig; // update signature
// fsm <- state variables that are maintained inside 'ahc_fis_receive'
wire [7:0] tfd_sts; // Current PxTFD status field (updated after regFIS and SDB - certain fields)
......@@ -419,11 +423,14 @@ module ahci_top#(
.phy_ready (phy_ready), // input
.syncesc_send (syncesc_send), // output
.syncesc_send_done (syncesc_send_done), // input
.cominit_got (cominit_got), // input
.set_offline (set_offline), // output
.x_rdy_collision (x_rdy_collision), // input
.send_R_OK (send_R_OK), // output
.send_R_ERR (send_R_ERR), // output
.update_pending (update_regs_pending),// input
.update_all (update_all_regs), // output
.update_busy (update_regs_busy), // input
......@@ -502,9 +509,8 @@ module ahci_top#(
.fis_first_vld (frcv_first_vld), // input
.fis_type (d2h_data[7:0]), // input[7:0] FIS type (low byte in the first FIS DWORD), valid with 'fis_first_vld'
.set_update_sig (frcv_set_update_sig),// output
.pUpdateSig (frcv_pUpdateSig), // input
.get_sig (frcv_get_sig), // output
.bist_bits (d2h_data[23:16]), // bits that define built-in self test
.get_dsfis (frcv_get_dsfis), // output
.get_psfis (frcv_get_psfis), // output
.get_rfis (frcv_get_rfis), // output
......@@ -517,6 +523,12 @@ module ahci_top#(
.fis_ok (frcv_ok), // input
.fis_err (frcv_err), // input
.fis_ferr (frcv_ferr), // input
.set_update_sig (frcv_set_update_sig),// output
.pUpdateSig (frcv_pUpdateSig), // input
.sig_available (frcv_sig_available), // input
.update_sig (frcv_update_sig), // output
.update_err_sts (frcv_update_err_sts),// output
.update_pio (frcv_update_pio), // output
.update_prdbc (frcv_update_prdbc), // output
......@@ -797,10 +809,7 @@ module ahci_top#(
.mclk (mclk), // input
.fis_first_vld (frcv_first_vld), // output reg
.set_update_sig (frcv_set_update_sig), // input
.pUpdateSig (frcv_pUpdateSig), // output
.get_sig (frcv_get_sig), // input
.get_dsfis (frcv_get_dsfis), // input
.get_psfis (frcv_get_psfis), // input
.get_rfis (frcv_get_rfis), // input
......@@ -814,6 +823,11 @@ module ahci_top#(
.fis_ok (frcv_ok), // output reg
.fis_err (frcv_err), // output reg
.fis_ferr (frcv_ferr), // output
.set_update_sig (frcv_set_update_sig), // input
.pUpdateSig (frcv_pUpdateSig), // output
.sig_available (frcv_sig_available), // output reg
.update_sig (frcv_update_sig), // input
.update_err_sts (frcv_update_err_sts), // input
.update_pio (frcv_update_pio), // input update PxTFD.STS and PxTFD.ERR from pio_* (entry PIO:Update)
......
......@@ -57,9 +57,9 @@ sequence = [{LBL:'POR', ADR: 0x0, ACT: NOP},
{LBL:'P:Init', ACT: 'PFSM'}, # pfsm_started HBA init done, port FSM started
{ ACT: 'PSCI0'}, # pxci0_clear, reset both (pIssueSlot:=32) and PxCI[0]
{ ACT: 'CLEAR_BSY_SET_DRQ'}, # frcv_clear_bsy_set_drq
{ ACT: 'SET_STS_7F'}, # frcv_set_sts_7f
{ ACT: 'SET_UPDATE_SIG'}, # #frcv_set_update_sig
{ ACT: 'CLEAR_BSY_SET_DRQ'}, # clear_bsy_set_drq
{ ACT: 'SET_STS_7F'}, # set_sts_7f
{ ACT: 'SET_UPDATE_SIG'}, # set_update_sig
{ ACT: 'XMIT_COMRESET'}, # Now does it on reset. See if it is possible to transmit COMRESET w/o reset
{ GOTO:'P:NotRunning'},
......@@ -80,9 +80,9 @@ sequence = [{LBL:'POR', ADR: 0x0, ACT: NOP},
# {IF:'PXIE_PCE', GOTO:'P:CominitSetIS'}, # Not needed, interrupt
{ GOTO:'P:NotRunning'},
{LBL:'P:RegFisUpdate', ACT: 'NOP'}, #
{ ACT: 'GET_SIG'}, # get_sig
# {IF: 'pcmd_fre', GOTO:'P:RegFisPostToMem'}, # pcmd_fre hardware always copies signature FIS to 'memory' if expected
{LBL:'P:RegFisUpdate', ACT: 'GET_RFIS'}, #get_rfis
{ ACT: 'UPDATE_SIG'}, # update_sig
# {IF: 'PCMD_FRE', GOTO:'P:RegFisPostToMem'}, # pcmd_fre hardware always copies signature FIS to 'memory' if expected
{ GOTO:'P:NotRunning'},
{LBL:'P:RegFisPostToMem', ACT: 'NOP'}, # Probably not needed, handled at lower level
......@@ -105,10 +105,12 @@ sequence = [{LBL:'POR', ADR: 0x0, ACT: NOP},
{IF: 'PCTI_XCZ', GOTO:'CFIS:Xmit'}, # 6. pCmdToIssue && xfer_cntr_zero
{ GOTO:'P:Idle'}, #10. (#7-#9 PM, not implemented)
#P:SelectCmd not implemented, using single slot
{LBL:'P:FetchCmd', ACT:'FETCH_CMD'}, # fetch_cmd (other actions included in ahci_fis_transmit)
{IF: 'CTBAA_CTBAP', ACT:'CFIS:PrefetchACMD'},#1. ch_a && ch_p # Note ch_p may be ignored or transition may be ignored
{IF: 'CTBAP', ACT:'CFIS:PrefetchPRD'}, #2. ch_p # Note ch_p may be ignored or transition may be ignored
# PxTFD.STS.BSY must be set before issuing a command (or now if predicted)
{LBL:'P:FetchCmd', ACT: 'FETCH_CMD'}, # fetch_cmd (other actions included in ahci_fis_transmit)
#ahci_fis_transmit already processes ch_p. ATAPI data is always preloaded, prd - if ch_p
{IF: 'CTBAA_CTBAP', GOTO:'CFIS:PrefetchACMD'},#1. ch_a && ch_p # Note ch_p may be ignored or transition may be ignored
{IF: 'CTBAP', GOTO:'CFIS:PrefetchPRD'}, #2. ch_p # Note ch_p may be ignored or transition may be ignored
{ GOTO:'P:Idle'}, #3. PxTFD.STS.BSY must be set before issuing a command (or now if predicted)
{LBL:'P:StartComm', ACT: 'SET_STS_7F'}, # frcv_set_sts_7f
{ ACT: 'SET_UPDATE_SIG'}, # #frcv_set_update_sig
{ ACT: 'XMIT_COMRESET'}, # Now does it on reset. See if it is possible to transmit COMRESET w/o reset
......@@ -117,14 +119,145 @@ sequence = [{LBL:'POR', ADR: 0x0, ACT: NOP},
#P:PowerOn, P;PwerOff,P:PhyListening - not implemented
#FB:* - Not implemented
#PM:* - Not implemented
{LBL:'PM:Aggr', ACT: 'NOP'}, # Just as a placeholder
{ GOTO:'P:Idle'}, #1
{LBL:'NDR:Entry', ACT: 'NOP'},
{IF: 'FIS_ERR', GOTO:'ERR:Non-fatal'}, # 1. fis_ok
{IF: 'FIS_ERR', GOTO:'ERR:Non-fatal'}, # 1. fis_err
{IF: 'FIS_FERR', GOTO:'ERR:Fatal'}, # 2. fis_ferr
{ GOTO:'NDR:Accept'}, # 3.
{ GOTO:'NDR:Accept'}, # 4.
{LBL:'NDR:IgnoreNR', ACT: 'FIS_IOGNORE'}, # get_ignore This one is not in docs, just to empty FIS FIFO
{ GOTO:'P:NotRunning'}, # (was directly from NDR:Accept.4
{LBL:'NDR:IgnoreIdle', ACT: 'FIS_IOGNORE'}, # get_ignore This one is not in docs, just to empty FIS FIFO
{ GOTO:'P:Idle'}, # (was directly from NDR:Accept.4
{LBL:'NDR:Accept', ACT: 'R_OK'}, # send_R_OK to device
{IF:'NB_ND_D2HR_PIO', GOTO:'NDR:IgnoreIdle'}, # 2 :((FIS == FIS_D2HR) || (FIS == FIS_PIO)) && !PxTBD.STS.BSY & !PxTBD.STS.DRQ
{IF:'NST_D2HR', GOTO:'P:RegFisUpdate'}, # 3 :!ST && (FIS == FIS_D2HR) TODO: does it mean either BSY or DRQ are 1?
{IF:'NPCMD_FRE', GOTO:'NDR:IgnoreNR' }, # 4 !pcmd_fre (docs: goto P:NotRunning, but we need to clear FIFO)
{IF:'D2HR', GOTO:'RegFIS:Entry' }, # 5 FIS == FIS_D2HR
{IF:'SDB', GOTO:'SDB:Entry' }, # 7 (# 6 skipped)
{IF:'DMA_ACT', GOTO:'DX:Entry' }, # 8 FIS == FIS_DMA_ACT
{IF:'DMA_SETUP', GOTO:'DmaSet:Entry' }, # 9 FIS == FIS_DMA_SETUP
{IF:'BIST_ACT_FE', GOTO:'BIST:FarEndLoopback'},#10 FIS == FIS_BIST_ACT && |bist_bits TODO:get_ignore to read in FIS
{IF:'BIST_ACT', GOTO:'BIST:TestOngoing'},# 11 FIS == FIS_BIST_ACT && |bist_bits TODO:get_ignore to read in FIS
{IF:'PIO_SETUP', GOTO:'PIO:Entry' }, # 12 FIS == FIS_PIO_SETUP
{ GOTO:'UFIS:Entry' }, # 13 Unknown FIS (else)
#5.3.6. Command Transfer State
{LBL:'CFIS:SyncEscape', ACT: 'SEND_SYNC_ESC'}, # syncesc_send, should wait (for syncesc_send_done)
{ ACT: 'SET_UPDATE_SIG'}, # set_update_sig
{ GOTO:'CFIS:Xmit' }, # 1
{LBL:'CFIS:Xmit', ACT: 'SET_BSY'}, # set_bsy
{ ACT: 'CFIS_XMIT'}, # cfis_xmit
{IF: 'X_RDY_COLLISION', GOTO:'P:Idle'}, # 2. x_rdy_collision_pend
{IF: 'SYNCESC_RECV', GOTO:'ERR:SyncEscapeRecv'}, # 4. syncesc_recv
{IF: 'FIS_OK', GOTO:'CFIS:SUCCESS'}, # 5. fis_ok
{ GOTO:'ERR:Non-fatal'}, # 6
{LBL:'CFIS:Success', ACT: 'CLEAR_CMD_TO_ISSUE'}, # clearCmdToIssue
{IF: 'CTBA_B', GOTO:'BIST:TestOngoing'}, # 1. ch_b
{IF: 'CTBA_C', GOTO:'CFIS:ClearCI'}, # 2. ch_c
{IF: 'CTBAA_CTBAP', GOTO:'CFIS:PrefetchACMD'},# 3. ch_a && ch_p # Note ch_p may be ignored or transition may be ignored
{IF: 'CTBAP', GOTO:'CFIS:PrefetchPRD'}, # 4. ch_p # Note ch_p may be ignored or transition may be ignored
{ GOTO:'P:Idle'}, # 6.
{LBL:'CFIS:CLearCI', ACT: 'PSCI0'}, # pxci0_clear, reset both (pIssueSlot:=32) and PxCI[0]
{ ACT: 'CLEAR_BSY_DRQ'}, # clear_bsy_drq
{ GOTO:'PM:Aggr' }, # 1
# As ahci_fis_transmit processes ch_p, GOTO:'CFIS:Prefetch*' can be shortcut to GOTO:'P:Idle'
{LBL:'CFIS:PrefetchACMD', ACT: 'NOP'}, # Nothing to do as it is already in memory, fetched together with command
{IF: 'CTBAP', GOTO:'CFIS:PrefetchPRD'}, # 1. ch_p Note ch_p may be ignored or transition may be ignored
{ GOTO:'P:Idle'}, # 3.
{LBL:'CFIS:PrefetchPRD', ACT: 'NOP'}, # ahci_fis_transmit processes ch_p, no more actions needed
{ GOTO:'P:Idle'}, # 1.
{LBL:'CFIS:PrefetchData', ACT: 'NOP'}, # ahci_fis_transmit-> ahci_dma prefetches data if possible
{ GOTO:'P:Idle'}, # 1.
#5.3.7 ATAPI Command Transfer States
{LBL:'ATAPI:Entry', ACT: 'ATAPI_XMIT'}, # atapi_xmit, '0->pXferAtapi[pPmpCur]' is done ahci_fis_transmit.
{IF: 'TX_ERR', GOTO:'ERR:Fatal'}, # 1. dx_err[1] (reset by new command)
{ GOTO:'PIO:Update'}, # 2.
#5.3.8 D2H Register FIS Receive States
{LBL:'RegFIS:Entry', ACT: 'GET_RFIS'}, # get_rfis
{IF: 'TFD_STS_ERR', GOTO:'ERR:FatalTaskfile'},# 1. tfd_sts[0]
{IF: 'NB_ND', GOTO:'RegFIS:ClearCI'}, # 2. PxTFD.STS.BSY =’0’ and PxTFD.STS.DRQ =’0’
{ GOTO:'RegFIS:UpdateSig'}, # 3.
{LBL:'RegFIS:ClearCI', ACT: 'UPDATE_PRDBC'}, # update_prdbc
{ ACT: 'PSCI0'}, # pxci0_clear, reset both (pIssueSlot:=32) and PxCI[0]
{IF: 'FIS_I', GOTO:'RegFIS:SetIntr'}, # 2. fis_i
{ GOTO:'RegFIS:UpdateSig'}, # 3.
{LBL:'RegFIS:SetIntr', ACT: 'SIRQ_DHR'}, # sirq_DHR
{ GOTO:'RegFIS:UpdateSig'}, # 2. (PxIE/IRQ is handled)
#RegFIS:SetIS, RegFIS:GenIntr are handled by hardware, skipping
{LBL:'RegFIS:UpdateSig', ACT: 'UPDATE_SIG'}, # update_sig will only update if pUpdateSig
{ GOTO:'PM:Aggr' }, # 1
#RegFIS:SetSig skipped, done in RegFIS:UpdateSig
#5.3.9 PIO Setup Receive States
{LBL:'PIO:Entry', ACT: 'GET_PSFIS'}, # get_psfis, includes all steps 1..9
{IF: 'TFD_STS_ERR', GOTO:'ERR:FatalTaskfile'},# 1. tfd_sts[0]
{IF: 'NPD_NCA', GOTO:'DX:Entry'}, # 2. pio_d = 0 && ch_a == 0
{IF: 'NPD', GOTO:'ATAPI:Entry'}, # 3. pio_d = 0 , "ch_a == 1" is not needed
{ GOTO:'P:Idle' }, # 4
]
"""
output reg pio_i, // value of "I" field in received PIO Setup FIS
output reg pio_d, // value of "D" field in received PIO Setup FIS
output [7:0] pio_es, // value of PIO E_Status
sirq_DHR
fis_i
update_prdbc, // update PRDBC in registers
output [7:0] tfd_sts, // Current PxTFD status field (updated after regFIS and SDB - certain fields)
// tfd_sts[7] - BSY, tfd_sts[4] - DRQ, tfd_sts[0] - ERR
{LBL:'P:RegFisUpdate', ACT: 'GET_SIG'}, # update_sig
input [ 1:0] dx_err, // bit 0 - syncesc_recv, 1 - xmit_err (valid @ xmit_err and later, reset by new command)
{IF: 'CTBAA_CTBAP', ACT:'CFIS:PrefetchACMD'},#1. ch_a && ch_p # Note ch_p may be ignored or transition may be ignored
{IF: 'CTBAP', ACT:'CFIS:PrefetchPRD'}, #2. ch_p # Note ch_p may be ignored or transition may be ignored
input ch_c, // Clear busy upon R_OK for this FIS
input ch_b, // Built-in self test command
input ch_r, // reset - may need to send SYNC escape before this command
input ch_p, // prefetchable - only used with non-zero PRDTL or ATAPI bit set
input ch_w, // Write: system memory -> device
input ch_a, // ATAPI: 1 means device should send PIO setup FIS for ATAPI command
input [4:0] ch_cfl, // length of the command FIS in DW, 0 means none. 0 and 1 - illegal,
fis_ok
syncesc_recv
x_rdy_collision_pend
input cfis_xmit, // transmit command (wait for dma_ct_busy == 0)
input syncesc_send_done, // "SYNC escape until the interface is quiescent..."
set_update_sig
bist_bits (use get_ignore to read in BIST FIS)
get_ignore
output send_R_OK, // Should it be originated in this layer SM?
output send_R_ERR,
input fis_ok, // FIS done, checksum OK reset by starting a new get FIS
input fis_err, // FIS done, checksum ERROR reset by starting a new get FIS
input fis_ferr, // FIS done, fatal error - FIS too long
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment