diff options
Diffstat (limited to 'kernel/xpp/utils/zconf/Zaptel/Xpp/Xbus.pm')
-rw-r--r-- | kernel/xpp/utils/zconf/Zaptel/Xpp/Xbus.pm | 148 |
1 files changed, 117 insertions, 31 deletions
diff --git a/kernel/xpp/utils/zconf/Zaptel/Xpp/Xbus.pm b/kernel/xpp/utils/zconf/Zaptel/Xpp/Xbus.pm index e840f14..f87e2aa 100644 --- a/kernel/xpp/utils/zconf/Zaptel/Xpp/Xbus.pm +++ b/kernel/xpp/utils/zconf/Zaptel/Xpp/Xbus.pm @@ -40,49 +40,135 @@ sub get_xpd_by_number($$) { my $xbus = shift; my $xpdid = shift; die "Missing XPD id parameter" unless defined $xpdid; + $xpdid = sprintf("%02d", $xpdid); my @xpds = $xbus->xpds; my ($wanted) = grep { $_->id eq $xpdid } @xpds; return $wanted; } +my %file_warned; # Prevent duplicate warnings about same file. + +sub xbus_attr_path($$) { + my ($busnum, @attr) = @_; + foreach my $attr (@attr) { + my $file = sprintf "$Zaptel::Xpp::sysfs_astribanks/xbus-%02d/$attr", $busnum; + unless(-f $file) { + my $procfile = sprintf "/proc/xpp/XBUS-%02d/$attr", $busnum; + warn "$0: warning - OLD DRIVER: missing '$file'. Fall back to '$procfile'\n" + unless $file_warned{$attr}++; + $file = $procfile; + } + next unless -f $file; + return $file; + } + return undef; +} + +sub xbus_getattr($$) { + my $xbus = shift || die; + my $attr = shift || die; + $attr = lc($attr); + my $file = xbus_attr_path($xbus->num, lc($attr)); + + open(F, $file) || die "Failed opening '$file': $!"; + my $val = <F>; + close F; + chomp $val; + return $val; +} + +sub read_attrs() { + my $xbus = shift || die; + my @attrnames = qw(CONNECTOR LABEL STATUS); + my @attrs; + + foreach my $attr (@attrnames) { + my $val = xbus_getattr($xbus, $attr); + if($attr eq 'STATUS') { + # Some values are in all caps as well + $val = uc($val); + } elsif($attr eq 'LABEL') { + # Fix badly burned labels. + $val =~ s/[[:^print:]]/_/g; + } + $xbus->{$attr} = $val; + } +} + +sub read_xpdnames_old($) { + my $xbus_num = shift || die; + my $pat = sprintf "/proc/xpp/XBUS-%02d/XPD-[0-9][0-9]", $xbus_num; + my @xpdnames; + + #print STDERR "read_xpdnames_old($xbus_num): $pat\n"; + foreach (glob $pat) { + die "Bad /proc entry: '$_'" unless /^.*XPD-([0-9])([0-9])$/; + my $name = sprintf("%02d:%1d:%1d", $xbus_num, $1, $2); + #print STDERR "\t> $_ ($name)\n"; + push(@xpdnames, $name); + } + return @xpdnames; +} + +sub read_xpdnames($) { + my $xbus_num = shift || die; + my $xbus_dir = "$Zaptel::Xpp::sysfs_astribanks/xbus-$xbus_num"; + my $pat = sprintf "%s/xbus-%02d/[0-9][0-9]:[0-9]:[0-9]", $Zaptel::Xpp::sysfs_astribanks, $xbus_num; + my @xpdnames; + + #print STDERR "read_xpdnames($xbus_num): $pat\n"; + foreach (glob $pat) { + die "Bad /sys entry: '$_'" unless m/^.*\/([0-9][0-9]):([0-9]):([0-9])$/; + my ($busnum, $unit, $subunit) = ($1, $2, $3); + my $name = sprintf("%02d:%1d:%1d", $1, $2, $3); + #print STDERR "\t> $_ ($name)\n"; + push(@xpdnames, $name); + } + return @xpdnames; +} + +my $warned_notransport = 0; + sub new($$) { my $pack = shift or die "Wasn't called as a class method\n"; - my $self = {}; + my $num = shift; + my $xbus_dir = "$Zaptel::Xpp::sysfs_astribanks/xbus-$num"; + my $self = { + NUM => $num, + NAME => "XBUS-$num", + SYSFS_DIR => $xbus_dir, + }; bless $self, $pack; - while(@_) { - my ($k, $v) = @_; - shift; shift; - # Keys in all caps - $k = uc($k); - # Some values are in all caps as well - if($k =~ /^(STATUS)$/) { - $v = uc($v); + $self->read_attrs; + # Get transport related info + my $transport = "$xbus_dir/transport"; + my ($usbdev) = glob("$transport/usb_device:*"); + if(defined $usbdev) { # It's USB + if($usbdev =~ /.*usb_device:usbdev(\d+)\.(\d+)/) { + my $busnum = $1; + my $devnum = $2; + #printf STDERR "DEBUG: %03d/%03d\n", $busnum, $devnum; + $self->{USB_DEVNAME} = sprintf("%03d/%03d", $busnum, $devnum); + } else { + warn "Bad USB transport='$transport' usbdev='$usbdev'\n"; } - $self->{$k} = $v; - } - # backward compat for drivers without labels. - if(!defined $self->{LABEL}) { - $self->{LABEL} = '[]'; } - $self->{LABEL} =~ s/^\[(.*)\]$/$1/ or die "$self->{NAME}: Bad label"; - # Fix badly burned labels. - $self->{LABEL} =~ s/[[:^print:]]/_/g; - $self->{NAME} or die "Missing xbus name"; - my $prefix = "$proc_base/" . $self->{NAME}; - my $usbfile = "$prefix/xpp_usb"; - if(open(F, "$usbfile")) { - my $head = <F>; - chomp $head; - close F; - $head =~ s/^device: +([^, ]+)/$1/i or die; - $self->{USB_DEVNAME} = $head; + my @xpdnames; + my @xpds; + if(-e $transport) { + @xpdnames = read_xpdnames($num); + } else { + @xpdnames = read_xpdnames_old($num); + warn "$0: warning - OLD DRIVER: missing '$transport'. Fall back to /proc\n" + unless $warned_notransport++; } - @{$self->{XPDS}} = (); - foreach my $dir (glob "$prefix/XPD-??") { - my $xpd = Zaptel::Xpp::Xpd->new($self, $dir); - push(@{$self->{XPDS}}, $xpd); + foreach my $xpdstr (@xpdnames) { + my ($busnum, $unit, $subunit) = split(/:/, $xpdstr); + my $procdir = "/proc/xpp/XBUS-$busnum/XPD-$unit$subunit"; + my $xpd = Zaptel::Xpp::Xpd->new($self, $unit, $subunit, $procdir, "$xbus_dir/$xpdstr"); + push(@xpds, $xpd); } - @{$self->{XPDS}} = sort { $a->id <=> $b->id } @{$self->{XPDS}}; + @{$self->{XPDS}} = sort { $a->id <=> $b->id } @xpds; return $self; } |