summaryrefslogtreecommitdiff
path: root/kernel/xpp/utils/zconf/Zaptel/Xpp/Xbus.pm
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/xpp/utils/zconf/Zaptel/Xpp/Xbus.pm')
-rw-r--r--kernel/xpp/utils/zconf/Zaptel/Xpp/Xbus.pm148
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;
}