#!/usr/bin/env python3
# Copyright (c) 2006 Arastra, Inc.  All rights reserved.
# Arastra, Inc. Confidential and Proprietary.

# Note: this script is installed with six symlinks, named:
#   /usr/bin/pciread8
#   /usr/bin/pciread16
#   /usr/bin/pciread32
#   /usr/bin/pciwrite8
#   /usr/bin/pciwrite16
#   /usr/bin/pciwrite32

import sys, os, PciUtil

def binary( integerValue, nbytes=4 ):
   return "".join( [ ( ( integerValue>>n &1 ) and "1" or "0" ) +
      ( ( n % 4 == 0 ) and " " or "" )
      for n in range( nbytes*8-1,-1,-1 ) ] )

def error( s ):
   print( s, file=sys.stderr )
   sys.exit( 1 )

progname = os.path.basename( sys.argv[ 0 ] )
if progname == 'pciread8':
   command = 'read'
   size = 8
elif progname == 'pciread16':
   command = 'read'
   size = 16
elif progname == 'pciread32':
   command = 'read'
   size = 32
elif progname == 'pciwrite8':
   command = 'write'
   size = 8
elif progname == 'pciwrite16':
   command = 'write'
   size = 16
elif progname == 'pciwrite32':
   command = 'write'
   size = 32
else:
   error( 'Use pciread8, pciread16, pciread32, pciwrite8, pciwrite16 or pciwrite32 '
          'instead' )

if command == 'read':
   if len( sys.argv ) != 4:
      # pylint: disable-next=consider-using-f-string
      error( 'Usage: %s <bus:device.function> <resource> <address>' % progname )
else:
   if len( sys.argv ) != 5:
      # pylint: disable-next=consider-using-f-string
      error( 'Usage: %s <bus:device.function> <resource> <address> <value>' 
               % progname )

try:
   pciId = sys.argv[ 1 ]
   addr = PciUtil.strToInt( sys.argv[ 3 ] )

   if sys.argv[ 2 ] == 'config':
      resource = 'config'
   else:
      resource = int( sys.argv[ 2 ] )

   if command == 'read':
      if size == 8:
         value = PciUtil.read8( pciId, resource, addr )
         # pylint: disable-next=consider-using-f-string
         print( "%#04x ==" % value, binary( value, 1 ) )
      elif size == 16:
         value = PciUtil.read16( pciId, resource, addr )
         # pylint: disable-next=consider-using-f-string
         print( "%#06x ==" % value, binary( value, 2 ) )
      else:
         value = PciUtil.read32( pciId, resource, addr )
         # pylint: disable-next=consider-using-f-string
         print( "%#010x ==" % value, binary( value, 4 ) )

   else:
      value = PciUtil.strToInt( sys.argv[ 4 ] )
      if size == 8:
         PciUtil.write8( pciId, resource, addr, value )
      elif size == 16:
         PciUtil.write16( pciId, resource, addr, value )
      else:
         PciUtil.write32( pciId, resource, addr, value )

except ValueError as e:
   error( e )
