Commit 2d285422 authored by Oleg Dzhimiev's avatar Oleg Dzhimiev
Browse files

merged eyesis4pi to regular script

parent 919ed05d
Loading
Loading
Loading
Loading
+231 −18
Original line number Diff line number Diff line
@@ -2,15 +2,75 @@

from __future__ import print_function
from __future__ import division

'''
/**
# Copyright (C) 2017, Elphel.inc.
# Description: switch between internal and external SSDs
# Comments:
#     reset_device (3x times max) 
#       does not matter if error or not - reload driver - wait for 10 seconds + 10
#           if error - reload (repeat up to 5x)
#
# Solved problem:
#     when using overlays deleting existing in the lower layer dirs can cause error (hopefully it gets fixed someday):
#       example: 
#           * /mnt/sda1 exists in lower layer: /tmp/rootfs.ro/tmp
#           * upper layer is mounted to /
#       # rmdir /mnt/sda1
#       # mkdir /mnt/sda1
#       mkdir: cannot create directory '/mnt/sda1': Operation not supported
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http:#www.gnu.org/licenses/>.

@author:     Oleg K Dzhimiev
@copyright:  2017 Elphel, Inc.
@license:    GPLv3.0+
@contact:    oleg@elphel.com
@deffield    updated: unknown
'''

__author__ = "Elphel"
__copyright__ = "Copyright 2017, Elphel, Inc."
__license__ = "GPL"
__version__ = "3.0+"
__maintainer__ = "Oleg K Dzhimiev"
__email__ = "oleg@elphel.com"
__status__ = "Development"

import x393sata
import x393_mem

import subprocess
import sys
import time
import os
import re

from time import sleep

LOGFILE = "/var/log/x393sata_control.log"
LOGFILE = "/var/log/x393sata_eyesis4pi.log"
STATEFILE = "/var/state/ssd"

# constants
RESET_LIMIT = 10
RESET_LIMIT = 3
DRIVER_RELOAD_LIMIT = 5
DRIVER_WAIT_TIME = 10
DRIVER_UNLOAD_TRIES = 30

#global
DEVICE_CONNECTED = False

def colorize(string, color, bold):
    color=color.upper()
@@ -36,6 +96,7 @@ def colorize(string, color, bold):
        attr.append('1')
    return '\x1b[%sm%s\x1b[0m' % (';'.join(attr), string)


def log_msg(msg, mode=0):
    bold = False
    color = ""
@@ -54,10 +115,18 @@ def log_msg(msg, mode=0):
        print("[%8.2f]  %s"%(t,msg),file=msg_file)
    if bold or color:
        msg = colorize(msg,color,bold)    
    print (colorize("[%8.2f] %s: "%(t, sys.argv[0].split('/')[-1].split('.')[0]),'CYAN',0)+msg)
    print (colorize("[%8.2f] %s: "%(t, sys.argv[0].split('/')[-1].split('.')[0]),'GREEN',0)+msg)


def shout(cmd):
  #subprocess.call prints to console
  subprocess.call(cmd,shell=True)


def connection_errors():
  
  global DEVICE_CONNECTED
  
  result = True
  skip0 = True
  MAXI1_ADDR = 0x80000000
@@ -77,6 +146,8 @@ def connection_errors():
    fld_value = (data >> fld['start_bit']) & ((1 << fld['num_bits']) - 1)
    if first_line:
        log_msg("%s: 0x%08x [%08x]"%(group_range, data, byte_addr))
        if data!=0:
          DEVICE_CONNECTED = True
        first_line = False
    if fld_value or not skip0:
        log_msg("%8x : %s (%s)"%(fld_value, fld['name'], fld['description'] ))
@@ -88,8 +159,13 @@ def connection_errors():


def reset_device():
  
  global DEVICE_CONNECTED
  
  result = False
  
  sleep(0.5)
  
  for i in range(RESET_LIMIT):
    if not connection_errors():        
      log_msg("connection error ("+str(i)+"), resetting device",4)
@@ -100,10 +176,147 @@ def reset_device():
      if i!=0: 
        log_msg("resetting device: success")
      result = True
    
    if i==0:
      DEVICE_CONNECTED = False
    
    if result:
      break
  
  # load driver in any case
  load_driver()
  return result

def load_ahci_elphel_driver():
  
  shout("modprobe ahci_elphel &")
  shout("sleep 2")
  shout("echo 1 > /sys/devices/soc0/amba@0/80000000.elphel-ahci/load_module")
  log_msg("AHCI driver loaded")
  

def unload_ahci_elphel_driver():
  
  for i in range(DRIVER_UNLOAD_TRIES):
    unmount_partitions()
    try:
      output = subprocess.check_output(["rmmod","ahci_elphel"],stderr=subprocess.STDOUT)
    except subprocess.CalledProcessError as e:
      output = [x.strip() for x in e.output.split(":")]
      if output[-1]=="Resource temporarily unavailable":
        log_msg("Tried to unload driver "+str(i)+": "+output[-1])
        if i==(DRIVER_UNLOAD_TRIES-1):
          log_msg("AHCI driver unloading timeout")
        sleep(2)
      else:
        log_msg("AHCI driver is not loaded")
        break
    else:
      log_msg("AHCI driver unloaded")
      break

def unmount_partitions():
  
  with open("/proc/mounts") as f:
    content = f.readlines()
  
  content = [x.strip() for x in content]
  content = [x.split(" ")[0] for x in content]
  
  for mounted_device in content:
    m = re.search(r"sd[a-z][0-9]",mounted_device)
    if m:
      mountpoint = "/mnt/"+m.group(0)
      partname = "/dev/"+m.group(0)
      log_msg("Unmounting "+partname)
      shout("umount "+mountpoint)

def load_driver():

  for i in range(DRIVER_RELOAD_LIMIT):
    log_msg("Loading SATA driver ("+str(i)+")")
    result = reload_driver()
    if result:
      break
    
  if not result:
    log_msg("SATA failed, SSD was not detected: reconnect SSD",2)
    shout("echo 0 > "+STATEFILE)
  else:
    if not DEVICE_CONNECTED:
      log_msg("SSD was not detected, ahci_elphel driver is loaded",4)
    else:
      log_msg("SATA ok, SSD detected after "+str(i)+" tries")
      #automount()
    shout("echo 1 > "+STATEFILE)
  

#def automount():
  #output = subprocess.check_output("blkid")
  #output = output.split("\n")
  
  #for line in output:
    #pars = line.split(" ")
    #m = re.search(r"sd[a-z][0-9]",pars[0])
    #if m:
      #pname = m.group(0)
      #m = re.search(r"TYPE=\"ext",pars[2])
      #if m:
        #mount_partition(pname)

#def mount_partition(dirname):
  #mountpoint = "/mnt/"+dirname
  #partname = "/dev/"+dirname
  
  #if not os.path.exists(mountpoint):
    #shout("mkdir "+mountpoint)
    #shout("mount "+partname+" "+mountpoint)

def check_device():
  with open("/proc/partitions") as f:
    content = f.readlines()
  
  content = [x.strip() for x in content]
  content = [x.split(" ")[-1] for x in content]
  
  result = False
  
  for device in content:
    m = re.search(r"sd[a-z]",device)
    if m:
      result = True
      break
  
  return result

def reload_driver():

  unload_ahci_elphel_driver()
  # check once
  sata.reset_ie()
  sata.reset_device()
  sleep(0.5)
  connection_errors()
  
  load_ahci_elphel_driver()
  
  if DEVICE_CONNECTED:
    sleep(DRIVER_WAIT_TIME)
    result = check_device()
    
    # one more try
    if not result:
      log_msg(colorize("SSD was not detected: waiting for another "+str(DRIVER_WAIT_TIME)+" seconds",'YELLOW',True))
      sleep(DRIVER_WAIT_TIME)  
      result = check_device()
  else:
    result = True
  
  return result

def unmount_unload_disconnect():
  unload_ahci_elphel_driver()
  sata.vsc3304.disconnect_all()  

mem = x393_mem.X393Mem(0,0,1)
sata = x393sata.x393sata() # 1,0,"10389B")
@@ -115,24 +328,24 @@ else:


if   cmd == "set_zynq_ssd":
  #sata.vsc3304.disconnect_all()
  unmount_unload_disconnect()
  sata.set_zynq_ssd()
  #reset_device()
  reset_device()
elif cmd == "set_zynq_esata":
  #sata.vsc3304.disconnect_all()
  unmount_unload_disconnect()
  sata.set_zynq_esata()
  #reset_device()
  reset_device()
elif cmd == "set_zynq_ssata":
  #sata.vsc3304.disconnect_all()
  unmount_unload_disconnect()
  sata.set_zynq_ssata()
  #reset_device()
  reset_device()
elif cmd == "set_esata_ssd":
  #sata.vsc3304.disconnect_all()
  unmount_unload_disconnect()
  sata.set_esata_ssd()
  #reset_device()
  # no reset because PC
else:
  print("Usage:")
  print("    * camera <-> internal SSD  :            x393sata_control.py set_zynq_ssd")
  print("    * camera <-> external disk :            x393sata_control.py set_zynq_esata")
  print("    * camera <-> external disk (crossover): x393sata_control.py set_zynq_ssata")
  print("    * PC <-> internal SSD)     :            x393sata_control.py set_esata_ssd")
  print("    * camera <-> internal SSD  :            x393sata_eyesis4pi_control.py set_zynq_ssd")
  print("    * camera <-> external disk :            x393sata_eyesis4pi_control.py set_zynq_esata")
  print("    * camera <-> external disk (crossover): x393sata_eyesis4pi_control.py set_zynq_ssata")
  print("    * PC <-> internal SSD)     :            x393sata_eyesis4pi_control.py set_esata_ssd")
+1 −1
Original line number Diff line number Diff line
@@ -342,7 +342,7 @@ elif cmd == "set_zynq_ssata":
elif cmd == "set_esata_ssd":
  unmount_unload_disconnect()
  sata.set_esata_ssd()
  reset_device()
  # no reset because PC
else:
  print("Usage:")
  print("    * camera <-> internal SSD  :            x393sata_eyesis4pi_control.py set_zynq_ssd")