2015-04-27 08:50:43 -04:00
|
|
|
import math
|
|
|
|
|
|
|
|
from misoclib.mem.litesata.common import *
|
|
|
|
from misoclib.mem.litesata.test.common import *
|
|
|
|
|
|
|
|
from misoclib.mem.litesata.test.model.phy import *
|
|
|
|
from misoclib.mem.litesata.test.model.link import *
|
|
|
|
from misoclib.mem.litesata.test.model.transport import *
|
|
|
|
from misoclib.mem.litesata.test.model.command import *
|
|
|
|
|
2015-05-23 08:08:56 -04:00
|
|
|
|
|
|
|
def print_hdd(s, n=None):
|
|
|
|
print_with_prefix(s, "[HDD{}]: ".format("" if n is None else str(n)))
|
2015-04-27 08:50:43 -04:00
|
|
|
|
|
|
|
|
|
|
|
class HDDMemRegion:
|
|
|
|
def __init__(self, base, count, sector_size):
|
|
|
|
self.base = base
|
|
|
|
self.count = count
|
|
|
|
self.data = [0]*(count*sector_size//4)
|
|
|
|
|
|
|
|
|
|
|
|
class HDD(Module):
|
2015-05-23 08:08:56 -04:00
|
|
|
def __init__(self, n=None,
|
2015-04-27 08:50:43 -04:00
|
|
|
link_debug=False, link_random_level=0,
|
|
|
|
transport_debug=False, transport_loopback=False,
|
|
|
|
hdd_debug=False,
|
|
|
|
):
|
2015-05-23 08:08:56 -04:00
|
|
|
self.n = n
|
2015-04-27 08:50:43 -04:00
|
|
|
self.submodules.phy = PHYLayer()
|
|
|
|
self.submodules.link = LinkLayer(self.phy, link_debug, link_random_level)
|
|
|
|
self.submodules.transport = TransportLayer(self.link, transport_debug, transport_loopback)
|
|
|
|
self.submodules.command = CommandLayer(self.transport)
|
|
|
|
|
|
|
|
self.command.set_hdd(self)
|
|
|
|
|
|
|
|
self.debug = hdd_debug
|
|
|
|
self.mem = None
|
|
|
|
self.wr_sector = 0
|
|
|
|
self.wr_end_sector = 0
|
|
|
|
self.rd_sector = 0
|
|
|
|
self.rx_end_sector = 0
|
|
|
|
|
|
|
|
def malloc(self, sector, count):
|
|
|
|
if self.debug:
|
|
|
|
s = "Allocating {n} sectors: {s} to {e}".format(n=count, s=sector, e=sector+count-1)
|
|
|
|
s += " ({} KB)".format(count*logical_sector_size//1024)
|
2015-05-23 08:08:56 -04:00
|
|
|
print_hdd(s, self.n)
|
2015-04-27 08:50:43 -04:00
|
|
|
self.mem = HDDMemRegion(sector, count, logical_sector_size)
|
|
|
|
|
|
|
|
def write(self, sector, data):
|
|
|
|
n = math.ceil(dwords2sectors(len(data)))
|
|
|
|
if self.debug:
|
|
|
|
if n == 1:
|
|
|
|
s = "{}".format(sector)
|
|
|
|
else:
|
|
|
|
s = "{s} to {e}".format(s=sector, e=sector+n-1)
|
2015-05-23 08:08:56 -04:00
|
|
|
print_hdd("Writing sector " + s, self.n)
|
2015-04-27 08:50:43 -04:00
|
|
|
for i in range(len(data)):
|
|
|
|
offset = sectors2dwords(sector)
|
|
|
|
self.mem.data[offset+i] = data[i]
|
|
|
|
|
|
|
|
def read(self, sector, count):
|
|
|
|
if self.debug:
|
|
|
|
if count == 1:
|
|
|
|
s = "{}".format(sector)
|
|
|
|
else:
|
|
|
|
s = "{s} to {e}".format(s=sector, e=sector+count-1)
|
2015-05-23 08:08:56 -04:00
|
|
|
print_hdd("Reading sector " + s, self.n)
|
2015-04-27 08:50:43 -04:00
|
|
|
data = []
|
|
|
|
for i in range(sectors2dwords(count)):
|
|
|
|
data.append(self.mem.data[sectors2dwords(sector)+i])
|
|
|
|
return data
|
|
|
|
|
|
|
|
def write_dma_callback(self, fis):
|
|
|
|
self.wr_sector = fis.lba_lsb + (fis.lba_msb << 32)
|
|
|
|
self.wr_end_sector = self.wr_sector + fis.count
|
|
|
|
return [FIS_DMA_ACTIVATE_D2H()]
|
|
|
|
|
|
|
|
def read_dma_callback(self, fis):
|
|
|
|
self.rd_sector = fis.lba_lsb + (fis.lba_msb << 32)
|
|
|
|
self.rd_end_sector = self.rd_sector + fis.count
|
|
|
|
packets = []
|
|
|
|
while self.rd_sector != self.rd_end_sector:
|
|
|
|
count = min(self.rd_end_sector-self.rd_sector, (fis_max_dwords*4)//logical_sector_size)
|
|
|
|
packet = self.read(self.rd_sector, count)
|
|
|
|
packet.insert(0, 0)
|
|
|
|
packets.append(FIS_DATA(packet, direction="D2H"))
|
|
|
|
self.rd_sector += count
|
|
|
|
packets.append(FIS_REG_D2H())
|
|
|
|
return packets
|
|
|
|
|
|
|
|
def data_callback(self, fis):
|
|
|
|
self.write(self.wr_sector, fis.packet[1:])
|
|
|
|
self.wr_sector += dwords2sectors(len(fis.packet[1:]))
|
|
|
|
if self.wr_sector == self.wr_end_sector:
|
|
|
|
return [FIS_REG_D2H()]
|
|
|
|
else:
|
|
|
|
return [FIS_DMA_ACTIVATE_D2H()]
|