]
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_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_rx_layout(dw):
+def transport_data_layout(dw):
layout = [
("d", dw)
]
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)
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),
"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),
"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),
"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),
"dma_transfer_count": FISField(4, 0, 32)
}
+fis_data_cmd_len = 1
fis_data_layout = {
"type": FISField(0, 0, 8)
}
"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),