Loading py393sata/x393sata.py +156 −0 Original line number Diff line number Diff line Loading @@ -150,6 +150,11 @@ ATA_RDMA_EXT = 0x25 # Read DMA devices that support 48-bit Addressing ATA_RBUF_PIO = 0xe4 # Read 512 bytes from device buffer in PIO mode ATA_RBUF_DMA = 0xe9 # Read 512 bytes from device buffer in DMA mode ATA_READ_LOG_EXT = 0x2f ATA_SET_FEATURES = 0xef # Set features command # SET FEATURES command subcommand codes APM_ENABLE = 0x05 APM_DISABLE = 0x85 class x393sata(object): DRY_MODE= True # True Loading Loading @@ -1466,6 +1471,157 @@ class x393sata(object): else: return '10389B' # raise Exception ("Unknown camera MAC address used to get 10389 revision. Only *:01 (10389) and *:02 (10389B) are currently defined") def set_features(self, feature, param = 0, do_not_start = False, prd_irqs = None): """ Send SET FEATURES command @param feature - subcommand to be processed (see ATA/ATAPI command set 7.45 for the list of subcommands); supported commands: 0x05 (enable APM feature set), 0x85 (disable APM feature set) @param param - parameter for the feature @param do_not_start - do not actually launch the command by writing 1 to command_issue (CI) bit in PxCI register @param prd_irqs - None or a tuple/list with per-PRD interrupts """ supported_subcmd = [APM_ENABLE, APM_DISABLE] if not feature in supported_subcmd: raise Exception("Subcommand 0x%x is not supported" % (feature)) # Clear interrupt register self.x393_mem.write_mem(self.get_reg_address('HBA_PORT__PxIS'), 0xffffffff) self.sync_for_cpu('H2D',COMMAND_ADDRESS, 256) # command and PRD table # clear system memory for the command for a in range(64): self.x393_mem.write_mem(COMMAND_ADDRESS + 4*a, 0) #Setup command table in system memory self.x393_mem.write_mem(COMMAND_ADDRESS + 0, FIS_H2DR | # FIS type - H2D register (0x27) (0x80 << 8) | # set C = 1 (ATA_SET_FEATURES << 16) | # Command = 0xEF ( feature << 24)) # features = subcommand, see ATA/ATAPI command set 7.45 table 104 # other DWORDs are subcommand scpecific if feature == APM_ENABLE: count = param & 0xff self.x393_mem.write_mem(COMMAND_ADDRESS + 12, count | # count field is subcommand specific (0x08 << 24)) # control field as set by hdparm # Setup command header self.x393_mem.write_mem(MAXI1_ADDR + COMMAND_HEADER0_OFFS + (0 << 2), (5 << 0) | # 'CFL' - number of DWORDs in this CFIS (0 << 5) | # 'A' Not ATAPI (0 << 6) | # 'W' Not write to device # (1 << 7) | # 'P' Prefetchable = 1 (0 << 7) | # 'P' Prefetchable = 0 (0 << 8) | # 'R' Not a Reset (0 << 9) | # 'B' Not a BIST # (1 << 10) | # 'C' Do clear BSY/CI after transmitting this command (0 << 10) | # 'C' Do clear BSY/CI after transmitting this command (0 << 16)) # 'PRDTL' - number of PRDT entries (no data required) self.x393_mem.write_mem(MAXI1_ADDR + COMMAND_HEADER0_OFFS + (2 << 2), (COMMAND_ADDRESS)) # 'CTBA' - Command table base address self.sync_for_device('H2D',COMMAND_ADDRESS, 256) # command and PRD table self.sync_for_device('D2H',DATAIN_ADDRESS, 512) # Set PxCMD.ST bit (it may already be set) self.x393_mem.write_mem(self.get_reg_address('HBA_PORT__PxCMD'), 0x11) # .ST and .FRE bits (FRE is readonly 1 anyway) # Set Command Issued if do_not_start: print ('Run the following command to start the comand:') print("mem.write_mem(sata.get_reg_address('HBA_PORT__PxCI'), 1)") else: self.x393_mem.write_mem(self.get_reg_address('HBA_PORT__PxCI'), 1) print("Command table data:") print("_=mem.mem_dump (0x%x, 0x10,4)"%(COMMAND_ADDRESS)) self.x393_mem.mem_dump (COMMAND_ADDRESS, 0x20,4) #Wait interrupt for _ in range(10): istat = self.x393_mem.read_mem(self.get_reg_address('HBA_PORT__PxIS')) if istat: self.parse_register(group_range = ['HBA_PORT__PxIS'], skip0 = True, dword = None) if istat != 1: #DHRS interrupt (for PIO - 2) print ("\n ======================Got wrong interrupt ============================") self.reg_status() print("_=mem.mem_dump (0x%x, 0x4,4)"%(MAXI1_ADDR + DBG_OFFS)) self.x393_mem.mem_dump (MAXI1_ADDR + DBG_OFFS, 0x4,4) print("Datascope (debug) data:") print("_=mem.mem_dump (0x%x, 0x20,4)"%(DATASCOPE_ADDR)) self.x393_mem.mem_dump (DATASCOPE_ADDR, 0xa0,4) dd =0 for a in range(0x80001000,0x80001014,4): dd |= self.x393_mem.read_mem(a) if dd == 0: print ("*** Probably got cache/write buffer problem, continuing ***") break raise Exception("Failed to get interrupt") break sleep(0.1) else: print ("\n ====================== Failed to get interrupt ============================") self.reg_status() print("_=mem.mem_dump (0x%x, 0x4,4)"%(MAXI1_ADDR + DBG_OFFS)) self.x393_mem.mem_dump (MAXI1_ADDR + DBG_OFFS, 0x4,4) print("Datascope (debug) data:") print("_=mem.mem_dump (0x%x, 0x100,4)"%(DATASCOPE_ADDR)) self.x393_mem.mem_dump (DATASCOPE_ADDR, 0x200,4) raise Exception("Failed to get interrupt") print("Datascope (debug) data:") print("_=mem.mem_dump (0x%x, 0x200,4)"%(DATASCOPE_ADDR)) self.x393_mem.mem_dump (DATASCOPE_ADDR, 0x200,4) def get_features(self): """ Send IDENTIFY DEVICE command and (partially) parse its output """ self.setup_pio_read_identify_command() # get power management features, see ATA/ATAPI command set 7.45.9 # all offsets here are in WORDS as given in IDENTIFY DEVICE data table and should be doubled print("Power management features:") id_word = self.x393_mem.read_mem(DATAIN_ADDRESS + IDENTIFY_BUF + 2 * 82) if id_word & 0x08: print("Power management feature set is supported (see ATA/ATAPI command set 4.15 for the full list of supported commands)") id_word = self.x393_mem.read_mem(DATAIN_ADDRESS + IDENTIFY_BUF + 2 * 83) if id_word & 0x08: id_word = self.x393_mem.read_mem(DATAIN_ADDRESS + IDENTIFY_BUF + 2 * 86) if (id_word & 0x08): is_enabled = "enabled" else: is_enabled = "disabled" print("\tAPM feature set is supported and %s" % (is_enabled)) else: print("\tAPM feature set is NOT supported") id_word = self.x393_mem.read_mem(DATAIN_ADDRESS + IDENTIFY_BUF + 2 * 91) & 0xff if id_word == 0x0: level = "reserved" elif id_word == 0x1: level = "minimum pwr with standby mode" elif id_word > 0x1 and id_word <= 0x7f: level = "intermediate pwr with standby mode" elif id_word == 0x80: level = "minimum pwr without standby mode" elif id_word >= 0x81 and id_word <= 0xfd: level = "intermediate pwr without standby mode" elif id_word == 0xfe: level = "maximun performance" elif id_word == 0xff: level = "reserved" print("\tCurrent APM level: 0x%x [%s]" % (id_word, level)) # get SATA features related to power management, see ATA/ATAPI command set 7.45.17 id_word = self.x393_mem.read_mem(DATAIN_ADDRESS + IDENTIFY_BUF + 2 * 78) if id_word & 0x08: id_word = self.x393_mem.read_mem(DATAIN_ADDRESS + IDENTIFY_BUF + 2 * 79) if id_word & 0x08: state = "device initiated power management enabled" else: state = "device initiated power management disabled" print("\tDevice supports initiating power management, %s" % (state)) id_word = self.x393_mem.read_mem(DATAIN_ADDRESS + IDENTIFY_BUF + 2 * 76) if id_word & 0x4000: print("\tSupports Device Automatic Partial to Slumber transition") if id_word & 0x2000: print("\tSupports Host Automatic Partial to Slumber transition") if id_word & 0x200: print("\tSupports receipt of host initiated power management requests") def init_sata(): Loading py393sata/x393sata_control.py +1 −1 Original line number Diff line number Diff line Loading @@ -60,7 +60,7 @@ import re from time import sleep LOGFILE = "/var/log/x393sata_eyesis4pi.log" LOGFILE = "/var/log/x393sata_control.log" STATEFILE = "/var/state/ssd" # constants Loading Loading
py393sata/x393sata.py +156 −0 Original line number Diff line number Diff line Loading @@ -150,6 +150,11 @@ ATA_RDMA_EXT = 0x25 # Read DMA devices that support 48-bit Addressing ATA_RBUF_PIO = 0xe4 # Read 512 bytes from device buffer in PIO mode ATA_RBUF_DMA = 0xe9 # Read 512 bytes from device buffer in DMA mode ATA_READ_LOG_EXT = 0x2f ATA_SET_FEATURES = 0xef # Set features command # SET FEATURES command subcommand codes APM_ENABLE = 0x05 APM_DISABLE = 0x85 class x393sata(object): DRY_MODE= True # True Loading Loading @@ -1466,6 +1471,157 @@ class x393sata(object): else: return '10389B' # raise Exception ("Unknown camera MAC address used to get 10389 revision. Only *:01 (10389) and *:02 (10389B) are currently defined") def set_features(self, feature, param = 0, do_not_start = False, prd_irqs = None): """ Send SET FEATURES command @param feature - subcommand to be processed (see ATA/ATAPI command set 7.45 for the list of subcommands); supported commands: 0x05 (enable APM feature set), 0x85 (disable APM feature set) @param param - parameter for the feature @param do_not_start - do not actually launch the command by writing 1 to command_issue (CI) bit in PxCI register @param prd_irqs - None or a tuple/list with per-PRD interrupts """ supported_subcmd = [APM_ENABLE, APM_DISABLE] if not feature in supported_subcmd: raise Exception("Subcommand 0x%x is not supported" % (feature)) # Clear interrupt register self.x393_mem.write_mem(self.get_reg_address('HBA_PORT__PxIS'), 0xffffffff) self.sync_for_cpu('H2D',COMMAND_ADDRESS, 256) # command and PRD table # clear system memory for the command for a in range(64): self.x393_mem.write_mem(COMMAND_ADDRESS + 4*a, 0) #Setup command table in system memory self.x393_mem.write_mem(COMMAND_ADDRESS + 0, FIS_H2DR | # FIS type - H2D register (0x27) (0x80 << 8) | # set C = 1 (ATA_SET_FEATURES << 16) | # Command = 0xEF ( feature << 24)) # features = subcommand, see ATA/ATAPI command set 7.45 table 104 # other DWORDs are subcommand scpecific if feature == APM_ENABLE: count = param & 0xff self.x393_mem.write_mem(COMMAND_ADDRESS + 12, count | # count field is subcommand specific (0x08 << 24)) # control field as set by hdparm # Setup command header self.x393_mem.write_mem(MAXI1_ADDR + COMMAND_HEADER0_OFFS + (0 << 2), (5 << 0) | # 'CFL' - number of DWORDs in this CFIS (0 << 5) | # 'A' Not ATAPI (0 << 6) | # 'W' Not write to device # (1 << 7) | # 'P' Prefetchable = 1 (0 << 7) | # 'P' Prefetchable = 0 (0 << 8) | # 'R' Not a Reset (0 << 9) | # 'B' Not a BIST # (1 << 10) | # 'C' Do clear BSY/CI after transmitting this command (0 << 10) | # 'C' Do clear BSY/CI after transmitting this command (0 << 16)) # 'PRDTL' - number of PRDT entries (no data required) self.x393_mem.write_mem(MAXI1_ADDR + COMMAND_HEADER0_OFFS + (2 << 2), (COMMAND_ADDRESS)) # 'CTBA' - Command table base address self.sync_for_device('H2D',COMMAND_ADDRESS, 256) # command and PRD table self.sync_for_device('D2H',DATAIN_ADDRESS, 512) # Set PxCMD.ST bit (it may already be set) self.x393_mem.write_mem(self.get_reg_address('HBA_PORT__PxCMD'), 0x11) # .ST and .FRE bits (FRE is readonly 1 anyway) # Set Command Issued if do_not_start: print ('Run the following command to start the comand:') print("mem.write_mem(sata.get_reg_address('HBA_PORT__PxCI'), 1)") else: self.x393_mem.write_mem(self.get_reg_address('HBA_PORT__PxCI'), 1) print("Command table data:") print("_=mem.mem_dump (0x%x, 0x10,4)"%(COMMAND_ADDRESS)) self.x393_mem.mem_dump (COMMAND_ADDRESS, 0x20,4) #Wait interrupt for _ in range(10): istat = self.x393_mem.read_mem(self.get_reg_address('HBA_PORT__PxIS')) if istat: self.parse_register(group_range = ['HBA_PORT__PxIS'], skip0 = True, dword = None) if istat != 1: #DHRS interrupt (for PIO - 2) print ("\n ======================Got wrong interrupt ============================") self.reg_status() print("_=mem.mem_dump (0x%x, 0x4,4)"%(MAXI1_ADDR + DBG_OFFS)) self.x393_mem.mem_dump (MAXI1_ADDR + DBG_OFFS, 0x4,4) print("Datascope (debug) data:") print("_=mem.mem_dump (0x%x, 0x20,4)"%(DATASCOPE_ADDR)) self.x393_mem.mem_dump (DATASCOPE_ADDR, 0xa0,4) dd =0 for a in range(0x80001000,0x80001014,4): dd |= self.x393_mem.read_mem(a) if dd == 0: print ("*** Probably got cache/write buffer problem, continuing ***") break raise Exception("Failed to get interrupt") break sleep(0.1) else: print ("\n ====================== Failed to get interrupt ============================") self.reg_status() print("_=mem.mem_dump (0x%x, 0x4,4)"%(MAXI1_ADDR + DBG_OFFS)) self.x393_mem.mem_dump (MAXI1_ADDR + DBG_OFFS, 0x4,4) print("Datascope (debug) data:") print("_=mem.mem_dump (0x%x, 0x100,4)"%(DATASCOPE_ADDR)) self.x393_mem.mem_dump (DATASCOPE_ADDR, 0x200,4) raise Exception("Failed to get interrupt") print("Datascope (debug) data:") print("_=mem.mem_dump (0x%x, 0x200,4)"%(DATASCOPE_ADDR)) self.x393_mem.mem_dump (DATASCOPE_ADDR, 0x200,4) def get_features(self): """ Send IDENTIFY DEVICE command and (partially) parse its output """ self.setup_pio_read_identify_command() # get power management features, see ATA/ATAPI command set 7.45.9 # all offsets here are in WORDS as given in IDENTIFY DEVICE data table and should be doubled print("Power management features:") id_word = self.x393_mem.read_mem(DATAIN_ADDRESS + IDENTIFY_BUF + 2 * 82) if id_word & 0x08: print("Power management feature set is supported (see ATA/ATAPI command set 4.15 for the full list of supported commands)") id_word = self.x393_mem.read_mem(DATAIN_ADDRESS + IDENTIFY_BUF + 2 * 83) if id_word & 0x08: id_word = self.x393_mem.read_mem(DATAIN_ADDRESS + IDENTIFY_BUF + 2 * 86) if (id_word & 0x08): is_enabled = "enabled" else: is_enabled = "disabled" print("\tAPM feature set is supported and %s" % (is_enabled)) else: print("\tAPM feature set is NOT supported") id_word = self.x393_mem.read_mem(DATAIN_ADDRESS + IDENTIFY_BUF + 2 * 91) & 0xff if id_word == 0x0: level = "reserved" elif id_word == 0x1: level = "minimum pwr with standby mode" elif id_word > 0x1 and id_word <= 0x7f: level = "intermediate pwr with standby mode" elif id_word == 0x80: level = "minimum pwr without standby mode" elif id_word >= 0x81 and id_word <= 0xfd: level = "intermediate pwr without standby mode" elif id_word == 0xfe: level = "maximun performance" elif id_word == 0xff: level = "reserved" print("\tCurrent APM level: 0x%x [%s]" % (id_word, level)) # get SATA features related to power management, see ATA/ATAPI command set 7.45.17 id_word = self.x393_mem.read_mem(DATAIN_ADDRESS + IDENTIFY_BUF + 2 * 78) if id_word & 0x08: id_word = self.x393_mem.read_mem(DATAIN_ADDRESS + IDENTIFY_BUF + 2 * 79) if id_word & 0x08: state = "device initiated power management enabled" else: state = "device initiated power management disabled" print("\tDevice supports initiating power management, %s" % (state)) id_word = self.x393_mem.read_mem(DATAIN_ADDRESS + IDENTIFY_BUF + 2 * 76) if id_word & 0x4000: print("\tSupports Device Automatic Partial to Slumber transition") if id_word & 0x2000: print("\tSupports Host Automatic Partial to Slumber transition") if id_word & 0x200: print("\tSupports receipt of host initiated power management requests") def init_sata(): Loading
py393sata/x393sata_control.py +1 −1 Original line number Diff line number Diff line Loading @@ -60,7 +60,7 @@ import re from time import sleep LOGFILE = "/var/log/x393sata_eyesis4pi.log" LOGFILE = "/var/log/x393sata_control.log" STATEFILE = "/var/state/ssd" # constants Loading