Commit 09386747 authored by Andrey Filippov's avatar Andrey Filippov

connecting AHCI to link/phy layers

parent 0f0cf866
......@@ -33,21 +33,25 @@ module ahci_fis_transmit #(
input fetch_cmd, // Enter p:FetchCmd, fetch command header (from the register memory, prefetch command FIS)
// wait for either fetch_cmd_busy == 0 or pCmdToIssue ==1 after fetch_cmd
input cfis_xmit, // transmit command (wait for dma_ct_busy == 0)
input dx_transmit, // send FIS header DWORD, (just 0x46), then forward DMA data
input dx_xmit, // send FIS header DWORD, (just 0x46), then forward DMA data
// transmit until error, 2048DWords or pDmaXferCnt
input atapi_xmit, // trasmit ATAPI command FIS
output reg done,
output reg done, // for fetch_cmd - dma_start, for *_xmit - xmit_ok, xmit_err, syncesc_recv or xrdy_collision
output reg busy,
input clearCmdToIssue, // From CFIS:SUCCESS
output pCmdToIssue, // AHCI port variable
// output dmaCntrZero, // DMA counter is zero - would be a duplicate to the one in receive module and dwords_sent output
// output reg fetch_cmd_busy, // does not include prefetching CT - now just use busy/done
input syncesc_recv, // These two inputs interrupt transmit
// Should wait for xmit_ok? Timeout? Timeout will be handled by software, so just wait for OK or some error
input xmit_ok, // FIS transmission acknowledged OK
input xmit_err, //
output [ 1:0] dx_err, // bit 0 - syncesc_recv, 1 - xmit_err (valid @ xmit_err and later, reset by new command)
input syncesc_recv, // These two inputs interrupt transmit
input xrdy_collision,
output [ 2:0] dx_err, // bit 0 - syncesc_recv, 1 - xmit_err, 2 - collision (valid @ xmit_err and later, reset by new command)
output [15:0] ch_prdtl, // Physical region descriptor table length (in entries, 0 is 0)
output ch_c, // Clear busy upon R_OK for this FIS
......@@ -89,7 +93,7 @@ module ahci_fis_transmit #(
// Data System memory or FIS -> device
output reg [31:0] todev_data, // 32-bit data from the system memory to HBA (dma data)
output reg [ 1:0] todev_type, // 0 - data, 1 - FIS head, 2 - FIS END (make FIS_Last?)
output reg [ 1:0] todev_type, // 0 - data, 1 - FIS head, 2 - FIS LAST)
output todev_valid, // output register full
input todev_ready // send FIFO has room for data (>= 8? dwords)
......@@ -152,13 +156,16 @@ module ahci_fis_transmit #(
reg dx_fis_pend_r; // waiting to send first DWORD of the H2D data transfer
wire dx_dma_last_w; // sending last adat word
reg dx_busy_r;
reg [ 1:0] dx_err_r;
wire any_cmd_start = fetch_cmd || cfis_xmit || dx_transmit || atapi_xmit;
wire done_w = dx_dma_last_w || ((|dx_err_r) && dx_busy_r) || chead_done_w || acfis_xmit_end || dma_start; // done on last transmit or error
reg [ 2:0] dx_err_r;
reg xmit_ok_r;
wire any_cmd_start = fetch_cmd || cfis_xmit || dx_xmit || atapi_xmit;
// wire done_w = dx_dma_last_w || ((|dx_err_r) && dx_busy_r) || chead_done_w || acfis_xmit_end || dma_start; // done on last transmit or error
// dma_start ends 'fetch_cmd'
wire done_w = xmit_ok_r || ((|dx_err_r) && dx_busy_r) || dma_start; // done on last transmit or error
reg fetch_cmd_busy_r;
assign todev_valid = todev_full_r;
assign dma_re = dma_re_w;
assign reg_re = reg_re_r[1:0];
......@@ -283,15 +290,15 @@ module ahci_fis_transmit #(
//TODO: update xfer length, prdtl (only after R_OK) - yes, do it outside
if (dx_transmit) dx_dwords_left[11:2] <= (|xfer_cntr[31:11])?10'h200:{1'b0,xfer_cntr[10:2]};
if (dx_xmit) dx_dwords_left[11:2] <= (|xfer_cntr[31:11])?10'h200:{1'b0,xfer_cntr[10:2]};
else if (dma_re_w) dx_dwords_left[11:2] <= dx_dwords_left[11:2] - 1;
if (dx_transmit) dwords_sent <= 0;
if (dx_xmit) dwords_sent <= 0;
else if (dma_re_w) dwords_sent <= dwords_sent + 1;
// send FIS header
if (hba_rst || write_or_w) dx_fis_pend_r <= 0;
else if (dx_transmit) dx_fis_pend_r <= 1;
else if (dx_xmit) dx_fis_pend_r <= 1;
if (hba_rst || dx_dma_last_w || (|dx_err_r)) dma_en_r <= 0;
else if (dx_fis_pend_r && write_or_w) dma_en_r <= 1;
......@@ -303,9 +310,14 @@ module ahci_fis_transmit #(
if (hba_rst || any_cmd_start) dx_err_r[1] <= 0;
else if (xmit_err) dx_err_r[1] <= 1;
if (hba_rst) dx_busy_r <= 0;
else if (dx_transmit) dx_busy_r <= 1;
else if (dx_dma_last_w || (|dx_err_r)) dx_busy_r <= 0;
if (hba_rst || any_cmd_start) dx_err_r[2] <= 0;
else if (xrdy_collision) dx_err_r[2] <= 1;
if (hba_rst) dx_busy_r <= 0; // sending CFIS, AFIS or data FIS (until error or R_OK)
// else if (dx_xmit) dx_busy_r <= 1;
// else if (dx_dma_last_w || (|dx_err_r)) dx_busy_r <= 0;
else if (dx_xmit || acfis_xmit_start_r) dx_busy_r <= 1;
else if (xmit_ok || (|dx_err_r)) dx_busy_r <= 0;
dma_prd_start <= (dma_start && (PREFETCH_ALWAYS || ch_p_r || !ch_w_r)) || // device read may prefetch just prd addresses
(dx_fis_pend_r && write_or_w); // enable PRD read now (if it was not already done)
......@@ -317,6 +329,11 @@ module ahci_fis_transmit #(
else if (any_cmd_start) busy <= 1;
else if (done_w) busy <= 0;
if (hba_rst) xmit_ok_r <= 0;
else xmit_ok_r <= dx_busy_r && !(|dx_err_r) && xmit_ok;
dma_cmd_abort <= done_w && (|dx_err_r);
......
......@@ -48,7 +48,7 @@ module ahci_fsm
output comreset_send, // Not possible yet?
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
// 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,
......@@ -213,7 +213,7 @@ module ahci_fsm
output fetch_cmd, // Enter p:FetchCmd, fetch command header (from the register memory, prefetch command FIS)
// wait for either fetch_cmd_busy == 0 or pCmdToIssue ==1 after fetch_cmd
output cfis_xmit, // transmit command (wait for dma_ct_busy == 0)
output dx_transmit, // send FIS header DWORD, (just 0x46), then forward DMA data
output dx_xmit, // send FIS header DWORD, (just 0x46), then forward DMA data
// transmit until error, 2048DWords or pDmaXferCnt
output atapi_xmit, // tarsmit ATAPI command FIS
input xmit_done,
......@@ -224,7 +224,7 @@ module ahci_fsm
// output dmaCntrZero, // DMA counter is zero - would be a duplicate to the one in receive module and dwords_sent output
// input syncesc_recv, // These two inputs interrupt transmit
// input xmit_err, //
input [ 1:0] dx_err, // bit 0 - syncesc_recv, 1 - xmit_err (valid @ xmit_err and later, reset by new command)
input [ 2:0] dx_err, // bit 0 - syncesc_recv, 1 - xmit_err, 2 - X_RDY/X_RDY collision (valid @ xmit_err and later, reset by new command)
/// input [15:0] ch_prdtl, // Physical region descriptor table length (in entries, 0 is 0)
input ch_c, // Clear busy upon R_OK for this FIS
......@@ -272,7 +272,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;
// reg x_rdy_collision_pend;
reg syncesc_send_pend; // waiting for 'syncesc_send' confiramtion 'syncesc_send_done'
reg [1:0] phy_ready_prev; // previous state of phy_ready / speed
reg phy_ready_chng_r; // pulse when phy_ready changes
......@@ -353,8 +353,8 @@ module ahci_fsm
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;
// if (hba_rst || pcmd_cr_set) x_rdy_collision_pend <= 0;
// else if (x_rdy_collision) x_rdy_collision_pend <= 1;
if (hba_rst || syncesc_send_done) syncesc_send_pend <= 0;
else if (syncesc_send) syncesc_send_pend <= 1;
......@@ -435,7 +435,7 @@ module ahci_fsm
.FETCH_CMD (fetch_cmd), // output reg
.ATAPI_XMIT (atapi_xmit), // output reg
.CFIS_XMIT (cfis_xmit), // output reg
.DX_XMIT (dx_transmit), // output reg
.DX_XMIT (dx_xmit), // output reg
//FIS RECEIVE/WAIT DONE
.GET_DATA_FIS (get_data_fis), // output reg
.GET_DSFIS (get_dsfis), // output reg
......@@ -500,7 +500,7 @@ module ahci_fsm
// DMA
.DMA_PRD_IRQ_PEND (dma_prd_irq_pend), // input
// SATA TRANSPORT/LINK/PHY
.X_RDY_COLLISION (x_rdy_collision_pend) // input
.X_RDY_COLLISION (dx_err[2]) //x_rdy_collision_pend) // input
);
......
This diff is collapsed.
......@@ -143,8 +143,9 @@ module ahci_top#(
// communication with transport/link/phys layers
// input phy_rst, // frome phy, as a response to hba_arst || port_arst. It is deasserted when clock is stable
input [ 1:0] phy_ready, // 0 - not ready, 1..3 - negotiated speed
input syncesc_recv, // These two inputs interrupt transmit
input xmit_ok, // FIS transmission acknowledged OK
input xmit_err, // Error during sending of a FIS
input syncesc_recv, // These two inputs interrupt transmit
output syncesc_send, // Send sync escape
input syncesc_send_done, // "SYNC escape until the interface is quiescent..."
output comreset_send, // Not possible yet?
......@@ -317,7 +318,7 @@ module ahci_top#(
wire fsnd_fetch_cmd; // Enter p:FetchCmd, fetch command header (from the register memory, prefetch command FIS)
// wait for either fetch_cmd_busy == 0 or pCmdToIssue ==1 after fetch_cmd
wire fsnd_cfis_xmit; // transmit command (wait for dma_ct_busy == 0)
wire fsnd_dx_transmit; // send FIS header DWORD, (just 0x46), then forward DMA data
wire fsnd_dx_xmit; // send FIS header DWORD, (just 0x46), then forward DMA data
// transmit until error, 2048DWords or pDmaXferCnt
wire fsnd_atapi_xmit; // tarsmit ATAPI command FIS
// responses fsm <- ahc_fis_transmit
......@@ -327,7 +328,7 @@ module ahci_top#(
wire fsnd_clearCmdToIssue; // From CFIS:SUCCESS
// State variables fsm <- ahc_fis_transmit
wire fsnd_pCmdToIssue; // AHCI port variable
wire [ 1:0] fsnd_dx_err; // bit 0 - syncesc_recv, 1 - xmit_err (valid @ xmit_err and later, reset by new command)
wire [ 2:0] fsnd_dx_err; // bit 0 - syncesc_recv, 1 - xmit_err 2 - X-RDY/X_RDY collision (valid @ xmit_err and later, reset by new command)
wire fsnd_ch_c; // Clear busy upon R_OK for this FIS
wire fsnd_ch_b; // Built-in self test command
wire fsnd_ch_r; // reset - may need to send SYNC escape before this command
......@@ -444,7 +445,7 @@ module ahci_top#(
.syncesc_send_done (syncesc_send_done), // input
.cominit_got (cominit_got), // input
.set_offline (set_offline), // output
.x_rdy_collision (x_rdy_collision), // input
// .x_rdy_collision (x_rdy_collision), // input
.send_R_OK (send_R_OK), // output
.send_R_ERR (send_R_ERR), // output
......@@ -572,7 +573,7 @@ module ahci_top#(
.fetch_cmd (fsnd_fetch_cmd), // output
.cfis_xmit (fsnd_cfis_xmit), // output
.dx_transmit (fsnd_dx_transmit), // output
.dx_xmit (fsnd_dx_xmit), // output
.atapi_xmit (fsnd_atapi_xmit), // output
.xmit_done (fsnd_done), // input
/// .xmit_busy (fsnd_busy), // input
......@@ -901,20 +902,23 @@ module ahci_top#(
.READ_CT_LATENCY (READ_CT_LATENCY),
.ADDRESS_BITS (ADDRESS_BITS)
) ahci_fis_transmit_i (
.hba_rst (mrst), // input
// .hba_rst (mrst), // input TODO: Reset when !PxCMD.ST? pcmd_st
.hba_rst (mrst || !pcmd_st), // input TODO: Reset when !PxCMD.ST? pcmd_st
.mclk (mclk), // input
.fetch_cmd (fsnd_fetch_cmd), // input
.cfis_xmit (fsnd_cfis_xmit), // input
.dx_transmit (fsnd_dx_transmit), // input
.dx_xmit (fsnd_dx_xmit), // input
.atapi_xmit (fsnd_atapi_xmit), // input
.done (fsnd_done), // output reg
.busy (), /// fsnd_busy), // output reg
.clearCmdToIssue (fsnd_clearCmdToIssue), // input
.pCmdToIssue (fsnd_pCmdToIssue), // output
.syncesc_recv (syncesc_recv), // input
.xmit_ok (xmit_ok), // input
.xmit_err (xmit_err), // input
.syncesc_recv (syncesc_recv), // input
.xrdy_collision (x_rdy_collision), // input
.dx_err (fsnd_dx_err), // output[1:0]
.ch_prdtl (prdtl), // output[15:0]
.ch_c (fsnd_ch_c), // output
......
......@@ -88,6 +88,8 @@ module link #(
output wire incom_done,
// if incoming transition had errors
output wire incom_invalidate,
// particular type - got sync escape
output wire incom_sync_escape,
// transport layer responds on a completion of a FIS
input wire incom_ack_good,
input wire incom_ack_bad,
......@@ -611,8 +613,11 @@ assign incom_start = set_rcvr_wait & ~alignes_pair;
// ... and processed
assign incom_done = set_rcvr_goodcrc & ~alignes_pair;
// or the FIS had errors
assign incom_invalidate = state_rcvr_eof & crc_bad & ~alignes_pair | state_rcvr_data & dword_val & rcvd_dword[CODE_WTRMP]
| (state_rcvr_wait | state_rcvr_rdy | state_rcvr_data | state_rcvr_rhold | state_rcvr_shold | state_rcvr_eof | state_rcvr_goodcrc) & got_escape;
//assign incom_invalidate = state_rcvr_eof & crc_bad & ~alignes_pair | state_rcvr_data & dword_val & rcvd_dword[CODE_WTRMP]
// | (state_rcvr_wait | state_rcvr_rdy | state_rcvr_data | state_rcvr_rhold | state_rcvr_shold | state_rcvr_eof | state_rcvr_goodcrc) & got_escape;
// Separating different types of errors, sync_escape from other problems. TODO: route individual errors to set SERR bits
assign incom_invalidate = state_rcvr_eof & crc_bad & ~alignes_pair | state_rcvr_data & dword_val & rcvd_dword[CODE_WTRMP];
assign incom_sync_escape = (state_rcvr_wait | state_rcvr_rdy | state_rcvr_data | state_rcvr_rhold | state_rcvr_shold | state_rcvr_eof | state_rcvr_goodcrc) & got_escape;
// shows that incoming primitive or data is ready to be processed // TODO somehow move alignes_pair into dword_val
assign dword_val = |rcvd_dword & phy_ready & ~rcvd_dword[CODE_ALIGNP];
......
......@@ -386,6 +386,7 @@ wire ll2tl_incom_start;
wire ll2tl_incom_done;
// LL reports of errors in current FIS
wire ll2tl_incom_invalidate; // TODO
wire ll2tl_incom_sync_escape;
// TL analyzes FIS and returnes if FIS makes sense.
wire ll2tl_incom_ack_good;
// ... and if it doesn't
......@@ -452,7 +453,7 @@ transport transport(
// LL reports of a completion of an incoming frame transmission.
.incom_done (ll2tl_incom_done),
// LL reports of errors in current FIS
.incom_invalidate (ll2tl_incom_invalidate), // TODO
.incom_invalidate (ll2tl_incom_invalidate || ll2tl_incom_sync_escape), // TODO
// TL analyzes FIS and returnes if FIS makes sense.
.incom_ack_good (ll2tl_incom_ack_good),
// ... and if it doesn't
......@@ -648,6 +649,8 @@ link link(
.incom_done (ll2tl_incom_done),
// if incoming transition had errors
.incom_invalidate (ll2tl_incom_invalidate),
// if incoming got sync escape
.incom_sync_escape (ll2tl_incom_sync_escape), // output wire
// transport layer responds on a completion of a FIS
.incom_ack_good (ll2tl_incom_ack_good),
.incom_ack_bad (ll2tl_incom_ack_bad),
......
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