diff --git a/lib/sata/std.py b/lib/sata/std.py index aac6a3411..bd054da3f 100644 --- a/lib/sata/std.py +++ b/lib/sata/std.py @@ -48,13 +48,48 @@ def link_layout(dw): ] return EndpointDescription(layout, packetized=True) -def transport_tx_layout(dw): +def transport_cmd_tx_layout(): layout = [ - ("d", dw) + ("type", 8), + ("pm_port", 4), + ("a", 1), + ("c", 1), + ("d", 1), + ("i", 1), + ("command", 8), + ("features", 16), + ("lba", 48), + ("device", 8), + ("count", 16), + ("icc", 8), + ("control", 8), + ("dma_buffer_id", 64), + ("dma_buffer_offset", 32), + ("dma_transfer_count", 32), ] return EndpointDescription(layout, packetized=True) -def transport_rx_layout(dw): +def transport_cmd_rx_layout(): + layout = [ + ("type", 8), + ("pm_port", 4), + ("a", 1), + ("d", 1), + ("i", 1), + ("status", 8), + ("error", 8), + ("lba", 48), + ("device", 8), + ("count", 16), + ("e_status", 8), + ("transfer_count", 16), + ("dma_buffer_id", 64), + ("dma_buffer_offset", 32), + ("dma_transfer_count", 32) + ] + return EndpointDescription(layout, packetized=True) + +def transport_data_layout(dw): layout = [ ("d", dw) ] diff --git a/lib/sata/transport/__init__.py b/lib/sata/transport/__init__.py index a9e0042e6..ba0161dce 100644 --- a/lib/sata/transport/__init__.py +++ b/lib/sata/transport/__init__.py @@ -1,15 +1,125 @@ from lib.sata.std import * from lib.sata.transport.std import * +def _encode_cmd(obj, layout, signal): + r = [] + for k, v in sorted(layout.items()): + start = v.word*32 + v.offset + end = start + v.width + r.append(signal[start:end].eq(getattr(obj, k))) + return r + class SATATransportLayerTX(Module): - def __init__(self): - self.sink = Sink(transport_layout(32)) + def __init__(self, link): + self.cmd = cmd = Sink(transport_cmd_tx_layout()) + self.data = data = Sink(transport_data_layout(32)) + + ### + + cmd_ndwords = max(fis_reg_h2d_cmd_len, fis_dma_setup_cmd_len, fis_data_cmd_len) + encoded_cmd = Signal(cmd_ndwords*32) + + cnt = Signal(max=cmd_ndwords+1) + clr_cnt = Signal() + inc_cnt = Signal() + + cmd_len = Signal(flen(cnt)) + cmd_with_data = Signal() + + cmd_send = Signal() + data_send = Signal() + cmd_done = Signal() + data_done = Signal() + + fsm = FSM(reset_state="IDLE") + self.submodules += fsm + + # FSM + fsm.act("IDLE", + clr_cnt.eq(1), + If(cmd.stb, + If(cmd.type == fis_types["REG_H2D"], + NextState("SEND_REG_H2D_CMD") + ).Elif(cmd.type == "DMA_SETUP_CMD", + NextState("SEND_DMA_SETUP") + ).Elif(cmd.type == "DATA_CMD"), + NextState("SEND_DATA") + ).Else( + # XXX: Generate error to command layer? + cmd.ack.eq(1) + ) + ) + ) + fsm.act("SEND_REG_H2D_CMD", + _encode_cmd(self.cmd, fis_reg_h2d_layout, encoded_cmd), + cmd_len.eq(fis_reg_h2d_cmd_len), + cmd_send.eq(1) + If(ack_cmd, + NextState.eq("ACK") + ) + ) + fsm.act("SEND_DMA_SETUP_CMD", + _encode_cmd(self.cmd, fis_dma_setup_layout, encoded_cmd), + cmd_len.eq(fis_dma_setup_cmd_len), + cmd_send.eq(1), + If(ack_cmd, + NextState.eq("ACK") + ) + ) + fsm.act("SEND_DATA_CMD", + _encode_cmd(self.cmd, fis_data_layout, encoded_cmd), + cmd_len.eq(fis_send_data_cmd_len), + cmd_width_data.eq(1), + cmd_send.eq(1), + If(cmd_done, + NextState.eq("SEND_DATA") + ) + ) + fsm.act("SEND_DATA", + data_send.eq(1), + If(data_done, + NextState.eq("ACK") + ) + ) + fsm.act("ACK", + cmd.ack.eq(1), + NextState.eq("IDLE") + ) + + cmd_cases = {} + for i in range(cmd_ndwords): + cmd_cases[i] = [link.sink.d.eq(encoded_cmd[32*i:32*(i+1)])] + + self.comb += \ + If(cmd_send, + link.sink.stb.eq(1), + link.sink.sop.eq(cnt==0), + link.sink.eop.eq((cnt==cmd_len) & ~cmd_with_data), + Case(cnt, cmd_cases), + inc_cnt.eq(link.sink.ack), + cmd_done.eq(cnt==cmd_len) + ).Elif(data_send, + link.sink.stb.eq(data.stb), + link.sink.sop.eq(0), + link.sink.eop.eq(data.eop), + link.sink.d.eq(data.d), + data.ack.eq(link.sink.ack), + data_done.eq(data.eop & data.ack) + ) + + self.sync += \ + If(clr_cnt, + cnt.eq(0) + ).Elif(inc_cnt, + cnt.eq(cnt+1) + ) class SATATransportLayerRX(Module): - def __init__(self): - self.sink = Sink(transport_layout(32)) + def __init__(self, link): + self.cmd = Source(transport_cmd_rx_layout()) + self.data = Source(transport_data_layout(32)) class SATATransportLayer(Module): - def __init__(self): - self.submodules.tx = SATATransportLayerTX() - self.submodules.rx = SATATransportLayerRX() + def __init__(self, link): + self.submodules.tx = SATATransportLayerTX(link) + self.submodules.rx = SATATransportLayerRX(link) diff --git a/lib/sata/transport/std.py b/lib/sata/transport/std.py index 03b56b2d0..a38b45ee0 100644 --- a/lib/sata/transport/std.py +++ b/lib/sata/transport/std.py @@ -13,7 +13,7 @@ class FISField(): self.offset = offset self.width = width -fis_reg_h2d_len = 5 +fis_reg_h2d_cmd_len = 5 fis_reg_h2d_layout = { "type": FISField(0, 0, 8), "pm_port": FISField(0, 8, 4), @@ -22,7 +22,7 @@ fis_reg_h2d_layout = { "features_lsb": FISField(0, 24, 8), "lba_lsb": FISField(1, 0, 24), - "device": FISField(1, 24, 0), + "device": FISField(1, 24, 8), "lba_msb": FISField(2, 0, 24), "features_msb": FISField(2, 24, 8), @@ -32,7 +32,7 @@ fis_reg_h2d_layout = { "control": FISField(3, 24, 8) } -fis_reg_d2h_len = 5 +fis_reg_d2h_cmd_len = 5 fis_reg_d2h_layout = { "type": FISField(0, 0, 8), "pm_port": FISField(0, 8, 4), @@ -41,20 +41,20 @@ fis_reg_d2h_layout = { "error": FISField(0, 24, 8), "lba_lsb": FISField(1, 0, 24), - "device": FISField(1, 24, 0), + "device": FISField(1, 24, 8), "lba_msb": FISField(2, 0, 24), "count": FISField(3, 0, 16) } -fis_dma_activate_d2h_len = 1 +fis_dma_activate_d2h_cmd_len = 1 fis_dma_activate_d2h_layout = { "type": FISField(0, 0, 8), "pm_port": FISField(0, 8, 4) } -fis_dma_setup_len = 7 +fis_dma_setup_cmd_len = 7 fis_dma_setup_layout = { "type": FISField(0, 0, 8), "pm_port": FISField(0, 8, 4), @@ -71,6 +71,7 @@ fis_dma_setup_layout = { "dma_transfer_count": FISField(4, 0, 32) } +fis_data_cmd_len = 1 fis_data_layout = { "type": FISField(0, 0, 8) } @@ -85,7 +86,7 @@ fis_pio_setup_d2h_layout = { "error": FISField(0, 24, 8), "lba_lsb": FISField(1, 0, 24), - "device": FISField(1, 24, 0), + "device": FISField(1, 24, 8), "lba_msb": FISField(2, 0, 24),