Zwischencommit Installer...

git-svn-id: http://svn.ipfire.org/svn/ipfire/trunk@333 ea5c0bd1-69bd-2848-81d8-4f18e57aeed8
This commit is contained in:
ms
2006-10-30 20:23:28 +00:00
parent c66941dd94
commit a6316ce423
208 changed files with 154048 additions and 102 deletions

View File

@@ -26,6 +26,8 @@
include Config
VER = ipfire
THISAPP = boot-$(VERSION).img
TARGET = $(DIR_INFO)/$(THISAPP)
@@ -62,7 +64,7 @@ $(TARGET) :
sed -e 's/boot IPFire/boot IPFire $(VERSION)/' $(DIR_SRC)/config/kernel/install-message \
> /install/mnt/message; \
cp $(DIR_SRC)/config/kernel/syslinux.cfg /install/mnt/syslinux.cfg; \
cp /boot/vmlinuz-installer /install/mnt/vmlinuz; \
cp /boot/vmlinuz-$(KVER) /install/mnt/vmlinuz; \
cp /install/images/fdinitrd.gz /install/mnt/instroot.gz; \
umount /install/mnt; \
losetup -d $$LOOPDEV; \

View File

@@ -18,12 +18,6 @@
# Makefiles are based on LFSMake, which is #
# Copyright (C) 2002 Rod Roard <rod@sunsetsystems.com> #
# #
# Modifications by: #
# ??-12-2003 Mark Wormgoor < mark@wormgoor.com> #
# - Modified Makefile for IPCop build #
# #
# $Id: driver.img,v 1.24.2.7 2006/01/29 20:17:30 franck78 Exp $
# #
###############################################################################
###############################################################################
@@ -32,6 +26,8 @@
include Config
VER = ipfire
THISAPP = driver-$(VERSION).img
TARGET = $(DIR_INFO)/$(THISAPP)
@@ -57,9 +53,7 @@ $(TARGET) :
# make new dependencies
depmod -a -F /boot/System.map-$(KVER) $(KVER)
if [ "$(MACHINE)" = "i386" ]; then \
depmod -a -F /boot/System.map-$(KVER)-smp $(KVER)-smp; \
fi
depmod -a -F /boot/System.map-$(KVER)-smp $(KVER)-smp
# Create drivers floppy
cd /tmp && rm -rf drivers.tgz drivers.tar bin lib etc var
@@ -100,19 +94,15 @@ $(TARGET) :
cd /tmp && tar xf drivers.tar
cd /tmp && mkdir -p {bin,etc/pcmcia,var/lib/pcmcia,var/run}
cd /tmp && cp -aR /install/misc/bin/* bin
cd /tmp && cp -r /etc/pcmcia/{config*,net*} etc/pcmcia
# cd /tmp && cp -r /etc/pcmcia/{config*,net*} etc/pcmcia
# cardmgr wants to execute these to bring up the card, we'll
# create blank ones as we'll bring them up ourselves
cd /tmp/etc/pcmcia && rm -f network
cd /tmp/etc/pcmcia && touch network
cd /tmp/etc/pcmcia && chmod +x network
# cd /tmp/etc/pcmcia && rm -f network
# cd /tmp/etc/pcmcia && touch network
# cd /tmp/etc/pcmcia && chmod +x network
cd /tmp && tar -cf - bin/ etc/pcmcia var lib/modules/$(KVER) | gzip -9 -c > drivers.tgz
if [ "$(MACHINE)" = "alpha" ]; then \
cp /tmp/drivers.tgz /install/images/drivers-$(VERSION).img; \
else \
dd if=/tmp/drivers.tgz of=/install/images/drivers-$(VERSION).img bs=1440k count=1 conv=sync; \
fi
dd if=/tmp/drivers.tgz of=/install/images/drivers-$(VERSION).img bs=2880k count=1 conv=sync
rm -rf /tmp/drivers.tgz /tmp/drivers.tar /tmp/bin /tmp/lib
### If this fails, the disk is TOO FULL !!!!

View File

@@ -18,12 +18,6 @@
# Makefiles are based on LFSMake, which is #
# Copyright (C) 2002 Rod Roard <rod@sunsetsystems.com> #
# #
# Modifications by: #
# ??-12-2003 Mark Wormgoor < mark@wormgoor.com> #
# - Modified Makefile for IPCop build #
# #
# $Id: initrd,v 1.26.2.8 2005/12/03 21:28:44 franck78 Exp $
# #
###############################################################################
###############################################################################
@@ -32,6 +26,8 @@
include Config
VER = ipfire
THISAPP = initrd
DIR_APP = $(DIR_SRC)/$(THISAPP)
TARGET = $(DIR_INFO)/$(THISAPP)
@@ -62,41 +58,34 @@ $(TARGET) :
# Finish up initrd directory
-mkdir -p /install/initrd/{etc,lib/modules/$(KVER)/kernel/drivers,cdrom,dev,harddisk,proc,tmp,usr/share/terminfo/l,var/run} && \
ln -sf /bin /install/initrd/sbin
cd /install/initrd/dev && /dev/make_devices
# cd /install/initrd/dev && /dev/make_devices
cp -aRf $(DIR_SRC)/config/install/* /install/initrd/etc/
rm -rf /install/initrd/etc/CVS/
cd /install/initrd/dev && ln -sf fd0 floppy
chmod 755 /install/initrd/etc/halt /install/initrd/etc/rc
cp -f /usr/share/terminfo/l/linux /install/initrd/usr/share/terminfo/l
if [ "$(MACHINE)" = "alpha" ]; then \
tar cvzf /tmp/libc.tgz /usr/share/locale /lib/libc.* /lib/libc-* /lib/libdl* /lib/libnsl* /lib/libresolv* /lib/libutil* /lib/ld* /lib/libcrypt*; \
tar xvzf /tmp/libc.tgz -C /install/initrd; \
strip /install/initrd/lib/*; \
rm -f /tmp/libc.tgz; \
fi
# Extra modules
-mkdir -p /install/initrd/lib/modules/$(KVER)/kernel/drivers/scsi
cp -f /lib/modules/$(KVER)/kernel/drivers/scsi/{scsi_mod.o.gz,sd_mod.o.gz,sr_mod.o.gz} \
cp -f /lib/modules/$(KVER)/kernel/drivers/scsi/{scsi_mod.ko,sd_mod.ko,sr_mod.ko} \
/install/initrd/lib/modules/$(KVER)/kernel/drivers/scsi/
-mkdir -p /install/initrd/lib/modules/$(KVER)/kernel/drivers/usb/storage/
cp -f /lib/modules/$(KVER)/kernel/drivers/usb/storage/*.o.gz \
cp -f /lib/modules/$(KVER)/kernel/drivers/usb/storage/*.ko \
/install/initrd/lib/modules/$(KVER)/kernel/drivers/usb/storage/
-mkdir -p /install/initrd/lib/modules/$(KVER)/kernel/drivers/usb/host/
cp -f /lib/modules/$(KVER)/kernel/drivers/usb/host/{usb-*,ehci*} \
/lib/modules/$(KVER)/kernel/drivers/usb/hid.o.gz \
/lib/modules/$(KVER)/kernel/drivers/usb/*core.o.gz \
cp -f /lib/modules/$(KVER)/kernel/drivers/usb/host/ehci* \
/lib/modules/$(KVER)/kernel/drivers/usb/input/usbhid.ko \
/lib/modules/$(KVER)/kernel/drivers/usb/core/usbcore.ko \
/install/initrd/lib/modules/$(KVER)/kernel/drivers/usb/
-mkdir -p /install/initrd/lib/modules/$(KVER)/kernel/drivers/input
cp -f /lib/modules/$(KVER)/kernel/drivers/input/{input.o.gz,keybdev.o.gz} \
/install/initrd/lib/modules/$(KVER)/kernel/drivers/input/
# -mkdir -p /install/initrd/lib/modules/$(KVER)/kernel/drivers/input
# cp -f /lib/modules/$(KVER)/kernel/drivers/input/{input.ko,keybdev.ko} \
# /install/initrd/lib/modules/$(KVER)/kernel/drivers/input/
-mkdir -p /install/initrd/lib/modules/$(KVER)/kernel/drivers/pnp
cp -f /lib/modules/$(KVER)/kernel/drivers/pnp/* \
/install/initrd/lib/modules/$(KVER)/kernel/drivers/pnp/
# -mkdir -p /install/initrd/lib/modules/$(KVER)/kernel/drivers/pnp
# cp -f /lib/modules/$(KVER)/kernel/drivers/pnp/* \
# /install/initrd/lib/modules/$(KVER)/kernel/drivers/pnp/
cp -f /lib/modules/$(KVER)/modules.* /install/initrd/lib/modules/$(KVER)/

View File

@@ -18,12 +18,6 @@
# Makefiles are based on LFSMake, which is #
# Copyright (C) 2002 Rod Roard <rod@sunsetsystems.com> #
# #
# Modifications by: #
# ??-12-2003 Mark Wormgoor < mark@wormgoor.com> #
# - Modified Makefile for IPCop build #
# #
# $Id: installer,v 1.6.2.3 2005/02/05 15:38:15 gespinasse Exp $
# #
###############################################################################
###############################################################################
@@ -32,6 +26,8 @@
include Config
VER = ipfire
THISAPP = installer
DIR_APP = $(DIR_SRC)/$(THISAPP)
TARGET = $(DIR_INFO)/$(THISAPP)

View File

@@ -18,12 +18,6 @@
# Makefiles are based on LFSMake, which is #
# Copyright (C) 2002 Rod Roard <rod@sunsetsystems.com> #
# #
# Modifications by: #
# ??-12-2003 Mark Wormgoor < mark@wormgoor.com> #
# - Modified Makefile for IPCop build #
# #
# $Id: newt,v 1.8.2.3 2005/02/05 15:38:15 gespinasse Exp $
# #
###############################################################################
###############################################################################
@@ -36,7 +30,7 @@ VER = 0.50.17
THISAPP = newt-utf8_$(VER)
DL_FILE = $(THISAPP).orig.tar.gz
DL_FROM = $(URL_DEBIAN)/n/newt-utf8
DL_FROM = $(URL_IPFIRE)
DIR_APP = $(DIR_SRC)/newt-0.50.17
ifeq "$(LFS_PASS)" "install"
TARGET = $(DIR_INFO)/$(THISAPP)-install

View File

@@ -81,7 +81,7 @@ $(TARGET) : $(patsubst %,$(DIR_DL)/%,$(objects))
ifeq "$(LFS_PASS)" "install"
cd $(DIR_APP)/lib && CFLAGS="-Os -fomit-frame-pointer" ./configure
cd $(DIR_APP)/lib && CFLAGS="-Os -fomit-frame-pointer" make
cd $(DIR_APP)/lib && CFLAGS="-Os -fomit-frame-pointer" make $(MAKETUNING)
-mkdir -p /install/include/pci
cd $(DIR_APP) && install -m 0644 lib/libpci.a /install/lib
cd $(DIR_APP) && install -m 0644 lib/{config,header,pci}.h /install/include/pci

View File

@@ -30,7 +30,7 @@ VER = 014
THISAPP = pcmciautils-$(VER)
DL_FILE = $(THISAPP).tar.bz2
DL_FROM = $(URL_SFNET)/pcmcia-cs
DL_FROM = $(URL_IPFIRE)
DIR_APP = $(DIR_SRC)/$(THISAPP)
ifeq "$(LFS_PASS)" "install"
TARGET = $(DIR_INFO)/$(THISAPP)-install
@@ -76,22 +76,17 @@ $(subst %,%_MD5,$(objects)) :
$(TARGET) : $(patsubst %,$(DIR_DL)/%,$(objects))
@$(PREBUILD)
@rm -rf $(DIR_APP) && cd $(DIR_SRC) && tar jxf $(DIR_DL)/$(DL_FILE)
cd $(DIR_APP) && make #$(MAKETUNING)
cd $(DIR_APP) && make install
## This is saved...
#ifeq "$(LFS_PASS)" "install"
# cd $(DIR_APP) && ./Configure -n --kernel=/usr/src/linux --notrust --cardbus --pnp --apm --nox11 --srctree --ucc=gcc --kcc="$(KGCC)"
ifeq "$(LFS_PASS)" "install"
# cd $(DIR_APP) && make -C cardmgr
# cd $(DIR_APP) && mkdir -p /install/misc/bin
# cd $(DIR_APP) && install -s -m 0755 cardmgr/cardmgr /install/misc/bin
# cd $(DIR_APP) && install -s -m 0755 cardmgr/cardctl /install/misc/bin
#else
# cd $(DIR_APP) && ./Configure -n --kernel=/usr/src/linux --notrust --cardbus --pnp --apm --nox11 --srctree --ucc=gcc --kcc="$(KGCC)"
# cd $(DIR_APP) && make all
# cd $(DIR_APP) && make install
#
# # Install our own extra pcmcia configs
# cp $(DIR_SRC)/src/pcmcia/*.conf /etc/pcmcia
#endif
else
cd $(DIR_APP) && make
cd $(DIR_APP) && make install
# Install our own extra pcmcia configs
cp $(DIR_SRC)/src/pcmcia/*.conf /etc/pcmcia
endif
@rm -rf $(DIR_APP)
@$(POSTBUILD)

View File

@@ -18,12 +18,6 @@
# Makefiles are based on LFSMake, which is #
# Copyright (C) 2002 Rod Roard <rod@sunsetsystems.com> #
# #
# Modifications by: #
# ??-12-2003 Mark Wormgoor < mark@wormgoor.com> #
# - Modified Makefile for IPCop build #
# #
# $Id: scsi.img,v 1.19.2.4 2005/02/05 15:38:15 gespinasse Exp $
# #
###############################################################################
###############################################################################
@@ -32,6 +26,8 @@
include Config
VER = ipfire
THISAPP = scsi-$(VERSION).img
TARGET = $(DIR_INFO)/$(THISAPP)
@@ -58,24 +54,20 @@ $(TARGET) :
-mkdir -p /install/images
cd /tmp && rm -rf scsi.tgz scsi.tar bin etc lib var
cd / && tar -cf /tmp/scsi.tar lib/modules/$(KVER)/kernel/drivers/{scsi,pcmcia,message/fusion} lib/modules/$(KVER)/kernel/drivers/block/{DAC960.o.gz,cpqarray.o.gz,cciss.o.gz} lib/modules/$(KVER)/kernel/drivers/ide
cd / && tar -cf /tmp/scsi.tar lib/modules/$(KVER)/kernel/drivers/{scsi,pcmcia,message/fusion} lib/modules/$(KVER)/kernel/drivers/block/{DAC960.ko,cpqarray.ko,cciss.ko} lib/modules/$(KVER)/kernel/drivers/ide
cd /tmp && tar xf scsi.tar
cd /tmp && rm -f lib/modules/$(KVER)/kernel/drivers/message/fusion/mptlan*
cd /tmp && mkdir -p {bin,etc/pcmcia/scsi,var/lib/pcmcia,var/run}
cd /tmp && cp -aR /install/misc/bin/* bin
cd /tmp && cp -r /etc/pcmcia/{config*,scsi*} etc/pcmcia/scsi
# cd /tmp && cp -r /etc/pcmcia/{config*,scsi*} etc/pcmcia/scsi
# cardmgr wants to execute these to bring up the card, we'll
# create blank ones as we'll bring them up ourselves
cd /tmp/etc/pcmcia/scsi && rm -f scsi
cd /tmp/etc/pcmcia/scsi && touch scsi
cd /tmp/etc/pcmcia/scsi && chmod +x scsi
# cd /tmp/etc/pcmcia/scsi && rm -f scsi
# cd /tmp/etc/pcmcia/scsi && touch scsi
# cd /tmp/etc/pcmcia/scsi && chmod +x scsi
cd /tmp && tar -cf - bin/ etc/pcmcia var lib/modules/$(KVER) | gzip -9 -c > scsi.tgz
if [ "$(MACHINE)" = "alpha" ]; then \
cp /tmp/scsi.tgz /install/images/scsidrv-$(VERSION).img; \
else \
dd if=/tmp/scsi.tgz of=/install/images/scsidrv-$(VERSION).img bs=2880k count=1 conv=sync; \
fi
dd if=/tmp/scsi.tgz of=/install/images/scsidrv-$(VERSION).img bs=2880k count=1 conv=sync
rm -f /tmp/scsi.tgz
### If this fails, the disk is TOO FULL !!!!

View File

@@ -78,16 +78,15 @@ $(TARGET) : $(patsubst %,$(DIR_DL)/%,$(objects))
@rm -rf $(DIR_APP) && cd $(DIR_SRC) && tar jxf $(DIR_DL)/$(DL_FILE)
ifeq "$(LFS_PASS)" "install"
-mkdir -p /install/lib
cd $(DIR_APP) && sed -i -e 's/libslang.a:/libslang.a:\ $$(OBJS)/' Makefile
cd $(DIR_APP) && CFLAGS="-Os -fomit-frame-pointer -Wall -fPIC" make -e libslang.a
cd $(DIR_APP) && install -m 0644 libslang.a /install/lib
-mkdir -p /install/include/slang
cd $(DIR_APP) && install -m 0644 slang.h slcurses.h /install/include/slang
cd $(DIR_APP) && ./configure --prefix=""
cd $(DIR_APP) && make $(MAKETUNING) elf
cd $(DIR_APP)/src && make $(MAKETUNING) install-elf DESTDIR="/opt/$(MACHINE)-uClibc"
rm -vf /opt/$(MACHINE)-uClibc/lib/libslang.so*
else
cd $(DIR_APP) && ./configure --prefix=/usr --sysconfdir=/etc
cd $(DIR_APP) && make
cd $(DIR_APP) && make elf
cd $(DIR_APP) && make install-elf
cd $(DIR_APP) && make $(MAKETUNING)
cd $(DIR_APP) && make elf $(MAKETUNING)
cd $(DIR_APP) && make install-elf $(MAKETUNING)
cd $(DIR_APP) && chmod -v 755 /usr/lib/libslang.so.2.0.6
endif
@rm -rf $(DIR_APP)

View File

@@ -36,7 +36,11 @@ DIR_APP = $(DIR_SRC)/$(THISAPP)
# Normal build or /tools build.
#
ifeq "$(ROOT)" ""
ifeq "$(LFS_PASS)" "install"
TARGET = $(DIR_INFO)/$(THISAPP)-install
else
TARGET = $(DIR_INFO)/$(THISAPP)
endif
else
TARGET = $(DIR_INFO)/$(THISAPP)-tools
endif
@@ -80,6 +84,16 @@ $(TARGET) : $(patsubst %,$(DIR_DL)/%,$(objects))
@$(PREBUILD)
@rm -rf $(DIR_APP) && cd $(DIR_SRC) && tar jxf $(DIR_DL)/$(DL_FILE)
ifeq "$(ROOT)" ""
ifeq "$(LFS_PASS)" "install"
cd $(DIR_APP) && CFLAGS="-Os -fomit-frame-pointer" ./configure
cd $(DIR_APP) && echo "HAVE_SLANG=yes" >> make_include
cd $(DIR_APP) && echo "SLANGFLAGS=-I/opt/$(MACHINE)-uClibc/include/slang" >> make_include
cd $(DIR_APP)/fdisk && make cfdisk
cd $(DIR_APP)/fdisk && install -m 0755 cfdisk /install/initrd/bin
cd $(DIR_APP)/disk-utils && make LDFLAGS=-static mkfs.minix fsck.minix
cd $(DIR_APP)/disk-utils && install -m 0755 mkfs.minix /sbin/mkfs.minix.static
cd $(DIR_APP)/disk-utils && install -m 0755 fsck.minix /sbin/fsck.minix.static
else
cd $(DIR_APP) && sed -i 's@etc/adjtime@var/lib/hwclock/adjtime@g' \
hwclock/hwclock.c
-mkdir -p /var/lib/hwclock
@@ -87,6 +101,7 @@ ifeq "$(ROOT)" ""
cd $(DIR_APP) && ./configure
cd $(DIR_APP) && make $(MAKETUNING) HAVE_KILL=yes HAVE_SLN=yes
cd $(DIR_APP) && make HAVE_KILL=yes HAVE_SLN=yes install
endif
else
cd $(DIR_APP) && sed -i 's@/usr/include@/tools/include@g' configure
cd $(DIR_APP) && ./configure

14
make.sh
View File

@@ -551,21 +551,23 @@ buildinstaller() {
installmake sysvinit
installmake e2fsprogs
installmake misc-progs
exiterror STOP HERE!
ipfiremake syslinux
ipfiremake as86
ipfiremake mbr
installmake sysfsutils
# installmake hwinfo
installmake slang
installmake util-linux
installmake newt
installmake pciutils
installmake pcmcia-cs
installmake kbd
installmake pcmciautils
installmake installer
installmake scsi.img
installmake driver.img
installmake initrd
installmake boot.img
exiterror STOP HERE!
ipfiremake syslinux
ipfiremake as86
ipfiremake mbr
installmake kbd
}
buildpackages() {

341
src/hwinfo/COPYING Normal file
View File

@@ -0,0 +1,341 @@
----------------------------------------------------------------------
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
675 Mass Ave, Cambridge, MA 02139, USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Library General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) 19yy <name of author>
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 2 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, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) 19yy name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Library General
Public License instead of this License.

1956
src/hwinfo/ChangeLog Normal file

File diff suppressed because it is too large Load Diff

95
src/hwinfo/Makefile Normal file
View File

@@ -0,0 +1,95 @@
TOPDIR = $(CURDIR)
SUBDIRS = src
TARGETS = hwinfo hwscan hwscand hwscanqueue
CLEANFILES = hwinfo hwinfo.static hwscan hwscan.static hwscand hwscanqueue doc/libhd doc/*~
LIBDIR = /lib
ULIBDIR = /usr$(LIBDIR)
LIBS = -lhd
SLIBS = -lhd -lsysfs
TLIBS = -lhd_tiny -lsysfs
SO_LIBS = -lsysfs
TSO_LIBS = -lsysfs
export SO_LIBS
include Makefile.common
SHARED_FLAGS =
OBJS_NO_TINY = names.o parallel.o modem.o
.PHONY: fullstatic static shared tiny doc diet tinydiet uc tinyuc
hwscan: hwscan.o $(LIBHD)
$(CC) hwscan.o $(LDFLAGS) $(LIBS) -o $@
hwinfo: hwinfo.o $(LIBHD)
$(CC) hwinfo.o $(LDFLAGS) $(LIBS) -o $@
hwscand: hwscand.o
$(CC) $< $(LDFLAGS) -o $@
hwscanqueue: hwscanqueue.o
$(CC) $< $(LDFLAGS) -o $@
# kept for compatibility
shared:
@make
tiny:
@make EXTRA_FLAGS=-DLIBHD_TINY LIBHD_BASE=libhd_tiny LIBS="$(TLIBS)" SO_LIBS="$(TSO_LIBS)"
tinyinstall:
@make EXTRA_FLAGS=-DLIBHD_TINY LIBHD_BASE=libhd_tiny LIBS="$(TLIBS)" SO_LIBS="$(TSO_LIBS)" install
tinystatic:
@make EXTRA_FLAGS=-DLIBHD_TINY LIBHD_BASE=libhd_tiny SHARED_FLAGS= LIBS="$(TLIBS)" SO_LIBS="$(TSO_LIBS)"
tinystaticinstall:
@make EXTRA_FLAGS=-DLIBHD_TINY LIBHD_BASE=libhd_tiny SHARED_FLAGS= LIBS="$(TLIBS)" SO_LIBS="$(TSO_LIBS)" install
diet:
@make CC="diet gcc" EXTRA_FLAGS="-fno-pic -DDIET" SHARED_FLAGS= LIBS="$(SLIBS)"
tinydiet:
@make CC="diet gcc" EXTRA_FLAGS="-fno-pic -DLIBHD_TINY -DDIET" SHARED_FLAGS= LIBS="$(SLIBS)"
uc:
@make CC="/opt/i386-linux-uclibc/bin/i386-uclibc-gcc" EXTRA_FLAGS="-fno-pic -DUCLIBC" SHARED_FLAGS= LIBS="$(SLIBS)"
tinyuc:
@make CC="/opt/i386-linux-uclibc/usr/bin/gcc" EXTRA_FLAGS="-fno-pic -DLIBHD_TINY -DUCLIBC" SHARED_FLAGS= LIBS="$(SLIBS)"
static:
make SHARED_FLAGS= LIBS="$(SLIBS)"
fullstatic: static
$(CC) -static hwinfo.o $(LDFLAGS) $(SLIBS) -o hwinfo.static
$(CC) -static hwscan.o $(LDFLAGS) $(SLIBS) -o hwscan.static
strip -R .note -R .comment hwinfo.static
strip -R .note -R .comment hwscan.static
doc:
@cd doc ; doxygen libhd.doxy
install:
install -d -m 755 $(DESTDIR)/sbin $(DESTDIR)/usr/sbin $(DESTDIR)$(LIBDIR) $(DESTDIR)$(ULIBDIR)\
$(DESTDIR)/usr/include $(DESTDIR)/etc/init.d
install -m 755 hwinfo $(DESTDIR)/usr/sbin
install -m 755 hwscan hwscand hwscanqueue $(DESTDIR)/sbin
install -m 755 -s src/ids/check_hd $(DESTDIR)/usr/sbin
install -m 755 src/ids/convert_hd $(DESTDIR)/usr/sbin
if [ -f $(LIBHD_SO) ] ; then \
install $(LIBHD_SO) $(DESTDIR)$(LIBDIR) ; \
ln -snf $(LIBHD_NAME) $(DESTDIR)$(LIBDIR)/$(LIBHD_SONAME) ; \
ln -snf $(LIBDIR)/$(LIBHD_SONAME) $(DESTDIR)$(ULIBDIR)/$(LIBHD_BASE).so ; \
else \
install -m 644 $(LIBHD) $(DESTDIR)$(ULIBDIR) ; \
fi
install -m 644 src/hd/hd.h $(DESTDIR)/usr/include
install -m 755 hwbootscan getsysinfo gen-hwcfg-disk.sh $(DESTDIR)/usr/sbin
install -m 755 hwbootscan.rc $(DESTDIR)/etc/init.d/hwscan
install -m 755 src/isdn/cdb/mk_isdnhwdb $(DESTDIR)/usr/sbin
install -d -m 755 $(DESTDIR)/usr/share/hwinfo
install -m 644 src/isdn/cdb/ISDN.CDB.txt $(DESTDIR)/usr/share/hwinfo
install -m 644 src/isdn/cdb/ISDN.CDB.hwdb $(DESTDIR)/usr/share/hwinfo

View File

@@ -0,0 +1,66 @@
# libhd/Makefile.common
ARCH := $(shell uname -m)
ifeq "$(ARCH)" "i486"
ARCH := i386
endif
ifeq "$(ARCH)" "i586"
ARCH := i386
endif
ifeq "$(ARCH)" "i686"
ARCH := i386
endif
ifeq "$(ARCH)" "parisc"
EXTRA_FLAGS := -fPIC $(EXTRA_FLAGS)
endif
LIBHD_VERSION := $(shell cat $(TOPDIR)/VERSION)
LIBHD_MINOR_VERSION := $(shell cut -d . -f 2 $(TOPDIR)/VERSION)
LIBHD_MAJOR_VERSION := $(shell cut -d . -f 1 $(TOPDIR)/VERSION)
CC = gcc
LD = ld
CFLAGS = -Wall -O2 -pipe -g $(SHARED_FLAGS) $(EXTRA_FLAGS) -I/opt/i586-uClibc/include -I/opt/i586-uClibc/usr/include -I$(TOPDIR)/src/hd
SHARED_FLAGS = -fPIC
LDFLAGS = -Lsrc
CFILES = $(wildcard *.c)
OBJS = $(CFILES:.c=.o)
LIBHD_BASE = libhd
LIBHD = $(TOPDIR)/src/$(LIBHD_BASE).a
LIBHD_SONAME = $(LIBHD_BASE).so.$(LIBHD_MAJOR_VERSION)
LIBHD_NAME = $(LIBHD_BASE).so.$(LIBHD_VERSION)
LIBHD_SO = $(TOPDIR)/src/$(LIBHD_NAME)
LIBHD_D = $(TOPDIR)/src/.lib
export CC TOPDIR CFLAGS LIBHD ARCH
.PHONY: all distclean clean install subdirs
%.o: %.c
$(CC) -c $(CFLAGS) $<
all: subdirs $(TARGETS)
install: all
ifneq "$(SUBDIRS)" ""
subdirs:
@for i in $(SUBDIRS) ; do make -C $$i $(MAKECMDGOALS) || exit ; done
endif
clean: subdirs
@rm -rf $(OBJS) .depend $(CLEANFILES) *~
distclean: subdirs
@rm -rf $(OBJS) .depend $(CLEANFILES) $(DISTCLEANFILES) *~
ifneq "$(CFILES)" ""
ifeq ($(findstring $(MAKECMDGOALS), clean distclean),)
.depend: $(CFILES)
@$(CC) -MG -MM $(CFLAGS) $(CFILES) >$@
-include .depend
endif
endif

149
src/hwinfo/README Normal file
View File

@@ -0,0 +1,149 @@
1. Usage
========
hwinfo [debug=deb_flag] [log=log_file] [list[+]=hw_item] [[+|-]probe_option1] [[+|-]probe_option2] ...
Examples:
hwinfo
- probes for nearly everything
hwinfo +all
- probes for everything
hwinfo log=hw_log
- default probing, output is written to hw_log
*** Please don't use "hwinfo >some_log 2>&1" to store the output into a
log file! ***
hwinfo -all +ide
- probe for ide drives only
hwinfo +all -isapnp -floppy
- probe for everything *except* isapnp and floppies
Some probing flags do not stand for complete modules but enable additional
features; e.g. "pci.range" or "cdrom.info".
Example:
hwinfo -all +cdrom
gives a list of all cdrom's
hwinfo -all +cdrom.info
additionally reads the iso9660 info
To get a list of all supported probing flags, call 'hwinfo -all'.
2. Environment variables/kernel cmdline parameters
==================================================
You can control the hardware probing using the environment variable
"hwprobe" and the kernel cmdline parameters "hwprobe" & "x11".
If "hwprobe" is set on the kernel cmdline, the environment variable
"hwprobe" is ignored. Otherwise, the meaning of both is exactly the same.
x11
- Controls the X server/X version to prefer. It is either "3" or "4" or the
name of the X server/X server module to use (XF3: server name without
the leading "XF86_", XF4: the server module name).
Examples:
x11=3
o prefer XFree86 3.x over 4.x (if possible)
x11=SVGA
o use the XF86_SVGA server (*** Even if the server does not
support the card! ***)
x11=nv
o use the XF4 nv_drv.o driver (*** Even if the module does not
support the card! ***)
hwprobe
- Controls which probing flags should *always* be set/cleared. (These
settings *cannot* be overridden by command line switches.)
Examples:
hwprobe=-isapnp
o *never* do any isapnp probing
hwprobe=-braille,-modem
o don't look for braille displays & modems
- Allows you to add and remove hardware from the probing results. In this case
the syntax is (-: remove, +: add at end of list, <nothing>: add at begin of
list):
hwprobe=[+-]<device_class>:<vendor_id>:<device_id>[:<unix_device_file>]
<device_class>, <vendor_id> and <device_id> are device ids as used by libhd.
See the output of hwinfo for examples. In connection with "-", you can use
"*" as a placeholder that matches every id.
Note: <unix_device_file> is optional.
Note2: you cannot usefully *add* hardware that needs more info than that
given by the hwprobe entry. Disks & floppies are notable examples.
(But you can *remove* them.)
Here is a typical hwinfo output for a mouse, with the relevant ids
underlined (<device_class> is the combined base_class & sub_class),
[see 1st example below]:
14: PS/2 00.0: 10500 PS/2 Mouse
^^^^^ --> <device_class>
[Created at mouse.110]
Vendor: s0200 "Unknown"
^^^^^ --> <vendor_id>
Model: 0002 "Generic PS/2 Mouse"
^^^^ --> <device_id>
Device File: /dev/psaux
^^^^^^^^^^ --> <unix_device_file>
Driver Info #0:
XFree86 Protocol: ps/2
GPM Protocol: ps2
Attached to: #8 (PS/2 Controller)
Examples:
hwprobe=+10500:s200:2:/dev/psaux
o add a ps/2 mouse [at the end of the hardware list]
hwprobe=10500:s200:2:/dev/psaux
o add a ps/2 mouse [at the start of the hardware list, so it
is our default mouse]
hwprobe=+10b00:s5001:0:/dev/ttyS0
o add a braille display connected to /dev/ttyS0
hwprobe=-10500:s200:2:/dev/psaux
o remove ps/2 mice attached to /dev/psaux
hwprobe=-10500:s200:2
o remove all ps/2 mice
hwprobe=-10500:*:*
o remove all ps/2 mice
hwprobe=-*:*:*:/dev/hdc
o remove /dev/hdc
hwprobe=+401:1274:5000
o add an ensoniq sound card
Grafics cards are are slightly trickier:
hwprobe=+300:1014:b7
o add a Fire GL1 card
Note: this way you'll get a multihead config. You'll probably
rather want the following example.
hwprobe=-300:*:*,+300:1014:b7
o remove all graphics cards; then add a Fire GL1 card
hwprobe=+400:121a:1
o add a 3fx voodoo card (Note the class "400", not "300"!)
- for more ids, see "src/ids/names.*" and "src/ids/drivers.*"

1
src/hwinfo/VERSION Normal file
View File

@@ -0,0 +1 @@
10.16

26
src/hwinfo/doc/example1.c Normal file
View File

@@ -0,0 +1,26 @@
#include <stdio.h>
#include <stdlib.h>
#include <hd.h>
int main(int argc, char **argv)
{
hd_data_t *hd_data;
hd_t *hd;
hd_data = calloc(1, sizeof *hd_data);
hd = hd_list(hd_data, hw_scsi, 1, NULL);
for(; hd; hd = hd->next) {
hd_dump_entry(hd_data, hd, stdout)
}
hd_free_hd_list(hd); /* free it */
hd_free_hd_data(hd_data);
free(hd_data);
return 0;
}

26
src/hwinfo/doc/example2.c Normal file
View File

@@ -0,0 +1,26 @@
#include <stdio.h>
#include <stdlib.h>
#include <hd.h>
int main(int argc, char **argv)
{
hd_data_t *hd_data;
hd_t *hd;
unsigned display_idx;
hd_data = calloc(1, sizeof *hd_data);
hd = hd_list(hd_data, hw_display, 1, NULL);
display_idx = hd_display_adapter(hd_data);
hd_dump_entry(hd_data, hd_get_device_by_idx(hd_data, display_idx), stdout)
hd_free_hd_list(hd);
hd_free_hd_data(hd_data);
free(hd_data);
return 0;
}

View File

@@ -0,0 +1 @@
</body></html>

92
src/hwinfo/doc/hwinfo.8 Normal file
View File

@@ -0,0 +1,92 @@
.\" Michal Svec <msvec@suse.cz>
.\"
.\" Process this file with
.\" groff -man -Tascii foo.1
.\"
.\"
.TH HWINFO 8 "January 2003" "hwinfo" "System configuration"
.\"
.\"
.SH NAME
hwinfo \- probe for hardware
.\"
.\"
.SH SYNOPSIS
.B hwinfo [
.I options
.B ]
.\"
.\"
.SH DESCRIPTION
.B hwinfo
is used to probe for the hardware present in the system. It can be used
to generate a system overview log which can be later used for support.
.\"
.\"
.SH OPTIONS
.\"
.TP
.BI --debug " " level
Set debug
.B level.
The debug info is shown only in the log file. If you specify a log file,
the debug level is implicitly set to a reasonable value.
.\"
.TP
.BI --dump-db " " n
Dump hardware data base,
.B n
is either
.B 0
for the external data base, or
.B 1
for the internal data base.
.\"
.TP
.BI --help
Print a usage and exit.
.\"
.TP
.BI --log " " logfile
Write info to
.B logfile.
.\"
.TP
.BI --short
Just a short listing.
.\"
.TP
.BI --version
Show libhd version.
.\"
.TP
.BI --<hwitem>
Probe for the particular hardware item. Available hardware items are:
.B all, bios, block, bluetooth, braille, bridge, camera, cdrom, chipcard, cpu,
.B disk, dsl, dvb, floppy, framebuffer, gfxcard, hub, ide, isapnp, isdn,
.B joystick, keyboard, memory, modem, monitor, mouse, netcard, network,
.B partition, pci, pcmcia, pcmcia-ctrl, pppoe, printer, scanner, scsi, smp,
.B sound, storage-ctrl, sys, tape, tv, usb, usb-ctrl, vbe, wlan,
and
.B zip.
.\"
.\"
.SH FILES
.B /var/lib/hardware/*
.\"
.\"
.SH BUGS
Not all hardware can be detected.
.\"
.\"
.SH AUTHOR
.nf
Steffen Winterfeldt <snwint@suse.de> - hwinfo
Michal Svec <msvec@suse.cz> - manual page
.fi
.\"
.\"
.SH "SEE ALSO"
Documentation in /usr/share/doc/packages/hwinfo.
.\"
.\" EOF

109
src/hwinfo/doc/libhd.doc Normal file
View File

@@ -0,0 +1,109 @@
/*! \mainpage libhd documentation
<h2>Introduction</h2>
libhd is a hardware detection lib.
<h2>Changes</h2>
\ref libhd_5_12
<h2>Examples</h2>
\ref example1
\ref example2
*/
/*! \page examples Examples
\ref example1
\ref example2
<hr>
\subsection example1 Get list of SCSI controllers
\include example1.c
<hr>
\subsection example2 Get primary display controller
\include example2.c
*/
/*! \page changes Changes
\ref libhd_5_12
<hr>
\subsection libhd_5_12 libhd-5.12
<ul>
<li>changes in \ref hd_t
<ul>
<li>\ref hd_t::bus "bus" is now a struct, use \ref hd_t::bus "bus.id" instead.
<li>\ref hd_t::base_class "base_class" is now a struct, use \ref hd_t::base_class "base_class.id" instead.
<li>\ref hd_t::sub_class "sub_class" is now a struct, use \ref hd_t::sub_class "sub_class.id" instead.
<li>\ref hd_t::prog_if "prog_if" is now a struct, use \ref hd_t::prog_if "prog_if.id" instead.
<li>\ref hd_t::vendor "vendor" is a struct replacing vend and vend_name.
Use \ref hd_t::vendor "vendor.id" and \ref hd_t::vendor "vendor.name" now.
<li>\ref hd_t::device "device" is a struct replacing dev and dev_name.
Use \ref hd_t::device "device.id" and \ref hd_t::device "device.name" now.
<li>\ref hd_t::sub_vendor "sub_vendor" is a struct replacing sub_vend and sub_vend_name.
Use \ref hd_t::sub_vendor "sub_vendor.id" and \ref hd_t::sub_vendor "sub_vendor.name" now.
<li>\ref hd_t::sub_device "sub_device" is a struct replacing sub_dev and sub_dev_name.
Use \ref hd_t::sub_device "sub_device.id" and \ref hd_t::sub_device "sub_device.name" now.
<li>\ref hd_t::revision "revision" is a struct replacing rev and rev_name.
Use \ref hd_t::revision "revision.id" and \ref hd_t::revision "revision.name" now.
<li>\ref hd_t::compat_vendor "compat_vendor" is a struct replacing compat_vend.
Use \ref hd_t::compat_vendor "compat_vendor.id" now.
<li>\ref hd_t::compat_device "compat_device" is a struct replacing compat_dev.
Use \ref hd_t::compat_device "compat_device.id" now.
</ul>
<li>interface functions removed
<ul>
<li>hd_bus_name is gone. Use \ref hd_t::bus "bus.name" instead.
<li>hd_class_name is gone. Use \ref hd_t::base_class "base_class.name",
\ref hd_t::sub_class "sub_class.name" or \ref hd_t::prog_if "prog_if.name" instead.
<li>hd_vendor_name is gone. Use \ref hd_t::vendor "vendor.name" instead.
<li>hd_device_name is gone. Use \ref hd_t::device "device.name" instead.
<li>hd_sub_device_name is gone. Use \ref hd_t::sub_device "sub_device.name" instead.
<li>hd_find_device_by_name is gone.
</ul>
</ul>
<hr>
*/

898
src/hwinfo/doc/libhd.doxy Normal file
View File

@@ -0,0 +1,898 @@
# Doxyfile 1.2.13.1
# This file describes the settings to be used by the documentation system
# doxygen (www.doxygen.org) for a project
#
# All text after a hash (#) is considered a comment and will be ignored
# The format is:
# TAG = value [value, ...]
# For lists items can also be appended using:
# TAG += value [value, ...]
# Values that contain spaces should be placed between quotes (" ")
#---------------------------------------------------------------------------
# General configuration options
#---------------------------------------------------------------------------
# The PROJECT_NAME tag is a single word (or a sequence of words surrounded
# by quotes) that should identify the project.
PROJECT_NAME = libhd
# The PROJECT_NUMBER tag can be used to enter a project or revision number.
# This could be handy for archiving the generated documentation or
# if some version control system is used.
PROJECT_NUMBER = 5.0
# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
# base path where the generated documentation will be put.
# If a relative path is entered, it will be relative to the location
# where doxygen was started. If left blank the current directory will be used.
OUTPUT_DIRECTORY = libhd
# The OUTPUT_LANGUAGE tag is used to specify the language in which all
# documentation generated by doxygen is written. Doxygen will use this
# information to generate all constant output in the proper language.
# The default language is English, other supported languages are:
# Brazilian, Chinese, Croatian, Czech, Danish, Dutch, Finnish, French,
# German, Greek, Hungarian, Italian, Japanese, Korean, Norwegian, Polish,
# Portuguese, Romanian, Russian, Slovak, Slovene, Spanish and Swedish.
OUTPUT_LANGUAGE = English
# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in
# documentation are documented, even if no documentation was available.
# Private class members and static file members will be hidden unless
# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES
EXTRACT_ALL = YES
# If the EXTRACT_PRIVATE tag is set to YES all private members of a class
# will be included in the documentation.
EXTRACT_PRIVATE = NO
# If the EXTRACT_STATIC tag is set to YES all static members of a file
# will be included in the documentation.
EXTRACT_STATIC = YES
# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs)
# defined locally in source files will be included in the documentation.
# If set to NO only classes defined in header files are included.
EXTRACT_LOCAL_CLASSES = YES
# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all
# undocumented members of documented classes, files or namespaces.
# If set to NO (the default) these members will be included in the
# various overviews, but no documentation section is generated.
# This option has no effect if EXTRACT_ALL is enabled.
HIDE_UNDOC_MEMBERS = NO
# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all
# undocumented classes that are normally visible in the class hierarchy.
# If set to NO (the default) these class will be included in the various
# overviews. This option has no effect if EXTRACT_ALL is enabled.
HIDE_UNDOC_CLASSES = NO
# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will
# include brief member descriptions after the members that are listed in
# the file and class documentation (similar to JavaDoc).
# Set to NO to disable this.
BRIEF_MEMBER_DESC = YES
# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend
# the brief description of a member or function before the detailed description.
# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
# brief descriptions will be completely suppressed.
REPEAT_BRIEF = YES
# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
# Doxygen will generate a detailed section even if there is only a brief
# description.
ALWAYS_DETAILED_SEC = NO
# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all inherited
# members of a class in the documentation of that class as if those members were
# ordinary class members. Constructors, destructors and assignment operators of
# the base classes will not be shown.
INLINE_INHERITED_MEMB = NO
# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full
# path before files name in the file list and in the header files. If set
# to NO the shortest path that makes the file name unique will be used.
FULL_PATH_NAMES = NO
# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag
# can be used to strip a user defined part of the path. Stripping is
# only done if one of the specified strings matches the left-hand part of
# the path. It is allowed to use relative paths in the argument list.
STRIP_FROM_PATH =
# The INTERNAL_DOCS tag determines if documentation
# that is typed after a \internal command is included. If the tag is set
# to NO (the default) then the documentation will be excluded.
# Set it to YES to include the internal documentation.
INTERNAL_DOCS = NO
# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct
# doxygen to hide any special comment blocks from generated source code
# fragments. Normal C and C++ comments will always remain visible.
STRIP_CODE_COMMENTS = YES
# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate
# file names in lower case letters. If set to YES upper case letters are also
# allowed. This is useful if you have classes or files whose names only differ
# in case and if your file system supports case sensitive file names. Windows
# users are adviced to set this option to NO.
CASE_SENSE_NAMES = YES
# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter
# (but less readable) file names. This can be useful is your file systems
# doesn't support long names like on DOS, Mac, or CD-ROM.
SHORT_NAMES = NO
# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen
# will show members with their full class and namespace scopes in the
# documentation. If set to YES the scope will be hidden.
HIDE_SCOPE_NAMES = NO
# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen
# will generate a verbatim copy of the header file for each class for
# which an include is specified. Set to NO to disable this.
VERBATIM_HEADERS = YES
# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen
# will put list of the files that are included by a file in the documentation
# of that file.
SHOW_INCLUDE_FILES = YES
# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen
# will interpret the first line (until the first dot) of a JavaDoc-style
# comment as the brief description. If set to NO, the JavaDoc
# comments will behave just like the Qt-style comments (thus requiring an
# explict @brief command for a brief description.
JAVADOC_AUTOBRIEF = YES
# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented
# member inherits the documentation from any documented member that it
# reimplements.
INHERIT_DOCS = YES
# If the INLINE_INFO tag is set to YES (the default) then a tag [inline]
# is inserted in the documentation for inline members.
INLINE_INFO = YES
# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen
# will sort the (detailed) documentation of file and class members
# alphabetically by member name. If set to NO the members will appear in
# declaration order.
SORT_MEMBER_DOCS = YES
# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
# tag is set to YES, then doxygen will reuse the documentation of the first
# member in the group (if any) for the other members of the group. By default
# all members of a group must be documented explicitly.
DISTRIBUTE_GROUP_DOC = NO
# The TAB_SIZE tag can be used to set the number of spaces in a tab.
# Doxygen uses this value to replace tabs by spaces in code fragments.
TAB_SIZE = 8
# The GENERATE_TODOLIST tag can be used to enable (YES) or
# disable (NO) the todo list. This list is created by putting \todo
# commands in the documentation.
GENERATE_TODOLIST = YES
# The GENERATE_TESTLIST tag can be used to enable (YES) or
# disable (NO) the test list. This list is created by putting \test
# commands in the documentation.
GENERATE_TESTLIST = YES
# The GENERATE_BUGLIST tag can be used to enable (YES) or
# disable (NO) the bug list. This list is created by putting \bug
# commands in the documentation.
GENERATE_BUGLIST = YES
# This tag can be used to specify a number of aliases that acts
# as commands in the documentation. An alias has the form "name=value".
# For example adding "sideeffect=\par Side Effects:\n" will allow you to
# put the command \sideeffect (or @sideeffect) in the documentation, which
# will result in a user defined paragraph with heading "Side Effects:".
# You can put \n's in the value part of an alias to insert newlines.
ALIASES =
# The ENABLED_SECTIONS tag can be used to enable conditional
# documentation sections, marked by \if sectionname ... \endif.
ENABLED_SECTIONS =
# The MAX_INITIALIZER_LINES tag determines the maximum number of lines
# the initial value of a variable or define consist of for it to appear in
# the documentation. If the initializer consists of more lines than specified
# here it will be hidden. Use a value of 0 to hide initializers completely.
# The appearance of the initializer of individual variables and defines in the
# documentation can be controlled using \showinitializer or \hideinitializer
# command in the documentation regardless of this setting.
MAX_INITIALIZER_LINES = 30
# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources
# only. Doxygen will then generate output that is more tailored for C.
# For instance some of the names that are used will be different. The list
# of all members will be omitted, etc.
OPTIMIZE_OUTPUT_FOR_C = YES
# Set the SHOW_USED_FILES tag to NO to disable the list of files generated
# at the bottom of the documentation of classes and structs. If set to YES the
# list will mention the files that were used to generate the documentation.
SHOW_USED_FILES = YES
#---------------------------------------------------------------------------
# configuration options related to warning and progress messages
#---------------------------------------------------------------------------
# The QUIET tag can be used to turn on/off the messages that are generated
# by doxygen. Possible values are YES and NO. If left blank NO is used.
QUIET = NO
# The WARNINGS tag can be used to turn on/off the warning messages that are
# generated by doxygen. Possible values are YES and NO. If left blank
# NO is used.
WARNINGS = YES
# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings
# for undocumented members. If EXTRACT_ALL is set to YES then this flag will
# automatically be disabled.
WARN_IF_UNDOCUMENTED = YES
# The WARN_FORMAT tag determines the format of the warning messages that
# doxygen can produce. The string should contain the $file, $line, and $text
# tags, which will be replaced by the file and line number from which the
# warning originated and the warning text.
WARN_FORMAT =
# The WARN_LOGFILE tag can be used to specify a file to which warning
# and error messages should be written. If left blank the output is written
# to stderr.
WARN_LOGFILE =
#---------------------------------------------------------------------------
# configuration options related to the input files
#---------------------------------------------------------------------------
# The INPUT tag can be used to specify the files and/or directories that contain
# documented source files. You may enter file names like "myfile.cpp" or
# directories like "/usr/src/myproject". Separate the files or directories
# with spaces.
INPUT = libhd.doc ../src
# If the value of the INPUT tag contains directories, you can use the
# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
# and *.h) to filter out the source-files in the directories. If left
# blank the following patterns are tested:
# *.c *.cc *.cxx *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx *.hpp
# *.h++ *.idl
FILE_PATTERNS = *.c *.h
# The RECURSIVE tag can be used to turn specify whether or not subdirectories
# should be searched for input files as well. Possible values are YES and NO.
# If left blank NO is used.
RECURSIVE = YES
# The EXCLUDE tag can be used to specify files and/or directories that should
# excluded from the INPUT source files. This way you can easily exclude a
# subdirectory from a directory tree whose root is specified with the INPUT tag.
EXCLUDE = ../src/ids
# If the value of the INPUT tag contains directories, you can use the
# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
# certain files from those directories.
EXCLUDE_PATTERNS =
# The EXAMPLE_PATH tag can be used to specify one or more files or
# directories that contain example code fragments that are included (see
# the \include command).
EXAMPLE_PATH = .
# If the value of the EXAMPLE_PATH tag contains directories, you can use the
# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
# and *.h) to filter out the source-files in the directories. If left
# blank all files are included.
EXAMPLE_PATTERNS = *.c
# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
# searched for input files to be used with the \include or \dontinclude
# commands irrespective of the value of the RECURSIVE tag.
# Possible values are YES and NO. If left blank NO is used.
EXAMPLE_RECURSIVE = NO
# The IMAGE_PATH tag can be used to specify one or more files or
# directories that contain image that are included in the documentation (see
# the \image command).
IMAGE_PATH =
# The INPUT_FILTER tag can be used to specify a program that doxygen should
# invoke to filter for each input file. Doxygen will invoke the filter program
# by executing (via popen()) the command <filter> <input-file>, where <filter>
# is the value of the INPUT_FILTER tag, and <input-file> is the name of an
# input file. Doxygen will then use the output that the filter program writes
# to standard output.
INPUT_FILTER =
# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
# INPUT_FILTER) will be used to filter the input files when producing source
# files to browse.
FILTER_SOURCE_FILES = NO
#---------------------------------------------------------------------------
# configuration options related to source browsing
#---------------------------------------------------------------------------
# If the SOURCE_BROWSER tag is set to YES then a list of source files will
# be generated. Documented entities will be cross-referenced with these sources.
SOURCE_BROWSER = NO
# Setting the INLINE_SOURCES tag to YES will include the body
# of functions and classes directly in the documentation.
INLINE_SOURCES = NO
# If the REFERENCED_BY_RELATION tag is set to YES (the default)
# then for each documented function all documented
# functions referencing it will be listed.
REFERENCED_BY_RELATION = YES
# If the REFERENCES_RELATION tag is set to YES (the default)
# then for each documented function all documented entities
# called/used by that function will be listed.
REFERENCES_RELATION = YES
#---------------------------------------------------------------------------
# configuration options related to the alphabetical class index
#---------------------------------------------------------------------------
# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index
# of all compounds will be generated. Enable this if the project
# contains a lot of classes, structs, unions or interfaces.
ALPHABETICAL_INDEX = NO
# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then
# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns
# in which this list will be split (can be a number in the range [1..20])
COLS_IN_ALPHA_INDEX = 5
# In case all classes in a project start with a common prefix, all
# classes will be put under the same header in the alphabetical index.
# The IGNORE_PREFIX tag can be used to specify one or more prefixes that
# should be ignored while generating the index headers.
IGNORE_PREFIX =
#---------------------------------------------------------------------------
# configuration options related to the HTML output
#---------------------------------------------------------------------------
# If the GENERATE_HTML tag is set to YES (the default) Doxygen will
# generate HTML output.
GENERATE_HTML = YES
# The HTML_OUTPUT tag is used to specify where the HTML docs will be put.
# If a relative path is entered the value of OUTPUT_DIRECTORY will be
# put in front of it. If left blank `html' will be used as the default path.
HTML_OUTPUT =
# The HTML_HEADER tag can be used to specify a personal HTML header for
# each generated HTML page. If it is left blank doxygen will generate a
# standard header.
HTML_HEADER =
# The HTML_FOOTER tag can be used to specify a personal HTML footer for
# each generated HTML page. If it is left blank doxygen will generate a
# standard footer.
HTML_FOOTER = footer.html
# The HTML_STYLESHEET tag can be used to specify a user defined cascading
# style sheet that is used by each HTML page. It can be used to
# fine-tune the look of the HTML output. If the tag is left blank doxygen
# will generate a default style sheet
HTML_STYLESHEET =
# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes,
# files or namespaces will be aligned in HTML using tables. If set to
# NO a bullet list will be used.
HTML_ALIGN_MEMBERS = YES
# If the GENERATE_HTMLHELP tag is set to YES, additional index files
# will be generated that can be used as input for tools like the
# Microsoft HTML help workshop to generate a compressed HTML help file (.chm)
# of the generated HTML documentation.
GENERATE_HTMLHELP = NO
# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag
# controls if a separate .chi index file is generated (YES) or that
# it should be included in the master .chm file (NO).
GENERATE_CHI = NO
# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag
# controls whether a binary table of contents is generated (YES) or a
# normal table of contents (NO) in the .chm file.
BINARY_TOC = NO
# The TOC_EXPAND flag can be set to YES to add extra items for group members
# to the contents of the Html help documentation and to the tree view.
TOC_EXPAND = NO
# The DISABLE_INDEX tag can be used to turn on/off the condensed index at
# top of each HTML page. The value NO (the default) enables the index and
# the value YES disables it.
DISABLE_INDEX = NO
# This tag can be used to set the number of enum values (range [1..20])
# that doxygen will group on one line in the generated HTML documentation.
ENUM_VALUES_PER_LINE = 4
# If the GENERATE_TREEVIEW tag is set to YES, a side panel will be
# generated containing a tree-like index structure (just like the one that
# is generated for HTML Help). For this to work a browser that supports
# JavaScript and frames is required (for instance Mozilla, Netscape 4.0+,
# or Internet explorer 4.0+). Note that for large projects the tree generation
# can take a very long time. In such cases it is better to disable this feature.
# Windows users are probably better off using the HTML help feature.
GENERATE_TREEVIEW = NO
# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be
# used to set the initial width (in pixels) of the frame in which the tree
# is shown.
TREEVIEW_WIDTH = 250
#---------------------------------------------------------------------------
# configuration options related to the LaTeX output
#---------------------------------------------------------------------------
# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will
# generate Latex output.
GENERATE_LATEX = YES
# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put.
# If a relative path is entered the value of OUTPUT_DIRECTORY will be
# put in front of it. If left blank `latex' will be used as the default path.
LATEX_OUTPUT =
# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact
# LaTeX documents. This may be useful for small projects and may help to
# save some trees in general.
COMPACT_LATEX = NO
# The PAPER_TYPE tag can be used to set the paper type that is used
# by the printer. Possible values are: a4, a4wide, letter, legal and
# executive. If left blank a4wide will be used.
PAPER_TYPE = a4wide
# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX
# packages that should be included in the LaTeX output.
EXTRA_PACKAGES =
# The LATEX_HEADER tag can be used to specify a personal LaTeX header for
# the generated latex document. The header should contain everything until
# the first chapter. If it is left blank doxygen will generate a
# standard header. Notice: only use this tag if you know what you are doing!
LATEX_HEADER =
# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated
# is prepared for conversion to pdf (using ps2pdf). The pdf file will
# contain links (just like the HTML output) instead of page references
# This makes the output suitable for online browsing using a pdf viewer.
PDF_HYPERLINKS = NO
# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of
# plain latex in the generated Makefile. Set this option to YES to get a
# higher quality PDF documentation.
USE_PDFLATEX = NO
# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode.
# command to the generated LaTeX files. This will instruct LaTeX to keep
# running if errors occur, instead of asking the user for help.
# This option is also used when generating formulas in HTML.
LATEX_BATCHMODE = NO
#---------------------------------------------------------------------------
# configuration options related to the RTF output
#---------------------------------------------------------------------------
# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output
# The RTF output is optimised for Word 97 and may not look very pretty with
# other RTF readers or editors.
GENERATE_RTF = NO
# The RTF_OUTPUT tag is used to specify where the RTF docs will be put.
# If a relative path is entered the value of OUTPUT_DIRECTORY will be
# put in front of it. If left blank `rtf' will be used as the default path.
RTF_OUTPUT =
# If the COMPACT_RTF tag is set to YES Doxygen generates more compact
# RTF documents. This may be useful for small projects and may help to
# save some trees in general.
COMPACT_RTF = NO
# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated
# will contain hyperlink fields. The RTF file will
# contain links (just like the HTML output) instead of page references.
# This makes the output suitable for online browsing using WORD or other
# programs which support those fields.
# Note: wordpad (write) and others do not support links.
RTF_HYPERLINKS = NO
# Load stylesheet definitions from file. Syntax is similar to doxygen's
# config file, i.e. a series of assigments. You only have to provide
# replacements, missing definitions are set to their default value.
RTF_STYLESHEET_FILE =
# Set optional variables used in the generation of an rtf document.
# Syntax is similar to doxygen's config file.
RTF_EXTENSIONS_FILE =
#---------------------------------------------------------------------------
# configuration options related to the man page output
#---------------------------------------------------------------------------
# If the GENERATE_MAN tag is set to YES (the default) Doxygen will
# generate man pages
GENERATE_MAN = NO
# The MAN_OUTPUT tag is used to specify where the man pages will be put.
# If a relative path is entered the value of OUTPUT_DIRECTORY will be
# put in front of it. If left blank `man' will be used as the default path.
MAN_OUTPUT =
# The MAN_EXTENSION tag determines the extension that is added to
# the generated man pages (default is the subroutine's section .3)
MAN_EXTENSION =
# If the MAN_LINKS tag is set to YES and Doxygen generates man output,
# then it will generate one additional man file for each entity
# documented in the real man page(s). These additional files
# only source the real man page, but without them the man command
# would be unable to find the correct page. The default is NO.
MAN_LINKS = NO
#---------------------------------------------------------------------------
# configuration options related to the XML output
#---------------------------------------------------------------------------
# If the GENERATE_XML tag is set to YES Doxygen will
# generate an XML file that captures the structure of
# the code including all documentation. Note that this
# feature is still experimental and incomplete at the
# moment.
GENERATE_XML = NO
#---------------------------------------------------------------------------
# configuration options for the AutoGen Definitions output
#---------------------------------------------------------------------------
# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will
# generate an AutoGen Definitions (see autogen.sf.net) file
# that captures the structure of the code including all
# documentation. Note that this feature is still experimental
# and incomplete at the moment.
GENERATE_AUTOGEN_DEF = NO
#---------------------------------------------------------------------------
# Configuration options related to the preprocessor
#---------------------------------------------------------------------------
# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will
# evaluate all C-preprocessor directives found in the sources and include
# files.
ENABLE_PREPROCESSING = YES
# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro
# names in the source code. If set to NO (the default) only conditional
# compilation will be performed. Macro expansion can be done in a controlled
# way by setting EXPAND_ONLY_PREDEF to YES.
MACRO_EXPANSION = NO
# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES
# then the macro expansion is limited to the macros specified with the
# PREDEFINED and EXPAND_AS_PREDEFINED tags.
EXPAND_ONLY_PREDEF = NO
# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files
# in the INCLUDE_PATH (see below) will be search if a #include is found.
SEARCH_INCLUDES = YES
# The INCLUDE_PATH tag can be used to specify one or more directories that
# contain include files that are not input files but should be processed by
# the preprocessor.
INCLUDE_PATH =
# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
# patterns (like *.h and *.hpp) to filter out the header-files in the
# directories. If left blank, the patterns specified with FILE_PATTERNS will
# be used.
INCLUDE_FILE_PATTERNS =
# The PREDEFINED tag can be used to specify one or more macro names that
# are defined before the preprocessor is started (similar to the -D option of
# gcc). The argument of the tag is a list of macros of the form: name
# or name=definition (no spaces). If the definition and the = are
# omitted =1 is assumed.
PREDEFINED =
# If the MACRO_EXPANSION and EXPAND_PREDEF_ONLY tags are set to YES then
# this tag can be used to specify a list of macro names that should be expanded.
# The macro definition that is found in the sources will be used.
# Use the PREDEFINED tag if you want to use a different macro definition.
EXPAND_AS_DEFINED =
# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then
# doxygen's preprocessor will remove all function-like macros that are alone
# on a line and do not end with a semicolon. Such function macros are typically
# used for boiler-plate code, and will confuse the parser if not removed.
SKIP_FUNCTION_MACROS = YES
#---------------------------------------------------------------------------
# Configuration::addtions related to external references
#---------------------------------------------------------------------------
# The TAGFILES tag can be used to specify one or more tagfiles.
TAGFILES =
# When a file name is specified after GENERATE_TAGFILE, doxygen will create
# a tag file that is based on the input files it reads.
GENERATE_TAGFILE =
# If the ALLEXTERNALS tag is set to YES all external classes will be listed
# in the class index. If set to NO only the inherited external classes
# will be listed.
ALLEXTERNALS = NO
# The PERL_PATH should be the absolute path and name of the perl script
# interpreter (i.e. the result of `which perl').
PERL_PATH =
#---------------------------------------------------------------------------
# Configuration options related to the dot tool
#---------------------------------------------------------------------------
# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will
# generate a inheritance diagram (in Html, RTF and LaTeX) for classes with base or
# super classes. Setting the tag to NO turns the diagrams off. Note that this
# option is superceded by the HAVE_DOT option below. This is only a fallback. It is
# recommended to install and use dot, since it yield more powerful graphs.
CLASS_DIAGRAMS = YES
# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
# available from the path. This tool is part of Graphviz, a graph visualization
# toolkit from AT&T and Lucent Bell Labs. The other options in this section
# have no effect if this option is set to NO (the default)
HAVE_DOT = NO
# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen
# will generate a graph for each documented class showing the direct and
# indirect inheritance relations. Setting this tag to YES will force the
# the CLASS_DIAGRAMS tag to NO.
CLASS_GRAPH = YES
# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen
# will generate a graph for each documented class showing the direct and
# indirect implementation dependencies (inheritance, containment, and
# class references variables) of the class with other documented classes.
COLLABORATION_GRAPH = YES
# If set to YES, the inheritance and collaboration graphs will show the
# relations between templates and their instances.
TEMPLATE_RELATIONS = YES
# If set to YES, the inheritance and collaboration graphs will hide
# inheritance and usage relations if the target is undocumented
# or is not a class.
HIDE_UNDOC_RELATIONS = YES
# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT
# tags are set to YES then doxygen will generate a graph for each documented
# file showing the direct and indirect include dependencies of the file with
# other documented files.
INCLUDE_GRAPH = YES
# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and
# HAVE_DOT tags are set to YES then doxygen will generate a graph for each
# documented header file showing the documented files that directly or
# indirectly include this file.
INCLUDED_BY_GRAPH = YES
# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen
# will graphical hierarchy of all classes instead of a textual one.
GRAPHICAL_HIERARCHY = YES
# The tag DOT_PATH can be used to specify the path where the dot tool can be
# found. If left blank, it is assumed the dot tool can be found on the path.
DOT_PATH =
# The DOTFILE_DIRS tag can be used to specify one or more directories that
# contain dot files that are included in the documentation (see the
# \dotfile command).
DOTFILE_DIRS =
# The MAX_DOT_GRAPH_WIDTH tag can be used to set the maximum allowed width
# (in pixels) of the graphs generated by dot. If a graph becomes larger than
# this value, doxygen will try to truncate the graph, so that it fits within
# the specified constraint. Beware that most browsers cannot cope with very
# large images.
MAX_DOT_GRAPH_WIDTH = 1024
# The MAX_DOT_GRAPH_HEIGHT tag can be used to set the maximum allows height
# (in pixels) of the graphs generated by dot. If a graph becomes larger than
# this value, doxygen will try to truncate the graph, so that it fits within
# the specified constraint. Beware that most browsers cannot cope with very
# large images.
MAX_DOT_GRAPH_HEIGHT = 1024
# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will
# generate a legend page explaining the meaning of the various boxes and
# arrows in the dot generated graphs.
GENERATE_LEGEND = YES
# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will
# remove the intermedate dot files that are used to generate
# the various graphs.
DOT_CLEANUP = YES
#---------------------------------------------------------------------------
# Configuration::addtions related to the search engine
#---------------------------------------------------------------------------
# The SEARCHENGINE tag specifies whether or not a search engine should be
# used. If set to NO the values of all tags below this one will be ignored.
SEARCHENGINE = NO
# The CGI_NAME tag should be the name of the CGI script that
# starts the search engine (doxysearch) with the correct parameters.
# A script with this name will be generated by doxygen.
CGI_NAME =
# The CGI_URL tag should be the absolute URL to the directory where the
# cgi binaries are located. See the documentation of your http daemon for
# details.
CGI_URL =
# The DOC_URL tag should be the absolute URL to the directory where the
# documentation is located. If left blank the absolute path to the
# documentation, with file:// prepended to it, will be used.
DOC_URL =
# The DOC_ABSPATH tag should be the absolute path to the directory where the
# documentation is located. If left blank the directory on the local machine
# will be used.
DOC_ABSPATH =
# The BIN_ABSPATH tag must point to the directory where the doxysearch binary
# is installed.
BIN_ABSPATH =
# The EXT_DOC_PATHS tag can be used to specify one or more paths to
# documentation generated for other projects. This allows doxysearch to search
# the documentation for these projects as well.
EXT_DOC_PATHS =

50
src/hwinfo/gen-hwcfg-disk.sh Executable file
View File

@@ -0,0 +1,50 @@
#!/bin/bash
#
# gen-hwcfg-disk.sh
#
# Generates hwcfg file for all configured disks
#
if [ -x /sbin/ata_identify ]; then
ATA_ID=/sbin/ata_identify
elif [ -x /lib/klibc/bin/ata_identify ]; then
ATA_ID=/lib/klibc/bin/ata_identify
else
echo "ata_identify not found, please install udev"
exit 1
fi
hwcfg=/etc/sysconfig/hardware
if [ ! -d "$hwcfg" ]; then
echo "No hardware configuration directory found"
exit 1
fi
# IDE disks first
for ifname in /sys/block/hd*; do
id=$($ATA_ID /dev/${ifname##*/} 2> /dev/null)
if [ $? -eq 0 ]; then
filename="SATA_$id"
echo "Generate hwcfg file for $filename"
echo "DEVICE=${ifname##*/}" > ${hwcfg}/hwcfg-disk-id-${filename}
fi
done
# SCSI disks next
for ifname in /sys/block/sd*; do
if [ -d $ifname/device ]; then
read vendor < $ifname/device/vendor
if [ "$vendor" = "ATA" ]; then
# We need page 0x80 to get the serial number
page="-p 0x80"
else
page=
fi
scsi_id -g $page -s ${ifname#/sys} 2> /dev/null | while read vendor model serial; do
filename="${vendor}_${model}_${serial}"
echo "Generate hwcfg file for $filename"
echo "DEVICE=${ifname##*/}" > ${hwcfg}/hwcfg-disk-id-${filename}
done
fi
done

77
src/hwinfo/getsysinfo Executable file
View File

@@ -0,0 +1,77 @@
#! /bin/sh
if [ "$1" ] ; then
cat <<EOF
Usage: getsysinfo
Collect some system data that are useful for debugging
hardware detection bugs.
EOF
exit 0
fi
# collect some system data
dir=`mktemp -d /tmp/getsysinfo.XXXXXXXXXX`
[ -d "$dir" ] || exit 1
host=`hostname`
[ "$host" ] || host=xxx
mkdir -p "$dir/$host"
for i in \
/proc/bus/input \
/proc/cpuinfo \
/proc/device-tree \
/proc/devices \
/proc/dma \
/proc/driver/nvram \
/proc/fb \
/proc/iSeries \
/proc/ide \
/proc/interrupts \
/proc/iomem \
/proc/ioports \
/proc/meminfo \
/proc/modules \
/proc/net/dev \
/proc/partitions \
/proc/scsi \
/proc/sys/dev/cdrom/info \
/proc/sys/dev/parport \
/proc/tty \
/proc/version \
/sys \
/var/log/boot.msg
do
if [ -e "$i" ] ; then
echo "$i"
cp -a --parents "$i" "$dir/$host" 2>/dev/null
chmod -R u+w,a+r,a+X "$dir/$host"
fi
done
echo /proc/mounts
cp --parents /proc/mounts "$dir/$host"
echo -e "\n------ dmesg start ------\n" >>"$dir/$host/var/log/boot.msg"
dmesg >>"$dir/$host/var/log/boot.msg"
file="$host.tar.gz"
tar -C "$dir" -zcf "$dir/$file" "$host"
rm -f "/tmp/$file"
if [ -e "/tmp/$file" ] ; then
echo "Warning: /tmp/$file exists, no info written"\!
rm -rf "$dir"
exit 1
fi
ln -nf "$dir/$file" "/tmp/$file"
rm -rf "$dir"
echo -e "\nSystem data written to: /tmp/$file"

15
src/hwinfo/hwbootscan Normal file
View File

@@ -0,0 +1,15 @@
#!/bin/bash
rm -f /var/lib/hardware/LOCK
/sbin/hwscan --silent --boot --fast --isapnp --pci --block --floppy --mouse
#
# create icons for static drives
#
if [ -e /etc/hotplug/hotplug.subfs.functions ]; then
. /etc/hotplug/hotplug.subfs.functions
coldplug_create_subfs
fi
exit 0

101
src/hwinfo/hwbootscan.rc Normal file
View File

@@ -0,0 +1,101 @@
#! /bin/sh
# Copyright (c) 2002 SuSE GmbH Nuernberg, Germany. All rights reserved.
#
# Author: Marcus Meissner <meissner@suse.de>
#
# /etc/init.d/hwscan
#
# System startup script for boot hw probing and reconfiguration
#
### BEGIN INIT INFO
# Provides: hwscan
# Required-Start:
# X-UnitedLinux-Should-Start: hotplug kbd
# Required-Stop:
# Default-Start: 2 3 5
# Default-Stop:
# Description: Hardware scan and reconfiguration on boot.
### END INIT INFO
HWBOOTSCAN_BIN=/usr/sbin/hwbootscan
test -x $HWBOOTSCAN_BIN || exit 5
# Shell functions sourced from /etc/rc.status:
# rc_check check and set local and overall rc status
# rc_status check and set local and overall rc status
# rc_status -v ditto but be verbose in local rc status
# rc_status -v -r ditto and clear the local rc status
# rc_failed set local and overall rc status to failed
# rc_reset clear local rc status (overall remains)
# rc_exit exit appropriate to overall rc status
. /etc/rc.status
# First reset status of this service
rc_reset
# Return values acc. to LSB for all commands but status:
# 0 - success
# 1 - misc error
# 2 - invalid or excess args
# 3 - unimplemented feature (e.g. reload)
# 4 - insufficient privilege
# 5 - program not installed
# 6 - program not configured
# 7 - program is not running
#
# Note that starting an already running service, stopping
# or restarting a not-running service as well as the restart
# with force-reload (in case signalling is not supported) are
# considered a success.
case "$1" in
start)
echo -n "Starting hardware scan on boot"
rc_splash "YaST"
[ -n "$REDIRECT" ] && exec 0<> $REDIRECT 1>&0 2>&0
$HWBOOTSCAN_BIN
rc_check
rc_status -v
;;
stop)
rc_check
;;
restart)
## Stop the service and regardless of whether it was
## running or not, start it again.
# Remember status and be quiet
rc_check
;;
force-reload)
## Signal the daemon to reload its config. Most daemons
## do this on signal 1 (SIGHUP).
## If it does not support it, restart.
# Remember status and be quiet
rc_check
;;
reload)
## Like force-reload, but if daemon does not support
## signalling, do nothing (!)
# If it supports signalling:
rc_reset
;;
status)
## Check status with checkproc(8), if process is running
## checkproc will return with exit status 0.
# Status has a slightly different for the status command:
# 0 - service running
# 1 - service dead, but /var/run/ pid file exists
# 2 - service dead, but /var/lock/ lock file exists
# 3 - service not running
rc_reset
;;
*)
echo "Usage: $0 {start|stop|restart|force-reload|reload|status}"
exit 1
;;
esac
rc_exit

2103
src/hwinfo/hwinfo.c Normal file

File diff suppressed because it is too large Load Diff

625
src/hwinfo/hwscan.c Normal file
View File

@@ -0,0 +1,625 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <getopt.h>
#include "hd.h"
#include "hd_int.h"
struct option options[] = {
{ "help", 0, NULL, 'h' },
{ "verbose", 0, NULL, 'v' },
{ "version", 0, NULL, 400 },
{ "show", 1, NULL, 500 },
{ "list", 0, NULL, 501 },
{ "cfg", 1, NULL, 502 },
{ "avail", 1, NULL, 503 },
{ "need", 1, NULL, 504 },
{ "new", 0, NULL, 505 },
{ "fast", 0, NULL, 506 },
{ "silent", 0, NULL, 507 },
{ "boot", 0, NULL, 508 },
{ "active", 1, NULL, 509 },
{ "only", 1, NULL, 510 },
{ "sys", 0, NULL, 1000 + hw_sys },
{ "cpu", 0, NULL, 1000 + hw_cpu },
{ "keyboard", 0, NULL, 1000 + hw_keyboard },
{ "braille", 0, NULL, 1000 + hw_braille },
{ "mouse", 0, NULL, 1000 + hw_mouse },
{ "joystick", 0, NULL, 1000 + hw_joystick },
{ "printer", 0, NULL, 1000 + hw_printer },
{ "scanner", 0, NULL, 1000 + hw_scanner },
{ "chipcard", 0, NULL, 1000 + hw_chipcard },
{ "monitor", 0, NULL, 1000 + hw_monitor },
{ "tv", 0, NULL, 1000 + hw_tv },
{ "gfxcard", 0, NULL, 1000 + hw_display },
{ "framebuffer", 0, NULL, 1000 + hw_framebuffer },
{ "camera", 0, NULL, 1000 + hw_camera },
{ "sound", 0, NULL, 1000 + hw_sound },
{ "storage-ctrl", 0, NULL, 1000 + hw_storage_ctrl },
{ "storage_ctrl", 0, NULL, 1000 + hw_storage_ctrl },
{ "netcard", 0, NULL, 1000 + hw_network_ctrl },
{ "network-ctrl", 0, NULL, 1000 + hw_network_ctrl },
{ "network_ctrl", 0, NULL, 1000 + hw_network_ctrl },
{ "isdn", 0, NULL, 1000 + hw_isdn },
{ "modem", 0, NULL, 1000 + hw_modem },
{ "network", 0, NULL, 1000 + hw_network },
{ "disk", 0, NULL, 1000 + hw_disk },
{ "partition", 0, NULL, 1000 + hw_partition },
{ "cdrom", 0, NULL, 1000 + hw_cdrom },
{ "floppy", 0, NULL, 1000 + hw_floppy },
{ "update", 0, NULL, 1000 + hw_manual },
{ "usb-ctrl", 0, NULL, 1000 + hw_usb_ctrl },
{ "usb_ctrl", 0, NULL, 1000 + hw_usb_ctrl },
{ "usb", 0, NULL, 1000 + hw_usb },
{ "bios", 0, NULL, 1000 + hw_bios },
{ "pci", 0, NULL, 1000 + hw_pci },
{ "isapnp", 0, NULL, 1000 + hw_isapnp },
{ "bridge", 0, NULL, 1000 + hw_bridge },
{ "hub", 0, NULL, 1000 + hw_hub },
{ "scsi", 0, NULL, 1000 + hw_scsi },
{ "ide", 0, NULL, 1000 + hw_ide },
{ "memory", 0, NULL, 1000 + hw_memory },
{ "dvb", 0, NULL, 1000 + hw_dvb },
{ "pcmcia", 0, NULL, 1000 + hw_pcmcia },
{ "pcmcia_ctrl", 0, NULL, 1000 + hw_pcmcia_ctrl },
{ "ieee1394", 0, NULL, 1000 + hw_ieee1394 },
{ "firewire", 0, NULL, 1000 + hw_ieee1394 },
{ "ieee1394_ctrl", 0, NULL, 1000 + hw_ieee1394_ctrl },
{ "firewire_ctrl", 0, NULL, 1000 + hw_ieee1394_ctrl },
{ "hotplug", 0, NULL, 1000 + hw_hotplug },
{ "hotplug_ctrl", 0, NULL, 1000 + hw_hotplug_ctrl },
{ "zip", 0, NULL, 1000 + hw_zip },
{ "pppoe", 0, NULL, 1000 + hw_pppoe },
{ "dsl", 0, NULL, 1000 + hw_dsl },
{ "wlan", 0, NULL, 1000 + hw_wlan },
{ "block", 0, NULL, 1000 + hw_block },
{ "tape", 0, NULL, 1000 + hw_tape },
{ "vbe", 0, NULL, 1000 + hw_vbe },
{ "bluetooth", 0, NULL, 1000 + hw_bluetooth },
{ "all", 0, NULL, 1000 + hw_all },
{ }
};
int verbose = 0;
hd_hw_item_t scan_item[100] = { };
unsigned scan_items = 0;
int found_items = 0;
struct {
unsigned show:1;
unsigned scan:1;
unsigned list:1;
unsigned config_cfg:1;
unsigned config_avail:1;
unsigned config_need:1;
unsigned config_active:1;
unsigned new:1;
unsigned fast:1;
unsigned silent:1;
unsigned boot:1;
str_list_t *only;
} opt;
void help(void);
int do_scan(hd_hw_item_t *items);
int do_show(char *id);
int do_list(hd_hw_item_t *items);
int do_config(int type, char *val, char *id);
int fast_ok(hd_hw_item_t *items);
int has_item(hd_hw_item_t *items, hd_hw_item_t item);
int has_hw_class(hd_t *hd, hd_hw_item_t *items);
int main(int argc, char **argv)
{
int rc = 0;
#ifndef LIBHD_TINY
char *id = NULL;
char *config_cfg = NULL;
char *config_avail = NULL;
char *config_need = NULL;
char *config_active = NULL;
int i;
int ok = 0;
FILE *f;
opterr = 0;
while((i = getopt_long(argc, argv, "hv", options, NULL)) != -1) {
switch(i) {
case 'v':
verbose++;
break;
case 400:
printf("%s\n", hd_version());
ok = 1;
break;
case 500:
opt.show = 1;
id = optarg;
break;
case 501:
opt.list = 1;
break;
case 502:
opt.config_cfg = 1;
config_cfg = optarg;
break;
case 503:
opt.config_avail = 1;
config_avail = optarg;
break;
case 504:
opt.config_need = 1;
config_need = optarg;
break;
case 505:
opt.new = 1;
break;
case 506:
opt.fast = 1;
break;
case 507:
opt.silent = 1;
break;
case 508:
opt.boot = 1;
break;
case 509:
opt.config_active = 1;
config_active = optarg;
break;
case 510:
if(*optarg) add_str_list(&opt.only, optarg);
break;
case 1000 ... 1100:
opt.scan = 1;
if(scan_items + 1 < sizeof scan_item / sizeof *scan_item) {
scan_item[scan_items++] = i - 1000;
}
break;
default:
help();
return 1;
}
}
scan_item[scan_items] = 0;
if(opt.scan && !opt.list) {
if(argv[optind] || !scan_items) return help(), 1;
rc = do_scan(scan_item);
if(found_items) {
unlink(HARDWARE_DIR "/.update"); /* the old file */
unlink(HARDWARE_UNIQUE_KEYS "/.update"); /* so we trigger a rescan */
if((f = fopen(HARDWARE_UNIQUE_KEYS "/.update", "a"))) fclose(f);
}
ok = 1;
}
if(opt.show) {
do_show(id);
ok = 1;
}
if(opt.list) {
do_list(scan_item);
ok = 1;
}
if(opt.config_cfg) {
if(!argv[optind]) return help(), 1;
do_config(1, config_cfg, argv[optind]);
ok = 1;
}
if(opt.config_avail) {
if(!argv[optind]) return help(), 1;
do_config(2, config_avail, argv[optind]);
ok = 1;
}
if(opt.config_need) {
if(!argv[optind]) return help(), 1;
do_config(3, config_need, argv[optind]);
ok = 1;
}
if(opt.config_active) {
if(!argv[optind]) return help(), 1;
do_config(4, config_active, argv[optind]);
ok = 1;
}
if(!ok) help();
#endif /* !defined(LIBHD_TINY) */
return rc;
}
void help()
{
fprintf(stderr,
"Usage: hwscan [options]\n"
"Show information about currently known hardware.\n"
" --list show list of known hardware\n"
" --version show libhd version\n"
" --silent don't show hardware config changes\n"
" --boot run only if we haven't been disabled via 'hwprobe=-scan'\n"
" --cfg=state id change 'configured' status; id is one of the\n"
" ids from 'hwscan --list'\n"
" state is one of new, no, yes\n"
" --avail=state id change 'available' status\n"
" --need=state id change 'needed' status\n"
" --active=state id change 'active' status\n"
" --hw_item probe for hw_item and update status info\n"
" hw_item is one of:\n"
" all, bios, block, bluetooth, braille, bridge, camera, cdrom, chipcard, cpu,\n"
" disk, dsl, dvb, floppy, framebuffer, gfxcard, hub, ide, isapnp, isdn,\n"
" joystick, keyboard, memory, modem, monitor, mouse, netcard, network,\n"
" partition, pci, pcmcia, pcmcia-ctrl, pppoe, printer, scanner, scsi, smp,\n"
" sound, storage-ctrl, sys, tape, tv, usb, usb-ctrl, vbe, wlan, zip\n"
);
}
#ifndef LIBHD_TINY
int do_scan(hd_hw_item_t *items)
{
int run_config = 0;
hd_status_t status = { };
hd_data_t *hd_data;
hd_t *hd, *hd1;
int err = 0;
if(opt.fast) opt.fast = fast_ok(items);
hd_data = calloc(1, sizeof *hd_data);
if(opt.boot) {
/* look if we have been disabled */
hd_clear_probe_feature(hd_data, pr_all);
hd_scan(hd_data);
hd_set_probe_feature(hd_data, pr_scan);
if(!hd_probe_feature(hd_data, pr_scan)) {
hd_free_hd_data(hd_data);
free(hd_data);
return 0;
}
}
hd_data->only = opt.only;
opt.only = NULL;
hd_data->flags.list_all = 1;
hd_data->flags.fast = opt.fast;
hd = hd_list2(hd_data, items, 1);
if(hd) found_items = 1;
for(hd1 = hd; hd1; hd1 = hd1->next) {
err = hd_write_config(hd_data, hd1);
if(verbose >= 2) {
printf(
"write=%d %s: (cfg=%s, avail=%s, need=%s, active=%s",
err,
hd1->unique_id,
hd_status_value_name(hd1->status.configured),
hd_status_value_name(hd1->status.available),
hd_status_value_name(hd1->status.needed),
hd_status_value_name(hd1->status.active)
);
if(hd1->unix_dev_name) {
printf(", dev=%s", hd1->unix_dev_name);
}
printf(
") %s\n",
hd1->model
);
}
if(err) break;
}
if(err) {
fprintf(stderr,
"Error writing configuration for %s (%s)\n",
hd1->unique_id,
hd1->model
);
exit(1);
}
hd = hd_free_hd_list(hd);
if(opt.new) {
status.configured = status_new;
}
else {
status.reconfig = status_yes;
}
hd = hd_list_with_status2(hd_data, items, status);
if(hd) run_config = 1;
if(verbose) {
for(hd1 = hd; hd1; hd1 = hd1->next) {
printf(
"%s: (cfg=%s, avail=%s, need=%s, active=%s",
hd1->unique_id,
hd_status_value_name(hd1->status.configured),
hd_status_value_name(hd1->status.available),
hd_status_value_name(hd1->status.needed),
hd_status_value_name(hd1->status.active)
);
if(hd1->unix_dev_name) {
printf(", dev=%s", hd1->unix_dev_name);
}
printf(
") %s\n",
hd1->model
);
}
}
else if(!opt.silent) {
for(hd1 = hd; hd1; hd1 = hd1->next) printf("%s\n", hd1->unique_id);
}
hd = hd_free_hd_list(hd);
hd_free_hd_data(hd_data);
free(hd_data);
return run_config ^ 1;
}
int do_show(char *id)
{
hd_data_t *hd_data;
hd_t *hd;
hd_data = calloc(1, sizeof *hd_data);
if ( id[0] == '/' ){
int nr=0;
char *_id = 0;
hd_t *hd_manual;
hd_manual = hd_list(hd_data, hw_manual, 1, NULL);
for(hd = hd_manual; hd; hd = hd->next) {
if(hd->status.available != status_yes) continue;
if(!search_str_list(hd->unix_dev_names, id)) continue;
_id = hd->unique_id;
nr++;
}
if ( nr == 1 ) /* > 1 means our database is not okay */
hd = hd_read_config(hd_data, _id);
}else
hd = hd_read_config(hd_data, id);
if(hd) {
hd_data->debug = -1;
hd_dump_entry(hd_data, hd, stdout);
hd = hd_free_hd_list(hd);
}
else {
printf("no such hardware item: %s\n", id);
}
hd_free_hd_data(hd_data);
free(hd_data);
return 0;
}
int do_list(hd_hw_item_t *items)
{
hd_data_t *hd_data;
hd_t *hd, *hd_manual;
char *s;
char status[64];
int i;
hd_data = calloc(1, sizeof *hd_data);
hd_manual = hd_list(hd_data, hw_manual, 1, NULL);
for(hd = hd_manual; hd; hd = hd->next) {
if(opt.scan && ! has_hw_class(hd, items)) continue;
strcpy(status, "(");
i = 0;
if(hd->status.configured && (s = hd_status_value_name(hd->status.configured))) {
sprintf(status + strlen(status), "%scfg=%s", i ? ", " : "", s);
i++;
}
if(hd->status.available && (s = hd_status_value_name(hd->status.available))) {
sprintf(status + strlen(status), "%savail=%s", i ? ", " : "", s);
i++;
}
if(hd->status.needed && (s = hd_status_value_name(hd->status.needed))) {
sprintf(status + strlen(status), "%sneed=%s", i ? ", " : "", s);
i++;
}
if(hd->status.active && (s = hd_status_value_name(hd->status.active))) {
sprintf(status + strlen(status), "%sactive=%s", i ? ", " : "", s);
i++;
}
strcat(status, ")");
s = hd_hw_item_name(hd->hw_class);
if(!s) s = "???";
printf("%s: %-32s %-16s %s\n", hd->unique_id, status, s, hd->model);
if(hd->config_string) {
printf(" configured as: \"%s\"\n", hd->config_string);
}
}
hd_free_hd_list(hd_manual);
hd_free_hd_data(hd_data);
free(hd_data);
return 0;
}
int do_config(int type, char *val, char *id)
{
hd_data_t *hd_data;
hd_t *hd;
hd_status_value_t status = 0;
int i;
char *s;
hd_data = calloc(1, sizeof *hd_data);
if ( id[0] == '/' ){
int nr=0;
char *_id = 0;
hd_t *hd_manual;
hd_manual = hd_list(hd_data, hw_manual, 1, NULL);
for(hd = hd_manual; hd; hd = hd->next) {
if(hd->status.available != status_yes) continue;
if(!search_str_list(hd->unix_dev_names, id)) continue;
_id = hd->unique_id;
nr++;
}
if ( nr == 1 )
hd = hd_read_config(hd_data, _id);
}else
hd = hd_read_config(hd_data, id);
if(hd) {
for(i = 1; i < 8; i++) {
s = hd_status_value_name(i);
if(s && !strcmp(val, s)) {
status = i;
break;
}
}
if(!status) {
printf("invalid status: %s\n", val);
}
else {
switch(type) {
case 1:
hd->status.configured = status;
break;
case 2:
hd->status.available = status;
break;
case 3:
hd->status.needed = status;
break;
case 4:
hd->status.active = status;
break;
}
hd_write_config(hd_data, hd);
}
hd = hd_free_hd_list(hd);
}
else {
printf("no such hardware item: %s\n", id);
}
hd_free_hd_data(hd_data);
free(hd_data);
return 0;
}
/*
* Check whether a 'fast' scan would suffice to re-check the presence
* of all known hardware.
*/
int fast_ok(hd_hw_item_t *items)
{
hd_data_t *hd_data;
hd_t *hd, *hd1;
int ok = 1;
if(!has_item(items, hw_mouse) && !has_item(items, hw_storage_ctrl)) {
return 1;
}
hd_data = calloc(1, sizeof *hd_data);
hd_data->flags.list_all = 1;
hd = hd_list(hd_data, hw_manual, 1, NULL);
for(hd1 = hd; hd1; hd1 = hd1->next) {
/* serial mice */
if(hd1->hw_class == hw_mouse && hd1->bus.id == bus_serial) {
ok = 0;
break;
}
/* parallel zip */
if(hd1->hw_class == hw_storage_ctrl && hd1->bus.id == bus_parallel) {
ok = 0;
break;
}
}
hd_free_hd_data(hd_data);
free(hd_data);
return ok;
}
/* check if item is in items */
int has_item(hd_hw_item_t *items, hd_hw_item_t item)
{
while(*items) if(*items++ == item) return 1;
return 0;
}
/* check if one of items is in hw_class */
int has_hw_class(hd_t *hd, hd_hw_item_t *items)
{
while(*items) if(hd_is_hw_class(hd, *items++)) return 1;
return 0;
}
#endif /* !defined(LIBHD_TINY) */

257
src/hwinfo/hwscand.c Normal file
View File

@@ -0,0 +1,257 @@
/* hwscan front end
Copyright 2004 by SUSE (<adrian@suse.de>) */
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <time.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include "init_message.h"
#define TIMEOUT 2
#define LONG_TIMEOUT 0
#define BUFFERS 1024
int main( int argc, char **argv )
{
int ret, i;
key_t key = KEY;
int msgid;
int mode = 0;
int dev_nr = 0;
int lines = 0;
int block, usb, firewire, pci;
int dev_last_state[BUFFERS];
int dev_counter[BUFFERS];
char * command_device[NR_COMMANDS][BUFFERS];
time_t command_device_last[NR_COMMANDS][BUFFERS];
time_t last;
char **commands;
char **devices;
char buffer[32];
message m;
// are we running already, maybe ?
{
do {
ssize_t r;
char b[1024];
char link[1024];
int fd = open( PID_FILE, O_RDONLY );
if ( fd >= 0 && (r=read(fd,b,1023)) > 0 ){
close(fd);
b[r]='\0';
snprintf(link, 1023, "/proc/%s/exe", b);
if ( (r=readlink( link, b, 1023 )) > 0 ){
b[r]='\0';
if ( r<8 )
unlink(PID_FILE);
else if ( strcmp("/hwscand", b+strlen(b)-8) )
unlink(PID_FILE);
else
exit(1);
}else
unlink(PID_FILE);
}else if ( fd >= 0 )
unlink(PID_FILE);
} while ( 0 > (ret = open( PID_FILE, O_WRONLY|O_CREAT|O_EXCL, S_IRUSR|S_IWUSR ) ) );
sprintf(buffer, "%d", getpid());
if ( ret < 0 || write(ret,buffer,strlen(buffer)) <= 0 ){
perror("hwscand: unable to write pid file "PID_FILE);
exit(1);
}
close(ret);
}
// initialize ...
for ( i=0; i<NR_COMMANDS; i++ ){
command_device[i][0] = 0;
command_device_last[i][0] = 1;
}
last=block=usb=firewire=pci=0;
commands = (char**) malloc( BUFFERS * sizeof(char*) );
devices = (char**) malloc( BUFFERS * sizeof(char*) );
msgid = msgget(key, IPC_CREAT | 0600);
if (msgid < 0) {
perror("msgget");
exit(1);
}
while (1) {
if ( last || dev_nr )
mode = IPC_NOWAIT;
else
mode = 0;
if( msgrcv(msgid, &m, MESSAGE_BUFFER, 1, mode) >= 0 ){
char *p = m.mtext;
if ( p == 0 ){
fprintf( stderr, "hwscand: error, zero sized message\n" );
}else{
if ( p[0] == 'S' && strlen(p) > 1 ){
// scan calls
char z[2];
int c;
z[0] = *(p+1);
z[1] = '\0';
c = atoi(z);
if ( c < NR_COMMANDS ){
if ( ! command_with_device[c] ){
last = time(0L);
if ( LONG_TIMEOUT+command_device_last[c][0] < time(0L) )
command_device_last[c][0] = 0;
}else
for ( i=0; i<BUFFERS; i++ ){
if ( !command_device[c][i] ){
last = time(0L);
command_device[c][i] = strdup(p+2);
command_device[c][i+1] = 0;
command_device_last[c][i] = 0;
break;
}else if ( !strcmp(command_device[c][i], p+2) ){
last = time(0L);
if ( LONG_TIMEOUT+command_device_last[c][i] < time(0L) )
command_device_last[c][i] = 0;
break;
}
}
}
}
if ( p[0] == 'C' && lines < BUFFERS ){
last = time(0L);
// config calls
commands[lines] = strdup(p+1);
lines++;
}
if ( p[0] == 'A' && dev_nr < BUFFERS ){
// add scan devices
devices[dev_nr] = strdup(p+1);
dev_last_state[dev_nr] = 0;
dev_counter[dev_nr] = 0;
dev_nr++;
}
if ( p[0] == 'R' && dev_nr < BUFFERS ){
for ( i=0; i<dev_nr; i++ ){
if ( !strcmp(p+1, devices[i]) ){
int j;
free(devices[i]);
for ( j=i; j+1<dev_nr; j++ ){
devices[j] = devices[j+1];
dev_last_state[j] = dev_last_state[j+1];
dev_counter[j] = dev_counter[j+1];
}
dev_nr--;
}
}
}
}
#if DEBUG
printf("CALL RECEIVED %s\n", p);
#endif
}else{
// we do this only in scanning mode ...
sleep(1);
for ( i=0; i<dev_nr; i++ ){
if (dev_counter[i]<0) continue;
dev_counter[i]++;
if ( dev_counter[i] > 5 ){
int fd;
char buf[MESSAGE_BUFFER];
dev_counter[i] = 0;
fd = open( devices[i], O_RDONLY );
strcpy( buf, "/sbin/hwscan --fast --partition --only=");
strcat( buf, devices[i] );
if ( fd < 0 ){
if ( dev_last_state[i] )
system(buf);
dev_last_state[i] = 0;
}else{
if ( dev_last_state[i] == 0)
system(buf);
dev_last_state[i] = 1;
close(fd);
}
}
}
}
if ( last && (last+TIMEOUT <= time(0L)) ){
char buf[MESSAGE_BUFFER * NR_COMMANDS];
int run_really = 0;
last=0;
strcpy( buf, "/sbin/hwscan --fast --boot --silent" );
for ( i=0; i<NR_COMMANDS; i++ ){
if ( command_with_device[i] == 0 &&
command_device_last[i][0] == 0 ){
command_device_last[i][0] = time(0L);
strcat( buf, " --");
strcat( buf, command_args[i] );
run_really = 1;
} else {
int j;
int commappended = 0;
for ( j=0; j<BUFFERS; j++ ){
if ( !command_device[i][j] )
break;
if ( command_device_last[i][j] == 0 ){
if (!commappended) {
strcat( buf, " --");
strcat( buf, command_args[i] );
commappended = 1;
}
strcat( buf, " --only=" );
strcat( buf, command_device[i][j] );
command_device_last[i][j] = time(0L);
run_really = 1;
if (strlen(buf) > sizeof(buf) - MESSAGE_BUFFER)
break;
}
}
}
if (strlen(buf) > sizeof(buf) - MESSAGE_BUFFER) {
last = time(0L); /* call me again */
break;
}
}
if ( run_really ){
#if DEBUG
printf("RUN %s\n", buf);
#endif
system(buf);
#if DEBUG
printf("RUN quit %s\n", buf);
#endif
}
if ( lines ){
for (i=0; i<lines; i++){
#if DEBUG
printf("CALL DIRECT %s\n", commands[i]);
#endif
system(commands[i]);
#if DEBUG
printf("CALL quit %s\n", commands[i]);
#endif
free(commands[i]);
}
lines=0;
}
}
}
return 0;
}

126
src/hwinfo/hwscanqueue.c Normal file
View File

@@ -0,0 +1,126 @@
/* hwscan front end
Copyright 2004 by SUSE (<adrian@suse.de>) */
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <signal.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include "init_message.h"
int main( int argc, char **argv )
{
int ret;
unsigned short i;
key_t key = KEY;
int msgid;
message m;
char *device = argv[2];
if ( argc < 2 ){
fprintf( stderr, "help: hwscanqueue hwscan-commands\n" );
fprintf( stderr, "help: commands:\n" );
for ( i=0; i<NR_COMMANDS; i++ ){
fprintf( stderr, " --%s", command_args[i] );
if ( command_with_device[i] )
fprintf( stderr, " device" );
fprintf( stderr, "\n");
}
fprintf( stderr, " --avail=yes/no id\n" );
fprintf( stderr, " --scan=device\n" );
fprintf( stderr, " --stop=device\n" );
exit(1);
}
if ( !strncmp("--cfg=", argv[1], 6) && argc>2 )
snprintf( m.mtext, MESSAGE_BUFFER, "C/sbin/hwscan %s %s", argv[1], argv[2] );
else if ( !strncmp("--avail=", argv[1], 8) && argc>2 )
snprintf( m.mtext, MESSAGE_BUFFER, "C/sbin/hwscan %s %s", argv[1], argv[2] );
else if ( !strncmp("--scan=", argv[1], 7) )
snprintf( m.mtext, MESSAGE_BUFFER, "A%s", argv[1]+7 );
else if ( !strncmp("--stop=", argv[1], 7) )
snprintf( m.mtext, MESSAGE_BUFFER, "R%s", argv[1]+7 );
else if ( !strncmp("--", argv[1], 2) ){
for ( i=0; i<NR_COMMANDS; i++ ){
if ( !strcmp(argv[1]+2,command_args[i]) ){
#if DEBUG
printf("COMMAND %s\n", command_args[i] );
#endif
snprintf( m.mtext, MESSAGE_BUFFER, "S%d", i );
if (command_with_device[i]){
if ( !device ){
fprintf(stderr, "need a device for this command\n");
exit(1);
}
strncat( m.mtext, device, MESSAGE_BUFFER-3 );
}
break;
}
}
if ( i>=NR_COMMANDS ){
fprintf(stderr, "unknown command\n");
exit(1);
}
}else
exit(1);
if ( (msgid = msgget(key, IPC_CREAT | 0600)) < 0 ){
perror("unable to init.");
exit(1);
}
m.mtype = 1;
ret = msgsnd( msgid, &m, MESSAGE_BUFFER, IPC_NOWAIT);
#if DEBUG
printf("SEND %s, return %d\n", m.mtext, ret );
#endif
if ( ret < 0 )
perror("message send failed");
else{
// success ... start hwscand, if it is not yet running
ssize_t r;
char buffer[1024];
char link[1024];
int fd = open( PID_FILE, O_RDONLY );
if ( fd >= 0 && (r=read(fd,buffer,1023)) > 0 ){
close(fd);
buffer[r]='\0';
snprintf(link, 1023, "/proc/%s/exe", buffer);
if ( (r=readlink( link, buffer, 1023 )) > 0 ){
buffer[r]='\0';
if ( r<8 )
fd=-1;
else if ( strcmp("/hwscand", buffer+strlen(buffer)-8) )
fd=-1;
}else
fd=-1;
}else
fd=-1;
if ( fd < 0 ){
pid_t pid;
signal(SIGCHLD,SIG_IGN);
pid=fork();
if (pid==0){
/* Change directory to allow clean shut-down */
chdir("/");
/* Close std fds */
close(0);
close(1);
close(2);
/* Start hwscand */
execve("/sbin/hwscand", 0, 0);
}
}
}
exit(ret);
}

17
src/hwinfo/init_message.h Normal file
View File

@@ -0,0 +1,17 @@
#define MESSAGE_BUFFER 1024
#define KEY 8024;
#define PID_FILE "/var/run/hwscand.pid"
// WARNING NEEDS TO BE <= 9
#define NR_COMMANDS 7
// WARNING NEEDS TO BE <= 9
static const char *command_args[] = { "block", "partition", "usb", "firewire", "pci", "pcmcia", "bluetooth" };
static const int command_with_device[] = { 1, 1, 0, 0, 0, 0, 0 };
typedef struct msgbuf {
long mtype;
char mtext[MESSAGE_BUFFER+1];
} message;
#define DEBUG 0

113
src/hwinfo/scripts/mci Executable file
View File

@@ -0,0 +1,113 @@
#! /usr/bin/perl
sub addr2line;
$list = shift;
$bin = shift;
$ofs = shift;
die "usage: mci data_file binary\n" unless -f($list);
open F, $list;
while(<F>) {
if(/^;\s*(.+?)\s*$/) {
@i = split ' ', $1;
$i[0] = sprintf "%-24s", $i[0];
$i[1] = addr2line $i[1];
print "; ", join("\t", @i), "\n";
next
}
@i = split;
die "oops, format error" if @i > 3;
if(@i == 1) {
if($i[0] =~ /^>(\S+)/) {
unshift @funcs, $1;
}
elsif($i[0] =~ /<(\S+)/) {
if($funcs[0] eq $1) {
shift @funcs
}
else {
die "oops, strange data (line $.)\n"
}
}
else {
die "oops, format error"
}
}
else {
$func = $i[0];
$addr = $i[1];
$size = undef;
$size = @i == 2 ? undef : $i[2];
if(defined $size) {
if(exists $mem{$addr}) {
$x = addr2line $func;
$y = addr2line ${$mem{$addr}}[1];
print "malloc oops (line $.): mem $addr; old: $y, size ${$mem{$addr}}[0]; new: $x, size $size\n";
}
$mem{$addr} = [ $size, $func, @funcs ];
delete $lfree{$addr};
}
else {
if(!exists $mem{$addr}) {
$xx = "";
$first = 1;
for $f ($func, @funcs) {
$xx .= "<-" unless $first;
$first = 0;
$xx .= addr2line $f;
}
print "free oops (line $.): $addr ($xx) [last free: line $lfree{$addr}]\n";
}
delete $mem{$addr};
$lfree{$addr} .= " $.";
}
}
}
for (sort keys %mem) {
$total += oct(${$mem{$_}}[0]);
$cnt++;
# $x = `addr2line -s -e $bin ${$mem{$_}}[1]`;
# chomp $x;
# $x = $x =~ /\?{2}/ ? undef : "$x ";
$x = addr2line ${$mem{$_}}[1];
print "$_\t${$mem{$_}}[0]\t";
$first = 1;
for $f (@{$mem{$_}}[1..$#{$mem{$_}}]) {
print "<-" unless $first;
$first = 0;
print addr2line $f;
}
print "\n"
}
printf "total: %u bytes in %u blocks\n", $total, $cnt;
sub addr2line
{
my ($x, $y);
return $_[0] unless $bin;
$y = sprintf "0x%x", oct($_[0]) + $ofs;
return $addr_cache{$y} if exists $addr_cache{$y};
$x = `addr2line -s -e $bin $y`;
chomp $x;
$x = $x =~ /\?{2}/ ? $_[0] : $x;
$addr_cache{$y} = $x;
return $x;
}

38
src/hwinfo/src/Makefile Normal file
View File

@@ -0,0 +1,38 @@
TOPDIR = ..
SUBDIRS = hd isdn ids
TARGETS = touch $(LIBHD) $(LIBHD_SO)
CLEANFILES = $(LIBHD) $(LIBHD_D) $(LIBHD_SO) *.so *.so.* *.a
.PHONY: touch
include $(TOPDIR)/Makefile.common
ifneq "$(findstring $(ARCH), i386 x86_64 ia64)" ""
ifneq ($(LIBHD_BASE), libhd_tiny)
SUBDIRS += x86emu int10
endif
endif
#ifeq "$(findstring $(ARCH), i386 alpha)" ""
#SUBDIRS := $(filter-out pnpdump, $(SUBDIRS))
#endif
$(LIBHD): $(OBJS)
ar r $@ $?
@rm -f $(LIBHD_D)
ifdef SHARED_FLAGS
$(LIBHD_SO): $(LIBHD)
$(CC) -shared $(SO_LIBS) -Wl,--whole-archive $(LIBHD) -Wl,--no-whole-archive \
-Wl,-soname=$(LIBHD_SONAME) \
-o $(LIBHD_SO)
ln -snf $(LIBHD_NAME) $(LIBHD_SONAME)
ln -snf $(LIBHD_SONAME) $(LIBHD_BASE).so
else
$(LIBHD_SO):
endif
subdirs: touch
touch:
@touch -r $(LIBHD) $(LIBHD_D) 2>/dev/null || true

View File

@@ -0,0 +1,14 @@
TOPDIR = ../..
TARGETS = $(LIBHD_D)
CLEANFILES = version.h
include $(TOPDIR)/Makefile.common
version.h: $(TOPDIR)/VERSION
@echo "#define HD_VERSION_STRING \"`cat $(TOPDIR)/VERSION`\"" >$@
hd.h: $(TOPDIR)/VERSION
@perl -pi -e "s/define\s+HD_VERSION\s+\d+/define HD_VERSION\t$(LIBHD_MAJOR_VERSION)/" $@
$(LIBHD_D): $(OBJS)
ar r $(LIBHD) $?

78
src/hwinfo/src/hd/adb.c Normal file
View File

@@ -0,0 +1,78 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <termios.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/ioctl.h>
#include "hd.h"
#include "hd_int.h"
#include "adb.h"
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
* adb info
*
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
*/
#ifdef __PPC__
void hd_scan_adb(hd_data_t *hd_data)
{
int i;
unsigned u, adr = 0;
hd_t *hd;
str_list_t *sl;
if(!hd_probe_feature(hd_data, pr_adb)) return;
hd_data->module = mod_adb;
/* some clean-up */
remove_hd_entries(hd_data);
PROGRESS(1, 0, "get info");
for(sl = hd_data->klog; sl; sl = sl->next) {
if(sscanf(sl->str, "<4>ADB mouse at %u, %*[a-z ] %i", &u, &i) == 2 && u < 32) {
/* u: max 15 actually, but who cares... */
if(!(adr & (1 << u))) {
adr |= 1 << u;
hd = add_hd_entry(hd_data, __LINE__, 0);
hd->base_class.id = bc_mouse;
hd->sub_class.id = sc_mou_bus;
hd->bus.id = bus_adb;
hd->slot = u;
// hd->func = i;
hd->unix_dev_name = new_str(DEV_MICE);
hd->vendor.id = MAKE_ID(TAG_SPECIAL, 0x0100);
hd->device.id = MAKE_ID(TAG_SPECIAL, 0x0300 + i);
}
}
if(sscanf(sl->str, "<4>ADB keyboard at %u, %*[a-z ] %i", &u, &i) == 2 && u < 32) {
/* u: max 15 actually, but who cares... */
if(!(adr & (1 << u))) {
adr |= 1 << u;
hd = add_hd_entry(hd_data, __LINE__, 0);
hd->base_class.id = bc_keyboard;
hd->sub_class.id = 0;
hd->bus.id = bus_adb;
hd->slot = u;
// hd->func = i;
// hd->unix_dev_name = new_str(DEV_ADBMOUSE);
hd->vendor.id = MAKE_ID(TAG_SPECIAL, 0x0100);
hd->device.id = MAKE_ID(TAG_SPECIAL, 0x0200+i);
}
}
}
}
#endif /* __PPC__ */

1
src/hwinfo/src/hd/adb.h Normal file
View File

@@ -0,0 +1 @@
void hd_scan_adb(hd_data_t *hd_data);

1014
src/hwinfo/src/hd/bios.c Normal file

File diff suppressed because it is too large Load Diff

8
src/hwinfo/src/hd/bios.h Normal file
View File

@@ -0,0 +1,8 @@
#define BIOS_ROM_START 0xc0000
#define BIOS_ROM_SIZE 0x40000
#define BIOS_RAM_START 0x400
#define BIOS_RAM_SIZE 0x100
void hd_scan_bios(hd_data_t *hd_data);
void get_vbe_info(hd_data_t *hd_data, vbe_info_t *vbe);

1578
src/hwinfo/src/hd/block.c Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,2 @@
void hd_scan_sysfs_block(hd_data_t *hd_data);
void hd_scan_sysfs_scsi(hd_data_t *hd_data);

455
src/hwinfo/src/hd/braille.c Normal file
View File

@@ -0,0 +1,455 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <termios.h>
#include "hd.h"
#include "hd_int.h"
#include "braille.h"
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
* braille displays
*
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
*/
#if !defined(LIBHD_TINY) && !defined(__sparc__)
static unsigned do_alva(hd_data_t *hd_data, char *dev_name, int cnt);
static unsigned do_fhp(hd_data_t *hd_data, char *dev_name, unsigned baud, int cnt);
static unsigned do_ht(hd_data_t *hd_data, char *dev_name, int cnt);
static unsigned do_baum(hd_data_t *hd_data, char *dev_name, int cnt);
void hd_scan_braille(hd_data_t *hd_data)
{
hd_t *hd, *hd_tmp;
int cnt = 0;
unsigned dev, vend;
if(!hd_probe_feature(hd_data, pr_braille)) return;
hd_data->module = mod_braille;
/* some clean-up */
remove_hd_entries(hd_data);
for(hd = hd_data->hd; hd; hd = hd->next) {
if(
hd->base_class.id == bc_comm &&
hd->sub_class.id == sc_com_ser &&
hd->unix_dev_name &&
!hd->tag.ser_skip &&
!has_something_attached(hd_data, hd)
) {
cnt++;
dev = vend = 0;
if(hd_probe_feature(hd_data, pr_braille_alva)) {
PROGRESS(1, cnt, "alva");
vend = MAKE_ID(TAG_SPECIAL, 0x5001);
dev = do_alva(hd_data, hd->unix_dev_name, cnt);
}
if(!dev && hd_probe_feature(hd_data, pr_braille_fhp)) {
PROGRESS(1, cnt, "fhp_old");
vend = MAKE_ID(TAG_SPECIAL, 0x5002);
dev = do_fhp(hd_data, hd->unix_dev_name, B19200, cnt);
if(!dev) {
PROGRESS(1, cnt, "fhp_el");
dev = do_fhp(hd_data, hd->unix_dev_name, B38400, cnt);
}
}
if(!dev && hd_probe_feature(hd_data, pr_braille_ht)) {
PROGRESS(1, cnt, "ht");
vend = MAKE_ID(TAG_SPECIAL, 0x5003);
dev = do_ht(hd_data, hd->unix_dev_name, cnt);
}
if(!dev && hd_probe_feature(hd_data, pr_braille_baum)) {
PROGRESS(1, cnt, "baum");
vend = MAKE_ID(TAG_SPECIAL, 0x5004);
dev = do_baum(hd_data, hd->unix_dev_name, cnt);
}
if(dev) {
hd_tmp = add_hd_entry(hd_data, __LINE__, 0);
hd_tmp->base_class.id = bc_braille;
hd_tmp->bus.id = bus_serial;
hd_tmp->unix_dev_name = new_str(hd->unix_dev_name);
hd_tmp->attached_to = hd->idx;
hd_tmp->vendor.id = vend;
hd_tmp->device.id = dev;
}
}
}
}
/*
* autodetect for Alva Braille-displays
* Author: marco Skambraks <marco@suse.de>
* Suse GmbH Nuernberg
*
* This is free software, placed under the terms of the
* GNU General Public License, as published by the Free Software
* Foundation. Please see the file COPYING for details.
*/
/* Communication codes */
#define BRL_ID "\033ID="
#define WAIT_DTR 700000
#define WAIT_FLUSH 200
unsigned do_alva(hd_data_t *hd_data, char *dev_name, int cnt)
{
int fd, i, timeout = 100;
struct termios oldtio, newtio; /* old & new terminal settings */
int model = -1;
unsigned char buffer[sizeof BRL_ID];
unsigned dev = 0;
PROGRESS(2, cnt, "alva open");
/* Open the Braille display device for random access */
fd = open(dev_name, O_RDWR | O_NOCTTY);
if(fd < 0) return 0;
tcgetattr(fd, &oldtio); /* save current settings */
/* Set flow control and 8n1, enable reading */
memset(&newtio, 0, sizeof newtio);
newtio.c_cflag = CRTSCTS | CS8 | CLOCAL | CREAD;
/* Ignore bytes with parity errors and make terminal raw and dumb */
newtio.c_iflag = IGNPAR;
newtio.c_oflag = 0; /* raw output */
newtio.c_lflag = 0; /* don't echo or generate signals */
newtio.c_cc[VMIN] = 0; /* set nonblocking read */
newtio.c_cc[VTIME] = 0;
PROGRESS(3, cnt, "alva init ok");
PROGRESS(4, cnt, "alva read data");
/* autodetecting ABT model */
/* to force DTR off */
cfsetispeed(&newtio, B0);
cfsetospeed(&newtio, B0);
tcsetattr(fd, TCSANOW, &newtio); /* activate new settings */
usleep(WAIT_DTR);
tcflush(fd, TCIOFLUSH); /* clean line */
usleep(WAIT_FLUSH);
/* DTR back on */
cfsetispeed(&newtio, B9600);
cfsetospeed(&newtio, B9600);
tcsetattr(fd, TCSANOW, &newtio); /* activate new settings */
usleep(WAIT_DTR); /* give time to send ID string */
if((i = read(fd, buffer, sizeof buffer)) == sizeof buffer) {
if(!strncmp(buffer, BRL_ID, sizeof BRL_ID - 1)) {
/* Find out which model we are connected to... */
switch(model = buffer[sizeof buffer - 1])
{
case 1:
case 2:
case 3:
case 4:
case 0x0b:
case 0x0d:
case 0x0e:
dev = MAKE_ID(TAG_SPECIAL, model);
break;
}
}
}
ADD2LOG("alva.%d@%s[%d]: ", timeout, dev_name, i);
if(i > 0) hexdump(&hd_data->log, 1, i, buffer);
ADD2LOG("\n");
PROGRESS(5, cnt, "alva read done");
/* reset serial lines */
tcflush(fd, TCIOFLUSH);
tcsetattr(fd, TCSAFLUSH, &oldtio);
close(fd);
return dev;
}
/*
* autodetect for Papenmeier Braille-displays
* Author: marco Skambraks <marco@suse.de>
* Suse GmbH Nuernberg
*
* This is free software, placed under the terms of the
* GNU General Public License, as published by the Free Software
* Foundation. Please see the file COPYING for details.
*/
unsigned do_fhp(hd_data_t *hd_data, char *dev_name, unsigned baud, int cnt)
{
int fd, i;
char crash[] = { 2, 'S', 0, 0, 0, 0 };
unsigned char buf[10];
struct termios oldtio, newtio; /* old & new terminal settings */
unsigned dev;
PROGRESS(2, cnt, "fhp open");
/* Now open the Braille display device for random access */
fd = open(dev_name, O_RDWR | O_NOCTTY);
if(fd < 0) return 0;
tcgetattr(fd, &oldtio); /* save current settings */
/* Set bps, flow control and 8n1, enable reading */
memset(&newtio, 0, sizeof newtio);
newtio.c_cflag = baud | CS8 | CLOCAL | CREAD;
/* Ignore bytes with parity errors and make terminal raw and dumb */
newtio.c_iflag = IGNPAR;
newtio.c_oflag = 0; /* raw output */
newtio.c_lflag = 0; /* don't echo or generate signals */
newtio.c_cc[VMIN] = 0; /* set nonblocking read */
newtio.c_cc[VTIME] = 0;
tcflush(fd, TCIFLUSH); /* clean line */
tcsetattr(fd, TCSANOW, &newtio); /* activate new settings */
PROGRESS(3, cnt, "fhp init ok");
crash[2] = 0x200 >> 8;
crash[3] = 0x200 & 0xff;
crash[5] = (7+10) & 0xff;
write(fd, crash, sizeof crash);
write(fd, "1111111111",10);
write(fd, "\03", 1);
crash[2] = 0x0 >> 8;
crash[3] = 0x0 & 0xff;
crash[5] = 5 & 0xff;
write(fd, crash, sizeof crash);
write(fd, "1111111111", 10);
write(fd, "\03", 1);
usleep(500000); /* 100000 should be enough */
PROGRESS(4, cnt, "fhp write ok");
i = read(fd, &buf, 10);
PROGRESS(5, cnt, "fhp read done");
ADD2LOG("fhp@%s[%d]: ", dev_name, i);
if(i > 0) hexdump(&hd_data->log, 1, i, buf);
ADD2LOG("\n");
dev = 0;
if(i == 10 && buf[0] == 0x02 && buf[1] == 0x49) {
switch(buf[2]) {
case 1:
case 2:
case 3:
case 64:
case 65:
case 66:
case 67:
case 68:
dev = buf[2];
dev = MAKE_ID(TAG_SPECIAL, dev);
break;
}
}
if(!dev) ADD2LOG("no fhp display: 0x%02x\n", i >= 2 ? buf[2] : 0);
/* reset serial lines */
tcflush(fd, TCIOFLUSH);
tcsetattr(fd, TCSAFLUSH, &oldtio);
close(fd);
return dev;
}
/*
* autodetect for Handy Tech Braille-displays
* Author: marco Skambraks <marco@suse.de>
* Suse GmbH Nuernberg
*
* This is free software, placed under the terms of the
* GNU General Public License, as published by the Free Software
* Foundation. Please see the file COPYING for details.
*/
unsigned do_ht(hd_data_t *hd_data, char *dev_name, int cnt)
{
int fd, i;
unsigned char code = 0xff, buf[2] = { 0, 0 };
struct termios oldtio, newtio;
unsigned dev = 0;
PROGRESS(2, cnt, "ht open");
fd = open(dev_name, O_RDWR | O_NOCTTY);
if(fd < 0) return 0;
tcgetattr(fd, &oldtio);
newtio = oldtio;
newtio.c_cflag = CLOCAL | PARODD | PARENB | CREAD | CS8;
newtio.c_iflag = IGNPAR;
newtio.c_oflag = 0;
newtio.c_lflag = 0;
newtio.c_cc[VMIN] = 0;
newtio.c_cc[VTIME] = 0;
i = 0;
/*
* Force down DTR, flush any pending data and then the port to what we
* want it to be
*/
if(
!(
cfsetispeed(&newtio, B0) ||
cfsetospeed(&newtio, B0) ||
tcsetattr(fd, TCSANOW, &newtio) ||
tcflush(fd, TCIOFLUSH) ||
cfsetispeed(&newtio, B19200) ||
cfsetospeed(&newtio, B19200) ||
tcsetattr(fd, TCSANOW, &newtio)
)
) {
/* Pause to let them take effect */
usleep(500);
PROGRESS(3, cnt, "ht init ok");
write(fd, &code, 1); /* reset brl */
usleep(5000); /* wait for reset */
PROGRESS(4, cnt, "ht write ok");
read(fd, buf, 1);
i = 1;
PROGRESS(5, cnt, "ht read done");
if(buf[0] == 0xfe) { /* resetok now read id */
usleep(5000);
read(fd, buf + 1, 1);
i = 2;
PROGRESS(6, cnt, "ht read done");
switch(buf[1]) {
case 0x05:
case 0x09:
case 0x44:
case 0x74:
case 0x80:
case 0x84:
case 0x88:
case 0x89:
dev = buf[1];
dev = MAKE_ID(TAG_SPECIAL, dev);
break;
}
}
}
ADD2LOG("ht@%s[%d]: ", dev_name, i);
if(i > 0) hexdump(&hd_data->log, 1, i, buf);
ADD2LOG("\n");
if(!dev) ADD2LOG("no ht display: 0x%02x\n", buf[1]);
/* reset serial lines */
tcflush(fd, TCIOFLUSH);
tcsetattr(fd, TCSAFLUSH, &oldtio);
close(fd);
return dev;
}
/*
* autodetect for Baum Braille-displays
* Author: marco Skambraks <marco@suse.de>
* Suse GmbH Nuernberg
*
* This is free software, placed under the terms of the
* GNU General Public License, as published by the Free Software
* Foundation. Please see the file COPYING for details.
*/
#define BAUDRATE B19200 /* But both run at 19k2 */
#define MAXREAD 18
unsigned do_baum(hd_data_t *hd_data, char *dev_name, int cnt)
{
static char device_id[] = { 0x1b, 0x84 };
int fd;
struct termios oldtio, curtio;
unsigned char buf[MAXREAD + 1];
int i;
PROGRESS(2, cnt, "baum open");
fd = open(dev_name, O_RDWR | O_NOCTTY);
if(fd < 0) return 0;
tcgetattr(fd, &curtio);
oldtio = curtio;
cfmakeraw(&curtio);
/* no SIGTTOU to backgrounded processes */
curtio.c_lflag &= ~TOSTOP;
curtio.c_cflag = BAUDRATE | CS8 | CLOCAL | CREAD;
/* no input parity check, no XON/XOFF */
curtio.c_iflag &= ~(INPCK | ~IXOFF);
curtio.c_cc[VTIME] = 1; /* 0.1s timeout between chars on input */
curtio.c_cc[VMIN] = 0; /* no minimum input */
tcsetattr(fd, TCSAFLUSH, &curtio);
/* write ID-request */
write(fd, device_id, sizeof device_id);
/* wait for response */
usleep(100000);
PROGRESS(3, cnt, "baum write ok");
i = read(fd, buf, sizeof buf - 1);
buf[sizeof buf - 1] = 0;
PROGRESS(4, cnt, "baum read done");
ADD2LOG("baum@%s[%d]: ", dev_name, i);
if(i > 0) hexdump(&hd_data->log, 1, i, buf);
ADD2LOG("\n");
/* reset serial lines */
tcflush(fd, TCIOFLUSH);
tcsetattr(fd, TCSAFLUSH, &oldtio);
close(fd);
if(!strcmp(buf + 2, "Baum Vario40")) return 1;
if(!strcmp(buf + 2, "Baum Vario80")) return 2;
return 0;
}
#endif /* !defined(LIBHD_TINY) && !defined(__sparc__) */

View File

@@ -0,0 +1 @@
void hd_scan_braille(hd_data_t *hd_data);

777
src/hwinfo/src/hd/cpu.c Normal file
View File

@@ -0,0 +1,777 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#ifdef __ia64__
#include <fcntl.h>
#include <errno.h>
#include <stdint.h>
#include <sys/mman.h>
#endif
#ifdef __powerpc__
#include <sys/utsname.h>
#endif
#include "hd.h"
#include "hd_int.h"
#include "klog.h"
#include "cpu.h"
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
* cpu info
*
* Note: on other architectures, entries differ (cf. Alpha)!!!
*
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
*/
static void read_cpuinfo(hd_data_t *hd_data);
static void dump_cpu_data(hd_data_t *hd_data);
#if defined(__i386__) || defined(__x86_64__)
static inline unsigned units_per_cpu();
#endif
#ifdef __ia64__
static int ia64DetectSMP(hd_data_t *hd_data);
#endif
void hd_scan_cpu(hd_data_t *hd_data)
{
hd_t *hd0, *hd;
int i, cpus;
unsigned u;
if(!hd_probe_feature(hd_data, pr_cpu)) return;
hd_data->module = mod_cpu;
/* some clean-up */
remove_hd_entries(hd_data);
hd_data->cpu = free_str_list(hd_data->cpu);
PROGRESS(1, 0, "cpuinfo");
read_cpuinfo(hd_data);
for(hd0 = hd_data->hd; hd0; hd0 = hd0->next) {
if(hd0->base_class.id == bc_internal && hd0->sub_class.id == sc_int_cpu) break;
}
if(!hd0 || hd0->next) return; /* 0 or > 1 entries */
/* only one entry, maybe UP kernel on SMP system */
cpus = 0;
#ifdef __ia64__
cpus = ia64DetectSMP(hd_data);
#endif
for(i = 1; i < cpus; i++) {
hd = add_hd_entry(hd_data, __LINE__, 0);
u = hd->idx;
hd_copy(hd, hd0);
hd->idx = u;
hd->slot = i;
}
}
void read_cpuinfo(hd_data_t *hd_data)
{
hd_t *hd;
unsigned cpus = 0;
cpu_info_t *ct;
str_list_t *sl;
#if defined(__i386__) || defined (__x86_64__)
char model_id[80], vendor_id[80], features[0x100];
unsigned bogo, mhz, cache, family, model, stepping;
char *t0, *t;
#endif
#ifdef __ia64__
char model_id[80], vendor_id[80], features[0x100];
unsigned mhz, stepping;
char *t0, *t;
#endif
#ifdef __alpha__
char model_id[80], system_id[80], serial_number[80], platform[80];
unsigned cpu_variation, cpu_revision, u, hz;
cpu_info_t *ct1;
#endif
#ifdef __PPC__
char model_id[80], vendor_id[80], motherboard[80];
unsigned bogo, mhz, cache, family, model, stepping;
struct utsname un;
#endif
#ifdef __sparc__
char cpu_id[80], fpu_id[80], promlib[80], prom[80], type[80], mmu[80];
unsigned u, bogo, cpus_active;
#endif
#if defined(__s390__) || defined(__s390x__)
char vendor_id[80];
unsigned bogo;
unsigned u0, u1, u2, u3;
#endif
hd_data->cpu = read_file(PROC_CPUINFO, 0, 0);
if((hd_data->debug & HD_DEB_CPU)) dump_cpu_data(hd_data);
if(!hd_data->cpu) return;
#ifdef __alpha__
*model_id = *system_id = *serial_number = *platform = 0;
cpu_variation = cpu_revision = hz = 0;
for(sl = hd_data->cpu; sl; sl = sl->next) {
if(sscanf(sl->str, "cpu model : %79[^\n]", model_id) == 1) continue;
if(sscanf(sl->str, "system type : %79[^\n]", system_id) == 1) continue;
if(sscanf(sl->str, "cpu variation : %u", &cpu_variation) == 1) continue;
if(sscanf(sl->str, "cpu revision : %u", &cpu_revision) == 1) continue;
if(sscanf(sl->str, "system serial number : %79[^\n]", serial_number) == 1) continue;
if(sscanf(sl->str, "cpus detected : %u", &cpus) == 1) continue;
if(sscanf(sl->str, "cycle frequency [Hz] : %u", &hz) == 1) continue;
if(sscanf(sl->str, "system variation : %79[^\n]", platform) == 1) continue;
}
if(*model_id || *system_id) { /* at least one of those */
ct = new_mem(sizeof *ct);
ct->architecture = arch_alpha;
if(model_id) ct->model_name = new_str(model_id);
if(system_id) ct->vend_name = new_str(system_id);
if(strncmp(serial_number, "MILO", 4) == 0)
hd_data->boot = boot_milo;
else
hd_data->boot = boot_aboot;
ct->family = cpu_variation;
ct->model = cpu_revision;
ct->stepping = 0;
ct->cache = 0;
ct->clock = (hz + 500000) / 1000000;
if(platform && strcmp(platform, "0")) {
ct->platform = new_str(platform);
}
if(!cpus) cpus = 1; /* at least 1 machine had a "cpus: 0" entry... */
for(u = 0; u < cpus; u++) {
hd = add_hd_entry(hd_data, __LINE__, 0);
hd->base_class.id = bc_internal;
hd->sub_class.id = sc_int_cpu;
hd->slot = u;
hd->detail = new_mem(sizeof *hd->detail);
hd->detail->type = hd_detail_cpu;
if(u) {
hd->detail->cpu.data = ct1 = new_mem(sizeof *ct);
*ct1 = *ct;
ct1->model_name = new_str(ct1->model_name);
ct1->vend_name = new_str(ct1->vend_name);
ct1->platform = new_str(ct1->platform);
}
else {
hd->detail->cpu.data = ct;
}
}
}
#endif /* __alpha__ */
#ifdef __sparc__
*cpu_id = *fpu_id = *promlib = *prom = *type = *mmu = 0;
cpus = cpus_active = bogo = 0;
for(sl = hd_data->cpu; sl; sl = sl->next) {
if(sscanf(sl->str, "cpu : %79[^\n]", cpu_id) == 1);
if(sscanf(sl->str, "fpu : %79[^\n]", fpu_id) == 1);
if(sscanf(sl->str, "promlib : %79[^\n]", promlib) == 1);
if(sscanf(sl->str, "prom : %79[^\n]", prom) == 1);
if(sscanf(sl->str, "type : %79[^\n]", type) == 1);
if(sscanf(sl->str, "ncpus probed : %u", &cpus) == 1);
if(sscanf(sl->str, "ncpus active : %u", &cpus_active) == 1);
if(sscanf(sl->str, "BogoMips : %u", &bogo) == 1);
if(sscanf(sl->str, "MMU Type : %79[^\n]", mmu) == 1);
}
if(*cpu_id) {
for(u = 0; u < cpus; u++) {
ct = new_mem(sizeof *ct);
ct->platform = new_str (type);
if(strcmp (type, "sun4u") == 0)
ct->architecture = arch_sparc64;
else
ct->architecture = arch_sparc;
ct->model_name = new_str(cpu_id);
hd_data->boot = boot_silo;
hd = add_hd_entry(hd_data, __LINE__, 0);
hd->base_class.id = bc_internal;
hd->sub_class.id = sc_int_cpu;
hd->slot = u;
hd->detail = new_mem(sizeof *hd->detail);
hd->detail->type = hd_detail_cpu;
hd->detail->cpu.data = ct;
}
}
#endif /* sparc */
#if defined(__i386__) || defined (__x86_64__)
*model_id = *vendor_id = *features = 0;
bogo = mhz = cache = family = model = stepping = 0;
for(sl = hd_data->cpu; sl; sl = sl->next) {
if(sscanf(sl->str, "model name : %79[^\n]", model_id) == 1);
if(sscanf(sl->str, "vendor_id : %79[^\n]", vendor_id) == 1);
if(sscanf(sl->str, "flags : %255[^\n]", features) == 1);
if(sscanf(sl->str, "bogomips : %u", &bogo) == 1);
if(sscanf(sl->str, "cpu MHz : %u", &mhz) == 1);
if(sscanf(sl->str, "cache size : %u KB", &cache) == 1);
if(sscanf(sl->str, "cpu family : %u", &family) == 1);
if(sscanf(sl->str, "model : %u", &model) == 1);
if(sscanf(sl->str, "stepping : %u", &stepping) == 1);
if(strstr(sl->str, "processor") == sl->str || !sl->next) { /* EOF */
if(*model_id || *vendor_id) { /* at least one of those */
ct = new_mem(sizeof *ct);
#ifdef __i386__
ct->architecture = arch_intel;
#endif
#ifdef __x86_64__
ct->architecture = arch_x86_64;
#endif
if(model_id) ct->model_name = new_str(model_id);
if(vendor_id) ct->vend_name = new_str(vendor_id);
ct->family = family;
ct->model = model;
ct->stepping = stepping;
ct->cache = cache;
hd_data->boot = boot_grub;
/* round clock to typical values */
if(mhz >= 38 && mhz <= 42)
mhz = 40;
else if(mhz >= 88 && mhz <= 92)
mhz = 90;
else {
unsigned u, v;
u = (mhz + 2) % 100;
v = (mhz + 2) / 100;
if(u <= 4)
u = 2;
else if(u >= 25 && u <= 29)
u = 25 + 2;
else if(u >= 33 && u <= 37)
u = 33 + 2;
else if(u >= 50 && u <= 54)
u = 50 + 2;
else if(u >= 66 && u <= 70)
u = 66 + 2;
else if(u >= 75 && u <= 79)
u = 75 + 2;
else if(u >= 80 && u <= 84) /* there are 180MHz PPros */
u = 80 + 2;
u -= 2;
mhz = v * 100 + u;
}
ct->clock = mhz;
hd = add_hd_entry(hd_data, __LINE__, 0);
hd->base_class.id = bc_internal;
hd->sub_class.id = sc_int_cpu;
hd->slot = cpus;
hd->detail = new_mem(sizeof *hd->detail);
hd->detail->type = hd_detail_cpu;
hd->detail->cpu.data = ct;
if(*features) {
for(t0 = features; (t = strsep(&t0, " ")); ) {
add_str_list(&ct->features, t);
if(!strcmp(t, "ht")) ct->units = units_per_cpu();
}
}
*model_id = *vendor_id = 0;
bogo = mhz = cache = family = model= 0;
cpus++;
}
}
}
#endif /* __i386__ || __x86_64__ */
#ifdef __PPC__
*model_id = *vendor_id = *motherboard = 0;
bogo = mhz = cache = family = model = stepping = 0;
for(sl = hd_data->cpu; sl; sl = sl->next) {
if(sscanf(sl->str, "machine : %79[^\n]", vendor_id) == 1);
}
for(sl = hd_data->cpu; sl; sl = sl->next) {
if(sscanf(sl->str, "cpu : %79[^\n]", model_id) == 1);
if(sscanf(sl->str, "motherboard : %79[^\n]", motherboard) == 1);
if(sscanf(sl->str, "bogomips : %u", &bogo) == 1);
if(sscanf(sl->str, "clock : %u", &mhz) == 1);
if(sscanf(sl->str, "L2 cache : %u KB", &cache) == 1);
if(strstr(sl->str, "processor") == sl->str || !sl->next) { /* EOF */
if(*model_id) { /* at least one of those */
ct = new_mem(sizeof *ct);
ct->architecture = arch_ppc;
if(model_id) {
ct->model_name = new_str(model_id);
}
if(!uname(&un))
if(strstr(un.machine,"ppc64"))
ct->architecture = arch_ppc64;
if(vendor_id) ct->vend_name = new_str(vendor_id);
if(motherboard) ct->platform = new_str(motherboard);
ct->family = family;
ct->model = model;
ct->stepping = stepping;
ct->cache = cache;
hd_data->boot = boot_ppc;
ct->clock = mhz;
hd = add_hd_entry(hd_data, __LINE__, 0);
hd->base_class.id = bc_internal;
hd->sub_class.id = sc_int_cpu;
hd->slot = cpus;
hd->detail = new_mem(sizeof *hd->detail);
hd->detail->type = hd_detail_cpu;
hd->detail->cpu.data = ct;
if(ct->vend_name && !strcmp(ct->vend_name, "PowerBook") && !hd_data->color_code) {
hd_data->color_code = 7; // black
}
*model_id = 0;
bogo = mhz = cache = family = model= 0;
cpus++;
}
}
}
#endif /* __PPC__ */
#ifdef __ia64__
*model_id = *vendor_id = *features = 0;
mhz = stepping = 0;
for(sl = hd_data->cpu; sl; sl = sl->next) {
if(sscanf(sl->str, "family : %79[^\n]", model_id) == 1);
if(sscanf(sl->str, "vendor : %79[^\n]", vendor_id) == 1);
if(sscanf(sl->str, "features : %255[^\n]", features) == 1);
if(sscanf(sl->str, "cpu MHz : %u", &mhz) == 1);
if(sscanf(sl->str, "revision : %u", &stepping) == 1);
if(strstr(sl->str, "processor") == sl->str || !sl->next) { /* EOF */
if(*model_id || *vendor_id) { /* at least one of those */
ct = new_mem(sizeof *ct);
ct->architecture = arch_ia64;
if(model_id) ct->model_name = new_str(model_id);
if(vendor_id) ct->vend_name = new_str(vendor_id);
ct->stepping = stepping;
hd_data->boot = boot_elilo;
/* round clock to typical values */
if(mhz >= 38 && mhz <= 42)
mhz = 40;
else if(mhz >= 88 && mhz <= 92)
mhz = 90;
else {
unsigned u, v;
u = (mhz + 2) % 100;
v = (mhz + 2) / 100;
if(u <= 4)
u = 2;
else if(u >= 25 && u <= 29)
u = 25 + 2;
else if(u >= 33 && u <= 37)
u = 33 + 2;
else if(u >= 50 && u <= 54)
u = 50 + 2;
else if(u >= 66 && u <= 70)
u = 66 + 2;
else if(u >= 75 && u <= 79)
u = 75 + 2;
else if(u >= 80 && u <= 84) /* there are 180MHz PPros */
u = 80 + 2;
u -= 2;
mhz = v * 100 + u;
}
ct->clock = mhz;
hd = add_hd_entry(hd_data, __LINE__, 0);
hd->base_class.id = bc_internal;
hd->sub_class.id = sc_int_cpu;
hd->slot = cpus;
hd->detail = new_mem(sizeof *hd->detail);
hd->detail->type = hd_detail_cpu;
hd->detail->cpu.data = ct;
if(*features) {
for(t0 = features; (t = strsep(&t0, " ")); ) {
add_str_list(&ct->features, t);
}
}
*model_id = *vendor_id = 0;
mhz = 0;
cpus++;
}
}
}
#endif /* __ia64__ */
#if defined(__s390__) || defined(__s390x__)
*vendor_id = 0;
bogo = 0;
for(sl = hd_data->cpu; sl; sl = sl->next) {
if(sscanf(sl->str, "vendor_id : %79[^\n]", vendor_id) == 1);
if(sscanf(sl->str, "bogomips per cpu : %u", &bogo) == 1);
}
for(sl = hd_data->cpu; sl; sl = sl->next) {
if(
sscanf(sl->str, "processor %u : version = %x , identification = %x , machine = %x", &u0, &u1, &u2, &u3) == 4
) {
ct = new_mem(sizeof *ct);
#ifdef __s390x__
ct->architecture = arch_s390x;
#else
ct->architecture = arch_s390;
#endif
if(vendor_id) ct->vend_name = new_str(vendor_id);
ct->stepping = u1;
hd_data->boot = boot_s390;
hd = add_hd_entry(hd_data, __LINE__, 0);
hd->base_class.id = bc_internal;
hd->sub_class.id = sc_int_cpu;
hd->slot = cpus;
hd->detail = new_mem(sizeof *hd->detail);
hd->detail->type = hd_detail_cpu;
hd->detail->cpu.data = ct;
bogo = 0;
cpus++;
}
}
#endif /* defined(__s390__) || defined(__s390x__) */
}
/*
* Add some cpu data to the global log.
*/
void dump_cpu_data(hd_data_t *hd_data)
{
str_list_t *sl;
ADD2LOG("----- /proc/cpuinfo -----\n");
for(sl = hd_data->cpu; sl; sl = sl->next) {
ADD2LOG(" %s", sl->str);
}
ADD2LOG("----- /proc/cpuinfo end -----\n");
}
#if defined(__i386__) || defined(__x86_64__)
inline unsigned units_per_cpu()
{
unsigned u;
asm(
#ifdef __i386__
"push %%ebx\n\t"
#else
"push %%rbx\n\t"
#endif
"mov $1,%%eax\n\t"
"cpuid\n\t"
"shr $8,%%ebx\n\t"
"movzx %%bh,%%eax\n\t"
#ifdef __i386__
"pop %%ebx"
#else
"pop %%rbx"
#endif
: "=a" (u)
:: "%ecx", "%edx"
);
return u;
}
#endif
#ifdef __ia64__
/*
* IA64 SMP detection code
*/
#define PAGE_OFFSET(addr) ((uintptr_t) (addr) & (getpagesize () - 1))
typedef struct
{
uint8_t type;
uint8_t length;
} __attribute__ ((packed)) acpi_table_entry_header;
struct acpi20_table_rsdp
{
char signature[8];
uint8_t checksum;
char oem_id[6];
uint8_t revision;
uint32_t rsdt_address;
uint32_t length;
unsigned long xsdt_address;
uint8_t ext_checksum;
uint8_t reserved[3];
} __attribute__ ((packed));
struct acpi_table_header
{
char signature[4];
uint32_t length;
uint8_t revision;
uint8_t checksum;
char oem_id[6];
char oem_table_id[8];
uint32_t oem_revision;
char asl_compiler_id[4];
uint32_t asl_compiler_revision;
};
#define ACPI_XSDT_SIG "XSDT"
struct acpi_table_xsdt
{
struct acpi_table_header header;
unsigned long entry[0];
} __attribute__ ((packed));
#define ACPI_MADT_SIG "ACPI"
struct acpi_table_madt
{
struct acpi_table_header header;
uint32_t lapic_address;
struct
{
uint32_t pcat_compat:1;
uint32_t reserved:31;
} flags;
} __attribute__ ((packed));
#define ACPI_MADT_LSAPIC 7
struct acpi_table_lsapic
{
acpi_table_entry_header header;
uint8_t acpi_id;
uint8_t id;
uint8_t eid;
uint8_t reserved[3];
struct
{
uint32_t enabled:1;
uint32_t reserved:31;
} flags;
} __attribute__ ((packed));
/*
* Map an ACPI table into virtual memory
*/
static struct acpi_table_header *
acpi_map_table (int mem, unsigned long addr, char *signature)
{
/* mmap header to determine table size */
struct acpi_table_header *table = NULL;
unsigned long offset = PAGE_OFFSET (addr);
uint8_t *mapped = mmap (NULL,
sizeof (struct acpi_table_header) + offset,
PROT_READ,
MAP_PRIVATE,
mem,
(unsigned long) addr - offset);
table = (struct acpi_table_header *) (mapped != MAP_FAILED
? mapped + offset
: NULL);
if (table)
{
if (memcmp (table->signature, signature, sizeof (table->signature)))
{
munmap ((char *) table - offset,
sizeof (struct acpi_table_header) + offset);
return NULL;
}
{
/* re-mmap entire table */
unsigned long size = table->length;
munmap ((uint8_t *) table - offset,
sizeof (struct acpi_table_header) + offset);
mapped = mmap (NULL, size + offset, PROT_READ, MAP_PRIVATE, mem,
(unsigned long) addr - offset);
table = (struct acpi_table_header *) (mapped != MAP_FAILED
? mapped + offset
: NULL);
}
}
return table;
}
/*
* Unmap an ACPI table from virtual memory
*/
static void
acpi_unmap_table (struct acpi_table_header * table)
{
if (table)
{
unsigned long offset = PAGE_OFFSET (table);
munmap ((uint8_t *) table - offset, table->length + offset);
}
}
int
acpi_parse_lsapic (acpi_table_entry_header *p)
{
struct acpi_table_lsapic *lsapic = (struct acpi_table_lsapic *) p;
return lsapic->flags.enabled;
}
static int
acpi_parse_madt (struct acpi_table_madt *madt)
{
acpi_table_entry_header *p, *end;
int n_cpu = 0;
p = (acpi_table_entry_header *) (madt + 1);
end = (acpi_table_entry_header *) ((char *) madt + madt->header.length);
while (p < end)
{
if (p->type == ACPI_MADT_LSAPIC)
n_cpu += acpi_parse_lsapic (p);
p = (acpi_table_entry_header *) ((char *) p + p->length);
}
return n_cpu;
}
static int
acpi_parse_rsdp (int mem_fd, struct acpi20_table_rsdp *rsdp)
{
int n_cpu = 0;
int i;
struct acpi_table_xsdt *xsdt = 0;
int tables;
if (rsdp->xsdt_address)
xsdt = (struct acpi_table_xsdt *) acpi_map_table (mem_fd, rsdp->xsdt_address,
ACPI_XSDT_SIG);
if (xsdt)
{
tables = (xsdt->header.length - sizeof (struct acpi_table_header)) / 8;
for (i = 0; i < tables; i++)
{
struct acpi_table_header *dt
= acpi_map_table (mem_fd, xsdt->entry[i], ACPI_MADT_SIG);
if (dt)
n_cpu += acpi_parse_madt ((struct acpi_table_madt *) dt);
acpi_unmap_table (dt);
}
acpi_unmap_table ((struct acpi_table_header *) xsdt);
}
return n_cpu;
}
int ia64DetectSMP(hd_data_t *hd_data)
{
int n_cpu = 0, mem_fd, systab_fd;
struct acpi20_table_rsdp rsdp;
uint8_t *mapped;
unsigned long addr = 0, offset;
int ok = 0;
str_list_t *sl;
const char *rsd_klog = "ACPI 2.0=";
const char *rsd_systab = "ACPI20=";
char *s;
mem_fd = open("/dev/mem", O_RDONLY);
if(mem_fd == -1) return -1;
systab_fd = open("/proc/efi/systab", O_RDONLY);
if (systab_fd != -1)
{
char buffer[512];
int n_read = read(systab_fd, buffer, sizeof(buffer) - 1);
close(systab_fd);
if (n_read > 0)
{
buffer[n_read] = 0;
if ((s = strstr(buffer, rsd_systab)) != NULL &&
sscanf(s + strlen(rsd_systab), "%lx", &addr) == 1)
goto found_it;
}
}
if(!hd_data->klog) read_klog(hd_data);
for(sl = hd_data->klog; sl; sl = sl->next) {
if((s = strstr(sl->str, rsd_klog))) {
if(sscanf(s + strlen(rsd_klog), "%lx", &addr) == 1) {
found_it:
offset= PAGE_OFFSET (addr);
mapped = mmap(NULL, sizeof rsdp + offset, PROT_READ, MAP_PRIVATE,
mem_fd, (unsigned long) addr - offset);
if(mapped != MAP_FAILED) {
ADD2LOG("seek to 0x%lx\n", addr);
memcpy(&rsdp, mapped + offset, sizeof rsdp);
munmap(mapped, sizeof rsdp + offset);
ok = 1;
}
break;
}
}
}
if(ok) {
n_cpu = acpi_parse_rsdp(mem_fd, &rsdp);
if(n_cpu) {
ADD2LOG("RSDP found at 0x%lx\n", addr);
}
}
close (mem_fd);
ADD2LOG("n_cpu = %d\n", n_cpu);
return n_cpu;
}
#endif /* __ia64__ */

1
src/hwinfo/src/hd/cpu.h Normal file
View File

@@ -0,0 +1 @@
void hd_scan_cpu(hd_data_t *hd_data);

242
src/hwinfo/src/hd/edd.c Normal file
View File

@@ -0,0 +1,242 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include "hd.h"
#include "hd_int.h"
#include "hddb.h"
#include "edd.h"
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
* edd
*
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
*/
static void get_edd_info(hd_data_t *hd_data);
void hd_scan_sysfs_edd(hd_data_t *hd_data)
{
if(!hd_probe_feature(hd_data, pr_edd)) return;
hd_data->module = mod_edd;
/* some clean-up */
remove_hd_entries(hd_data);
hd_data->flags.edd_used = 0;
if(hd_probe_feature(hd_data, pr_edd_mod)) {
PROGRESS(1, 0, "edd mod");
load_module(hd_data, "edd");
}
PROGRESS(2, 0, "edd info");
get_edd_info(hd_data);
}
void get_edd_info(hd_data_t *hd_data)
{
hd_t *hd;
hd_res_t *res;
unsigned u, u1, u2, edd_cnt = 0, lba;
uint64_t ul0;
str_list_t *sl;
bios_info_t *bt;
edd_info_t *ei;
struct sysfs_directory *sf_dir;
struct sysfs_directory *sf_dir_2;
struct sysfs_link *sf_link;
for(u = 0; u < sizeof hd_data->edd / sizeof *hd_data->edd; u++) {
free_mem(hd_data->edd[u].sysfs_id);
}
memset(hd_data->edd, 0, sizeof hd_data->edd);
sf_dir = sysfs_open_directory("/sys/firmware/edd");
if(sf_dir) {
if(!sysfs_read_all_subdirs(sf_dir)) {
if(sf_dir->subdirs) {
dlist_for_each_data(sf_dir->subdirs, sf_dir_2, struct sysfs_directory) {
if(
sscanf(sf_dir_2->name, "int13_dev%02x", &u) == 1 &&
u >= 0x80 &&
u <= 0xff
) {
edd_cnt++;
u -= 0x80;
ei = hd_data->edd + u;
if(hd_attr_uint(sysfs_get_directory_attribute(sf_dir_2, "sectors"), &ul0, 0)) {
ei->sectors = ul0;
}
if(hd_attr_uint(sysfs_get_directory_attribute(sf_dir_2, "default_cylinders"), &ul0, 0)) {
ei->edd.cyls = ul0;
}
if(hd_attr_uint(sysfs_get_directory_attribute(sf_dir_2, "default_heads"), &ul0, 0)) {
ei->edd.heads = ul0;
}
if(hd_attr_uint(sysfs_get_directory_attribute(sf_dir_2, "default_sectors_per_track"), &ul0, 0)) {
ei->edd.sectors = ul0;
}
if(hd_attr_uint(sysfs_get_directory_attribute(sf_dir_2, "legacy_max_cylinder"), &ul0, 0)) {
ei->legacy.cyls = ul0 + 1;
}
if(hd_attr_uint(sysfs_get_directory_attribute(sf_dir_2, "legacy_max_head"), &ul0, 0)) {
ei->legacy.heads = ul0 + 1;
}
if(hd_attr_uint(sysfs_get_directory_attribute(sf_dir_2, "legacy_sectors_per_track"), &ul0, 0)) {
ei->legacy.sectors = ul0;
}
if(ei->sectors && ei->edd.heads && ei->edd.sectors) {
ei->edd.cyls = ei->sectors / (ei->edd.heads * ei->edd.sectors);
}
sf_link = sysfs_get_directory_link(sf_dir_2, "pci_dev");
if(sf_link) {
hd_data->edd[u].sysfs_id = new_str(hd_sysfs_id(sf_link->target));
if((hd = hd_find_sysfs_id(hd_data, hd_data->edd[u].sysfs_id))) {
hd_data->edd[u].hd_idx = hd->idx;
}
}
sl = hd_attr_list(sysfs_get_directory_attribute(sf_dir_2, "extensions"));
if(search_str_list(sl, "Fixed disk access")) hd_data->edd[u].ext_fixed_disk = 1;
if(search_str_list(sl, "Device locking and ejecting")) hd_data->edd[u].ext_lock_eject = 1;
if(search_str_list(sl, "Enhanced Disk Drive support")) hd_data->edd[u].ext_edd = 1;
if(search_str_list(sl, "64-bit extensions")) hd_data->edd[u].ext_64bit = 1;
ADD2LOG(
"edd: 0x%02x\n size: %"PRIu64"\n chs default: %u/%u/%u\n chs legacy: %u/%u/%u\n caps: %s%s%s%s\n attached: #%u %s\n",
u + 0x80,
ei->sectors,
ei->edd.cyls,
ei->edd.heads,
ei->edd.sectors,
ei->legacy.cyls,
ei->legacy.heads,
ei->legacy.sectors,
ei->ext_fixed_disk ? "fixed " : "",
ei->ext_lock_eject ? "lock " : "",
ei->ext_edd ? "edd " : "",
ei->ext_64bit ? "64bit " : "",
ei->hd_idx,
ei->sysfs_id ?: ""
);
}
}
}
}
}
sysfs_close_directory(sf_dir);
if(!edd_cnt) return;
for(hd = hd_data->hd; hd; hd = hd->next) {
if(
hd->base_class.id == bc_storage_device &&
hd->sub_class.id == sc_sdev_disk
) {
hd->rom_id = free_mem(hd->rom_id);
}
}
/* add BIOS drive ids to disks */
/* first, check sysfs link */
for(u = 0; u < sizeof hd_data->edd / sizeof *hd_data->edd; u++) {
if(!hd_data->edd[u].hd_idx) continue;
for(hd = hd_data->hd; hd; hd = hd->next) {
if(
hd->base_class.id == bc_storage_device &&
hd->sub_class.id == sc_sdev_disk &&
hd->attached_to == hd_data->edd[u].hd_idx &&
!hd->rom_id
) {
str_printf(&hd->rom_id, 0, "0x%02x", u + 0x80);
hd_data->flags.edd_used = 1;
hd_data->edd[u].assigned = 1;
break;
}
}
}
/* try based on disk size */
for(u = 0; u < sizeof hd_data->edd / sizeof *hd_data->edd; u++) {
if(hd_data->edd[u].assigned) continue;
if(!(ul0 = hd_data->edd[u].sectors)) continue;
for(u1 = u2 = 0; u1 < sizeof hd_data->edd / sizeof *hd_data->edd; u1++) {
if(ul0 == hd_data->edd[u1].sectors) u2++;
}
/* more than one disk with this size */
if(u2 != 1) continue;
for(hd = hd_data->hd; hd; hd = hd->next) {
if(
hd->base_class.id == bc_storage_device &&
hd->sub_class.id == sc_sdev_disk &&
!hd->rom_id
) {
for(res = hd->res; res; res = res->next) {
if(
res->any.type == res_size &&
res->size.unit == size_unit_sectors &&
res->size.val1 == ul0
) break;
}
if(!res) continue;
str_printf(&hd->rom_id, 0, "0x%02x", u + 0x80);
hd_data->flags.edd_used = 1;
hd_data->edd[u].assigned = 1;
break;
}
}
}
/* set lba support flag in BIOS data */
for(lba = u = 0; u < sizeof hd_data->edd / sizeof *hd_data->edd; u++) {
if(hd_data->edd[u].ext_fixed_disk) {
lba = 1;
break;
}
}
if(lba) {
for(hd = hd_data->hd; hd; hd = hd->next) {
if(
hd->base_class.id == bc_internal &&
hd->sub_class.id == sc_int_bios &&
hd->detail &&
hd->detail->type == hd_detail_bios &&
(bt = hd->detail->bios.data)
) {
bt->lba_support = lba;
}
}
}
}

1
src/hwinfo/src/hd/edd.h Normal file
View File

@@ -0,0 +1 @@
void hd_scan_sysfs_edd(hd_data_t *hd_data);

136
src/hwinfo/src/hd/fb.c Normal file
View File

@@ -0,0 +1,136 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <linux/hdreg.h>
#include <linux/fb.h>
#include "hd.h"
#include "hd_int.h"
#include "fb.h"
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
*
* scan framebuffer devices
*
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
*/
typedef struct {
unsigned width;
unsigned height;
double pix_clock;
double h_freq;
double v_freq;
} fb_info_t;
static fb_info_t *fb_get_info(hd_data_t *hd_data);
void hd_scan_fb(hd_data_t *hd_data)
{
fb_info_t *fb;
hd_t *hd;
hd_res_t *res;
unsigned imac_dev, imac_vend;
unsigned imac = 0;
monitor_info_t *mi = NULL;
if(!hd_probe_feature(hd_data, pr_fb)) return;
hd_data->module = mod_fb;
/* some clean-up */
remove_hd_entries(hd_data);
PROGRESS(1, 0, "read info");
fb = fb_get_info(hd_data);
if(fb) {
imac_dev = MAKE_ID(TAG_EISA, 0x9d03);
imac_vend = name2eisa_id("APP");
for(hd = hd_data->hd; hd; hd = hd->next) {
if(hd->base_class.id == bc_monitor) break;
}
if(hd && hd->device.id == imac_dev && hd->vendor.id == imac_vend) {
hd->tag.remove = 1;
remove_tagged_hd_entries(hd_data);
imac = 1;
hd = NULL;
}
/* add monitor entry based on fb data if we have no other info */
if(!hd) {
hd = add_hd_entry(hd_data, __LINE__, 0);
hd->base_class.id = bc_monitor;
if(imac) {
hd->vendor.id = imac_vend;
hd->device.id = imac_dev;
}
else {
hd->vendor.name = new_str("Generic");
hd->device.name = new_str("Monitor");
}
res = add_res_entry(&hd->res, new_mem(sizeof *res));
res->monitor.type = res_monitor;
res->monitor.width = fb->width;
res->monitor.height = fb->height;
res->monitor.vfreq = fb->v_freq + 0.5;
if(!hd->detail) {
mi = new_mem(sizeof *mi);
hd->detail = new_mem(sizeof *hd->detail);
hd->detail->type = hd_detail_monitor;
hd->detail->monitor.data = mi;
mi->min_vsync = 50;
mi->min_hsync = 31;
mi->max_vsync = fb->v_freq * 1.11 + 0.9;
mi->max_hsync = fb->h_freq / 1000.0 + 1.9;
if(mi->max_vsync <= mi->min_vsync) mi->max_vsync = mi->min_vsync + 10;
if(mi->max_hsync <= mi->min_hsync) mi->max_hsync = mi->min_hsync + 5;
/* round up */
mi->max_vsync = ((mi->max_vsync + 9) / 10) * 10;
}
}
}
}
fb_info_t *fb_get_info(hd_data_t *hd_data)
{
int fd;
struct fb_var_screeninfo fbv_info;
static fb_info_t fb_info;
fb_info_t *fb = NULL;
int h, v;
fd = open(DEV_FB, O_RDONLY);
if(fd < 0) fd = open(DEV_FB0, O_RDONLY);
if(fd < 0) return fb;
if(!ioctl(fd, FBIOGET_VSCREENINFO, &fbv_info)) {
h = fbv_info.left_margin + fbv_info.xres + fbv_info.right_margin + fbv_info.hsync_len;
v = fbv_info.upper_margin + fbv_info.yres + fbv_info.lower_margin + fbv_info.vsync_len;
if(fbv_info.pixclock && h && v) {
fb_info.width = fbv_info.xres;
fb_info.height = fbv_info.yres;
fb_info.pix_clock = 1e12 / fbv_info.pixclock;
fb_info.h_freq = fb_info.pix_clock / h;
fb_info.v_freq = fb_info.h_freq / v;
fb = &fb_info;
ADD2LOG("fb: size %d x %d\n", fb_info.width, fb_info.height);
ADD2LOG("fb: timing %.2f MHz, %.2f kHz, %.2f Hz\n", fb_info.pix_clock * 1e-6, fb_info.h_freq * 1e-3, fb_info.v_freq);
}
}
close(fd);
return fb;
}

1
src/hwinfo/src/hd/fb.h Normal file
View File

@@ -0,0 +1 @@
void hd_scan_fb(hd_data_t *hd_data);

162
src/hwinfo/src/hd/floppy.c Normal file
View File

@@ -0,0 +1,162 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include "hd.h"
#include "hd_int.h"
#include "klog.h"
#include "floppy.h"
static void dump_floppy_data(hd_data_t *hd_data);
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
* floppy info
*
* This should currently be called *before* scan_misc() so we can try to get
* the floppy controller resources in scan_misc() by actually accessing the
* floppy drive. (Otherwise there would be a rather longish timeout.)
*
* This is all rather strange and should be rewritten...
*
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
*/
void hd_scan_floppy(hd_data_t *hd_data)
{
hd_t *hd;
char b0[10], b1[10], c;
unsigned u;
int fd, i, floppy_ctrls = 0, floppy_ctrl_idx = 0;
str_list_t *sl;
hd_res_t *res;
int floppy_stat[2] = { 1, 1 };
if(!hd_probe_feature(hd_data, pr_floppy)) return;
hd_data->module = mod_floppy;
/* some clean-up */
remove_hd_entries(hd_data);
hd_data->floppy = free_str_list(hd_data->floppy);
PROGRESS(1, 0, "get nvram");
/*
* Look for existing floppy controller entries (typically there will be
* *none*).
*/
for(hd = hd_data->hd; hd; hd = hd->next) {
if(hd->base_class.id == bc_storage && hd->sub_class.id == sc_sto_floppy) {
floppy_ctrls++;
floppy_ctrl_idx = hd->idx;
}
}
/*
* Is enough to load the nvram module.
*
* Note: although you must be root to access /dev/nvram, every
* user can read /proc/nvram.
*/
fd = open(DEV_NVRAM, O_RDONLY | O_NONBLOCK);
if(fd >= 0) close(fd);
if(
!(hd_data->floppy = read_file(PROC_NVRAM_24, 0, 0)) &&
!(hd_data->floppy = read_file(PROC_NVRAM_22, 0, 0))
);
if(hd_data->floppy && (hd_data->debug & HD_DEB_FLOPPY)) dump_floppy_data(hd_data);
if(!hd_data->klog) read_klog(hd_data);
for(sl = hd_data->klog; sl; sl = sl->next) {
if(sscanf(sl->str, "<4>floppy%u: no floppy controllers foun%c", &u, &c) == 2) {
if(u < sizeof floppy_stat / sizeof *floppy_stat) {
floppy_stat[u] = 0;
}
}
}
if(hd_data->floppy) {
PROGRESS(2, 0, "nvram info");
sl = hd_data->floppy;
}
else {
PROGRESS(2, 0, "klog info");
sl = hd_data->klog;
}
for(; sl; sl = sl->next) {
if(hd_data->floppy) {
i = sscanf(sl->str, " Floppy %u type : %8[0-9.]'' %8[0-9.]%c", &u, b0, b1, &c) == 4;
}
else {
i = sscanf(sl->str, "<6>Floppy drive(s): fd%u is %8[0-9.]%c", &u, b1, &c) == 3;
*b0 = 0;
}
if(i) {
if(
!floppy_ctrls &&
u < sizeof floppy_stat / sizeof *floppy_stat &&
floppy_stat[u]
) {
/* create one, if missing (there's no floppy without a controller...) */
hd = add_hd_entry(hd_data, __LINE__, 0);
hd->base_class.id = bc_storage;
hd->sub_class.id = sc_sto_floppy;
floppy_ctrl_idx = hd->idx;
floppy_ctrls++;
}
if(floppy_ctrls) {
hd = add_hd_entry(hd_data, __LINE__, 0);
hd->base_class.id = bc_storage_device;
hd->sub_class.id = sc_sdev_floppy;
hd->bus.id = bus_floppy;
hd->slot = u;
str_printf(&hd->unix_dev_name, 0, "/dev/fd%u", u);
if(*b0) {
res = add_res_entry(&hd->res, new_mem(sizeof *res));
res->size.type = res_size;
res->size.val1 = str2float(b0, 2);
res->size.unit = size_unit_cinch;
}
/* 'k' or 'M' */
i = c == 'M' ? str2float(b1, 3) : str2float(b1, 0);
res = add_res_entry(&hd->res, new_mem(sizeof *res));
res->size.type = res_size;
res->size.val1 = i << 1;
res->size.val2 = 0x200;
res->size.unit = size_unit_sectors;
/* the only choice... */
if(floppy_ctrls == 1) hd->attached_to = floppy_ctrl_idx;
}
}
}
}
/*
* Add floppy data to the global log.
*/
void dump_floppy_data(hd_data_t *hd_data)
{
str_list_t *sl;
ADD2LOG("----- /proc/nvram -----\n");
for(sl = hd_data->floppy; sl; sl = sl->next) {
ADD2LOG(" %s", sl->str);
}
ADD2LOG("----- /proc/nvram end -----\n");
}

View File

@@ -0,0 +1 @@
void hd_scan_floppy(hd_data_t *hd_data);

5684
src/hwinfo/src/hd/hd.c Normal file

File diff suppressed because it is too large Load Diff

2488
src/hwinfo/src/hd/hd.h Normal file

File diff suppressed because it is too large Load Diff

236
src/hwinfo/src/hd/hd_int.h Normal file
View File

@@ -0,0 +1,236 @@
#include <sysfs/dlist.h>
#include <sysfs/libsysfs.h>
#define PROC_CMDLINE "/proc/cmdline"
#define PROC_PCI_DEVICES "/proc/bus/pci/devices"
#define PROC_PCI_BUS "/proc/bus/pci"
#define PROC_CPUINFO "/proc/cpuinfo"
#define PROC_IOPORTS "/proc/ioports"
#define PROC_DMA "/proc/dma"
#define PROC_INTERRUPTS "/proc/interrupts"
#define PROC_NVRAM_22 "/proc/driver/nvram"
#define PROC_NVRAM_24 "/proc/nvram"
#define PROC_IDE "/proc/ide"
#define PROC_SCSI "/proc/scsi"
#define PROC_CDROM_INFO "/proc/sys/dev/cdrom/info"
#define PROC_NET_IF_INFO "/proc/net/dev"
#define PROC_MODULES "/proc/modules"
#define PROC_DRIVER_SERIAL "/proc/tty/driver/serial"
#define PROC_DRIVER_MACSERIAL "/proc/tty/driver/macserial"
#define PROC_PARPORT_22 "/proc/parport/" /* Final '/' is essential! */
#define PROC_PARPORT_24 "/proc/sys/dev/parport/parport"
#define PROC_KCORE "/proc/kcore"
// #define PROC_USB_DEVICES "/proc/bus/usb/devices"
#define PROC_USB_DEVICES "/proc/bus/usb/devices_please-use-sysfs-instead"
#define PROC_PROM "/proc/device-tree"
#define PROC_MEMINFO "/proc/meminfo"
#define PROC_VERSION "/proc/version"
#define PROC_ISAPNP "/proc/isapnp"
#define PROC_ISERIES "/proc/iSeries"
#define PROC_ISERIES_VETH "/proc/iSeries/veth"
#define PROC_PARTITIONS "/proc/partitions"
#define PROC_APM "/proc/apm"
#define DEV_NVRAM "/dev/nvram"
#define DEV_PSAUX "/dev/psaux"
#define DEV_ADBMOUSE "/dev/adbmouse"
#define DEV_MEM "/dev/mem"
#define DEV_KBD "/dev/kbd"
#define DEV_CONSOLE "/dev/console"
#define DEV_OPENPROM "/dev/openprom"
#define DEV_SUNMOUSE "/dev/sunmouse"
#define DEV_MICE "/dev/input/mice"
#define DEV_FB "/dev/fb"
#define DEV_FB0 "/dev/fb0"
#define PROG_MODPROBE "/sbin/modprobe"
#define PROG_RMMOD "/sbin/rmmod"
#define PROG_CARDCTL "/sbin/cardctl"
#define PROG_UDEVINFO "/usr/bin/udevinfo"
#define KLOG_BOOT "/var/log/boot.msg"
#define ISAPNP_CONF "/etc/isapnp.conf"
#define ID_LIST HARDWARE_DIR "/hd.ids"
#define LIB_CMDLINE HARDWARE_DIR "/cmdline"
#define KERNEL_22 0x020200
#define KERNEL_24 0x020400
#define KERNEL_26 0x020600
#if defined(__s390__) || defined(__s390x__) || defined(__alpha__) || defined(LIBHD_TINY)
#define WITH_ISDN 0
#else
#define WITH_ISDN 1
#endif
#define PROGRESS(a, b, c) progress(hd_data, a, b, c)
#define ADD2LOG(a...) str_printf(&hd_data->log, -2, a)
#undef LIBHD_MEMCHECK
#if defined(__i386__) || defined(__PPC__)
/*
* f: function we are in
* a: first argument
*/
#ifdef __i386__
#define CALLED_FROM(f, a) ((void *) ((unsigned *) &a)[-1] - 5)
#endif
#ifdef __PPC__
/* (1-arg funcs only) #define CALLED_FROM(f, a) ((void *) *((unsigned *) ((void *) &a - ((short *) f)[1] - 4)) - 4) */
static inline void *getr1() { void *p; asm("mr %0,1" : "=r" (p) :); return p; }
#define CALLED_FROM(f, a) ((void *) ((unsigned *) (getr1() - ((short *) f)[1]))[1] - 4)
#endif
#else
#undef LIBHD_MEMCHECK
#endif
#ifdef LIBHD_MEMCHECK
FILE *libhd_log;
#endif
/*
* define to make (hd_t).unique_id a hex string, otherwise it is a
* base64-like string
*/
#undef NUMERIC_UNIQUE_ID
/*
* Internal probing module numbers. Use mod_name_by_idx() outside of libhd.
*/
enum mod_idx {
mod_none, mod_memory, mod_pci, mod_isapnp, mod_pnpdump, mod_net,
mod_floppy, mod_misc, mod_bios, mod_cpu, mod_monitor, mod_mouse, mod_scsi,
mod_serial, mod_usb, mod_adb, mod_modem, mod_parallel, mod_isa, mod_isdn,
mod_kbd, mod_prom, mod_sbus, mod_int, mod_braille, mod_xtra, mod_sys,
mod_manual, mod_fb, mod_veth, mod_pppoe, mod_pcmcia, mod_s390,
mod_sysfs, mod_dsl, mod_block, mod_edd, mod_input, mod_wlan
};
void *new_mem(size_t size);
void *resize_mem(void *, size_t);
void *add_mem(void *, size_t, size_t);
char *new_str(const char *);
void *free_mem(void *);
int have_common_res(hd_res_t *res1, hd_res_t *res2);
void join_res_io(hd_res_t **res1, hd_res_t *res2);
void join_res_irq(hd_res_t **res1, hd_res_t *res2);
void join_res_dma(hd_res_t **res1, hd_res_t *res2);
hd_res_t *free_res_list(hd_res_t *res);
hd_res_t *add_res_entry(hd_res_t **res, hd_res_t *new_res);
hd_t *add_hd_entry(hd_data_t *hd_data, unsigned line, unsigned count);
misc_t *free_misc(misc_t *m);
scsi_t *free_scsi(scsi_t *scsi, int free_all);
hd_detail_t *free_hd_detail(hd_detail_t *d);
devtree_t *free_devtree(hd_data_t *hd_data);
void hd_add_id(hd_data_t *hd_data, hd_t *hd);
char *isa_id2str(unsigned);
char *eisa_vendor_str(unsigned);
unsigned name2eisa_id(char *);
char *canon_str(char *, int);
int hex(char *string, int digits);
void str_printf(char **buf, int offset, char *format, ...) __attribute__ ((format (printf, 3, 4)));
void hexdump(char **buf, int with_ascii, unsigned data_len, unsigned char *data);
str_list_t *search_str_list(str_list_t *sl, char *str);
str_list_t *add_str_list(str_list_t **sl, char *str);
str_list_t *free_str_list(str_list_t *list);
str_list_t *read_file(char *file_name, unsigned start_line, unsigned lines);
str_list_t *read_dir(char *dir_name, int type);
char *hd_read_symlink(char *link_name);
void progress(hd_data_t *hd_data, unsigned pos, unsigned count, char *msg);
void remove_hd_entries(hd_data_t *hd_data);
void remove_tagged_hd_entries(hd_data_t *hd_data);
driver_info_t *free_driver_info(driver_info_t *di);
int str2float(char *s, int n);
char *float2str(int i, int n);
/* return the file name of a module */
char *mod_name_by_idx(unsigned idx);
int hd_timeout(void(*func)(void *), void *arg, int timeout);
str_list_t *read_kmods(hd_data_t *hd_data);
char *get_cmd_param(hd_data_t *hd_data, int field);
#ifdef __i386__
/* smp/smp.c */
int detectSMP(void);
#endif
void update_irq_usage(hd_data_t *hd_data);
int run_cmd(hd_data_t *hd_data, char *cmd);
int load_module_with_params(hd_data_t *hd_data, char *module, char *params);
int load_module(hd_data_t *hd_data, char *module);
int unload_module(hd_data_t *hd_data, char *module);
int probe_module(hd_data_t *hd_data, char *module);
int cmp_hd(hd_t *hd1, hd_t *hd2);
unsigned has_something_attached(hd_data_t *hd_data, hd_t *hd);
str_list_t *get_cmdline(hd_data_t *hd_data, char *key);
int detect_smp_bios(hd_data_t *hd_data);
int detect_smp_prom(hd_data_t *hd_data);
unsigned char *read_block0(hd_data_t *hd_data, char *dev, int *timeout);
void hd_copy(hd_t *dst, hd_t *src);
/* parameter for gather_resources(,,, which) */
#define W_IO (1 << 0)
#define W_DMA (1 << 1)
#define W_IRQ (1 << 2)
void gather_resources(misc_t *m, hd_res_t **r, char *name, unsigned which);
char *vend_id2str(unsigned vend);
int hd_getdisksize(hd_data_t *hd_data, char *dev, int fd, hd_res_t **geo, hd_res_t **size);
str_list_t *hd_split(char del, char *str);
char *hd_join(char *del, str_list_t *str);
int is_pnpinfo(ser_device_t *mi, int ofs);
int is_pcmcia_ctrl(hd_data_t *hd_data, hd_t *hd);
void hd_fork(hd_data_t *hd_data, int timeout, int total_timeout);
void hd_fork_done(hd_data_t *hd_data);
void hd_shm_init(hd_data_t *hd_data);
void hd_shm_clean(hd_data_t *hd_data);
void hd_shm_done(hd_data_t *hd_data);
void *hd_shm_add(hd_data_t *hd_data, void *ptr, unsigned len);
int hd_is_shm_ptr(hd_data_t *hd_data, void *ptr);
void hd_move_to_shm(hd_data_t *hd_data);
void read_udevinfo(hd_data_t *hd_data);
hd_t *hd_find_sysfs_id(hd_data_t *hd_data, char *id);
int hd_attr_uint(struct sysfs_attribute *attr, uint64_t *u, int base);
char *hd_attr_str(struct sysfs_attribute *attr);
str_list_t *hd_attr_list(struct sysfs_attribute *attr);
char *hd_sysfs_id(char *path);
char *hd_sysfs_name2_dev(char *str);
char *hd_sysfs_dev2_name(char *str);
void hd_sysfs_driver_list(hd_data_t *hd_data);
char *hd_sysfs_find_driver(hd_data_t *hd_data, char *sysfs_id, int exact);
int hd_report_this(hd_data_t *hd_data, hd_t *hd);
str_list_t *hd_module_list(hd_data_t *hd_data, unsigned id);
int hd_is_iseries(hd_data_t *hd_data);
#ifdef __cplusplus
}
#endif

2748
src/hwinfo/src/hd/hddb.c Normal file

File diff suppressed because it is too large Load Diff

7
src/hwinfo/src/hd/hddb.h Normal file
View File

@@ -0,0 +1,7 @@
void hddb_init(hd_data_t *hd_data);
unsigned device_class(hd_data_t *hd_data, unsigned vendor, unsigned device);
unsigned sub_device_class(hd_data_t *hd_data, unsigned vendor, unsigned device, unsigned sub_vendor, unsigned sub_device);
char *hid_tag_name(int tag);
char *hid_tag_name2(int tag);

View File

@@ -0,0 +1,55 @@
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
*
* type defs for internal data base
*
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#define DATA_VALUE(a) ((a) & ~(-1 << 28))
#define DATA_FLAG(a) (((a) >> 28) & 0xf)
#define MAKE_DATA(a, b) ((a << 28) | (b))
#define FLAG_ID 0
#define FLAG_RANGE 1
#define FLAG_MASK 2
#define FLAG_STRING 3
#define FLAG_REGEXP 4
/* 5 - 7 reserved */
#define FLAG_CONT 8 /* bit mask, _must_ be bit 31 */
typedef enum hddb_entry_e {
he_other, he_bus_id, he_baseclass_id, he_subclass_id, he_progif_id,
he_vendor_id, he_device_id, he_subvendor_id, he_subdevice_id, he_rev_id,
he_bus_name, he_baseclass_name, he_subclass_name, he_progif_name,
he_vendor_name, he_device_name, he_subvendor_name, he_subdevice_name,
he_rev_name, he_serial, he_driver, he_requires /* 21 */,
he_detail_ccw_data_cu_model,
/* add new entries _here_! */
he_nomask,
/* if he_nomask exceeds 31, adjust entry_mask_t & hddb_entry_mask_t */
he_class_id = he_nomask, he_driver_module_insmod, he_driver_module_modprobe,
he_driver_module_config, he_driver_xfree, he_driver_xfree_config,
he_driver_mouse, he_driver_display, he_driver_any
} hddb_entry_t;
static hddb_entry_t hddb_is_numeric[] = {
he_bus_id, he_baseclass_id, he_subclass_id, he_progif_id, he_vendor_id,
he_device_id, he_subvendor_id, he_subdevice_id, he_rev_id, he_detail_ccw_data_cu_model
};
static char *hddb_entry_strings[] = {
"other", "bus.id", "baseclass.id", "subclass.id", "progif.id",
"vendor.id", "device.id", "subvendor.id", "subdevice.id", "rev.id",
"bus.name", "baseclass.name", "subclass.name", "progif.name",
"vendor.name", "device.name", "subvendor.name", "subdevice.name",
"rev.name", "serial", "driver", "requires",
"detail.ccw.data.cu_model",
"class.id", "driver.module.insmod", "driver.module.modprobe",
"driver.module.config", "driver.xfree", "driver.xfree.config",
"driver.mouse", "driver.display", "driver.any"
};

1262
src/hwinfo/src/hd/hdp.c Normal file

File diff suppressed because it is too large Load Diff

0
src/hwinfo/src/hd/hdp.h Normal file
View File

View File

@@ -0,0 +1,169 @@
{ 1024, 768, "IBM", "18305CU", NULL },
{ 1024, 768, "IBM", "1830BLU", NULL },
{ 1024, 768, "IBM", "1830H3U", NULL },
{ 1024, 768, "IBM", "1830PVU", NULL },
{ 1024, 768, "IBM", "18344AU", NULL },
{ 1024, 768, "IBM", "18344EU", NULL },
{ 1024, 768, "IBM", "183456U", NULL },
{ 1024, 768, "IBM", "18345BU", NULL },
{ 1024, 768, "IBM", "1834E7U", NULL },
{ 1024, 768, "IBM", "1834ELU", NULL },
{ 1024, 768, "IBM", "1834FKU", NULL },
{ 1024, 768, "IBM", "1834NEU", NULL },
{ 1024, 768, "IBM", "1836BAU", NULL },
{ 1024, 768, "IBM", "1836H7U", NULL },
{ 1024, 768, "IBM", "1836Q4U", NULL },
{ 1024, 768, "IBM", "18422QU", NULL },
{ 1024, 768, "IBM", "18422RU", NULL },
{ 1024, 768, "IBM", "1842G3U", NULL },
{ 1024, 768, "IBM", "1842G7U", NULL },
{ 1024, 768, "IBM", "1842GDU", NULL },
{ 1024, 768, "IBM", "1842GQU", NULL },
{ 1024, 768, "IBM", "1842GRU", NULL },
{ 1024, 768, "IBM", "1842HRU", NULL },
{ 1024, 768, "IBM", "1842PPU", NULL },
{ 1024, 768, "IBM", "185928U", NULL },
{ 1024, 768, "IBM", "18594YU", NULL },
{ 1024, 768, "IBM", "18595RU", NULL },
{ 1024, 768, "IBM", "23711CU", NULL },
{ 1024, 768, "IBM", "23716EU", NULL },
{ 1024, 768, "IBM", "23716FU", NULL },
{ 1024, 768, "IBM", "23716GU", NULL },
{ 1024, 768, "IBM", "23717GU", NULL },
{ 1024, 768, "IBM", "23718EU", NULL },
{ 1024, 768, "IBM", "237197U", NULL },
{ 1024, 768, "IBM", "2371A9U", NULL },
{ 1024, 768, "IBM", "2371GHU", NULL },
{ 1024, 768, "IBM", "23731FU", NULL },
{ 1024, 768, "IBM", "23731HU", NULL },
{ 1024, 768, "IBM", "23731WU", NULL },
{ 1024, 768, "IBM", "23734YU", NULL },
{ 1024, 768, "IBM", "23735TU", NULL },
{ 1024, 768, "IBM", "23736VU", NULL },
{ 1024, 768, "IBM", "23736YU", NULL },
{ 1024, 768, "IBM", "23737FU", NULL },
{ 1024, 768, "IBM", "2373J4U", NULL },
{ 1024, 768, "IBM", "2373JTU", NULL },
{ 1024, 768, "IBM", "2373K1U", NULL },
{ 1024, 768, "IBM", "2373L1U", NULL },
{ 1024, 768, "IBM", "23785UU", NULL },
{ 1024, 768, "IBM", "2378DGU", NULL },
{ 1024, 768, "IBM", "2378DHU", NULL },
{ 1024, 768, "IBM", "2378DTU", NULL },
{ 1024, 768, "IBM", "2378DUU", NULL },
{ 1024, 768, "IBM", "2378DWU", NULL },
{ 1024, 768, "IBM", "2378FTU", NULL },
{ 1024, 768, "IBM", "2378FZU", NULL },
{ 1024, 768, "IBM", "2378R1U", NULL },
{ 1024, 768, "IBM", "2378R4U", NULL },
{ 1024, 768, "IBM", "2378R8U", NULL },
{ 1024, 768, "IBM", "23795VU", NULL },
{ 1024, 768, "IBM", "2379DKU", NULL },
{ 1024, 768, "IBM", "2379DWU", NULL },
{ 1024, 768, "IBM", "2379R1U", NULL },
{ 1024, 768, "IBM", "2379R6U", NULL },
{ 1024, 768, "IBM", "2379R8U", NULL },
{ 1024, 768, "IBM", "23826UU", NULL },
{ 1024, 768, "IBM", "2382ECU", NULL },
{ 1024, 768, "IBM", "2382HCU", NULL },
{ 1024, 768, "IBM", "2384A9U", NULL },
{ 1024, 768, "IBM", "2384ATU", NULL },
{ 1024, 768, "IBM", "2384B9U", NULL },
{ 1024, 768, "IBM", "2384DLU", NULL },
{ 1024, 768, "IBM", "2384DWU", NULL },
{ 1024, 768, "IBM", "2384ECU", NULL },
{ 1024, 768, "IBM", "2384EHU", NULL },
{ 1024, 768, "IBM", "2384JCU", NULL },
{ 1024, 768, "IBM", "238613U", NULL },
{ 1024, 768, "IBM", "23861CU", NULL },
{ 1024, 768, "IBM", "23861ZU", NULL },
{ 1024, 768, "IBM", "23865FU", NULL },
{ 1024, 768, "IBM", "23866GU", NULL },
{ 1024, 768, "IBM", "23866RU", NULL },
{ 1024, 768, "IBM", "23866UU", NULL },
{ 1024, 768, "IBM", "23868EU", NULL },
{ 1024, 768, "IBM", "23868WU", NULL },
{ 1024, 768, "IBM", "2386A4U", NULL },
{ 1024, 768, "IBM", "2386E9U", NULL },
{ 1024, 768, "IBM", "23884QU", NULL },
{ 1024, 768, "IBM", "238852U", NULL },
{ 1024, 768, "IBM", "2388DGU", NULL },
{ 1024, 768, "IBM", "2388DMU", NULL },
{ 1024, 768, "IBM", "2388EJU", NULL },
{ 1024, 768, "IBM", "2388ENU", NULL },
{ 1024, 768, "IBM", "2388F4U", NULL },
{ 1024, 768, "IBM", "2388HBU", NULL },
{ 1024, 768, "IBM", "2388JBU", NULL },
{ 1024, 768, "IBM", "2389DHU", NULL },
{ 1024, 768, "IBM", "26284UG", NULL },
{ 1024, 768, "IBM", "26446AG", NULL },
{ 1024, 768, "IBM", "26455BG", NULL },
{ 1024, 768, "IBM", "264721G", NULL },
{ 1024, 768, "IBM", "26725KU", NULL },
{ 1024, 768, "IBM", "2672REU", NULL },
{ 1024, 768, "IBM", "2672RHU", NULL },
{ 1024, 768, "IBM", "267358U", NULL },
{ 1024, 768, "IBM", "26735KU", NULL },
{ 1024, 768, "IBM", "26817FU", NULL },
{ 1024, 768, "IBM", "2682PAU", NULL },
{ 1024, 768, "IBM", "2684FU4", NULL },
{ 1024, 768, "IBM", "2684KJU", NULL },
{ 1024, 768, "IBM", "2684QBU", NULL },
{ 1024, 768, "IBM", "27225JU", NULL },
{ 1024, 768, "IBM", "27233XU", NULL },
{ 1024, 768, "IBM", "288122U", NULL },
{ 1024, 768, "IBM", "288136U", NULL },
{ 1024, 768, "IBM", "288157U", NULL },
{ 1024, 768, "IBM", "28832ZU", NULL },
{ 1024, 768, "IBM", "28838QU", NULL },
{ 1024, 768, "IBM", "2883ARU", NULL },
{ 1024, 768, "IBM", "2883ELU", NULL },
{ 1024, 768, "IBM", "2883GKU", NULL },
{ 1024, 768, "IBM", "28854WU", NULL },
{ 1024, 768, "IBM", "2885PWU", NULL },
{ 1024, 768, "IBM", "28865TU", NULL },
{ 1024, 768, "IBM", "288692U", NULL },
{ 1024, 768, "IBM", "28872KU", NULL },
{ 1024, 768, "IBM", "288745U", NULL },
{ 1024, 768, "IBM", "288767U", NULL },
{ 1024, 768, "IBM", "28878PU", NULL },
{ 1024, 768, "IBM", "28885RU", NULL },
{ 1024, 768, "IBM", "2888M9U", NULL },
{ 1400, 1050, "IBM", "1830BQU", NULL },
{ 1400, 1050, "IBM", "18363SU", NULL },
{ 1400, 1050, "IBM", "1836H8U", NULL },
{ 1400, 1050, "IBM", "1836H9U", NULL },
{ 1400, 1050, "IBM", "1836HAU", NULL },
{ 1400, 1050, "IBM", "1836Q6U", NULL },
{ 1400, 1050, "IBM", "1836Q7U", NULL },
{ 1400, 1050, "IBM", "18594AU", NULL },
{ 1400, 1050, "IBM", "237394U", NULL },
{ 1400, 1050, "IBM", "23739FU", NULL },
{ 1400, 1050, "IBM", "2373G1U", NULL },
{ 1400, 1050, "IBM", "2373G3U", NULL },
{ 1400, 1050, "IBM", "2373GEU", NULL },
{ 1400, 1050, "IBM", "2373GGU", NULL },
{ 1400, 1050, "IBM", "2373GHG", NULL },
{ 1400, 1050, "IBM", "2373KTU", NULL },
{ 1400, 1050, "IBM", "2373KUU", NULL },
{ 1400, 1050, "IBM", "2373L4U", NULL },
{ 1400, 1050, "IBM", "2374GGG", NULL },
{ 1400, 1050, "IBM", "2378DXU", NULL },
{ 1400, 1050, "IBM", "2378FVU", NULL },
{ 1400, 1050, "IBM", "2379DJU", NULL },
{ 1400, 1050, "IBM", "2379DXU", NULL },
{ 1400, 1050, "IBM", "2379R9U", NULL },
{ 1400, 1050, "IBM", "23885DU", NULL },
{ 1400, 1050, "IBM", "2388F5U", NULL },
{ 1400, 1050, "IBM", "288678U", NULL },
{ 1400, 1050, "IBM", "288679U", NULL },
{ 1400, 1050, "IBM", "288693U", NULL },
{ 1600, 1200, "IBM", "183222U", NULL },
{ 1600, 1200, "IBM", "183223U", NULL },
{ 1600, 1200, "IBM", "2373HTU", NULL },
{ 1600, 1200, "IBM", "2373HVU", NULL },
{ 1600, 1200, "IBM", "2373KXU", NULL },
{ 1600, 1200, "IBM", "2373KYU", NULL },
{ 1600, 1200, "IBM", "2373Q1U", NULL },
{ 1600, 1200, "IBM", "2378DYU", NULL },
{ 1600, 1200, "IBM", "2379DYU", NULL },

267
src/hwinfo/src/hd/input.c Normal file
View File

@@ -0,0 +1,267 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <linux/input.h>
#include "hd.h"
#include "hd_int.h"
#include "hddb.h"
#include "input.h"
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
* input devs
*
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
*/
static void get_input_devices(hd_data_t *hd_data);
static char *all_bits(char *str);
static int test_bit(char *str, unsigned bit);
void hd_scan_input(hd_data_t *hd_data)
{
if(!hd_probe_feature(hd_data, pr_input)) return;
hd_data->module = mod_input;
/* some clean-up */
remove_hd_entries(hd_data);
PROGRESS(1, 0, "joydev mod");
load_module(hd_data, "joydev");
PROGRESS(1, 1, "evdev mod");
load_module(hd_data, "evdev");
PROGRESS(2, 0, "input");
get_input_devices(hd_data);
}
#define INP_NAME "N: Name="
#define INP_HANDLERS "H: Handlers="
#define INP_KEY "B: KEY="
#define INP_REL "B: REL="
void get_input_devices(hd_data_t *hd_data)
{
hd_t *hd;
str_list_t *input, *sl, *sl1;
char *s;
unsigned ok, u;
unsigned bus, vendor, product, version;
unsigned mouse_buttons, mouse_wheels;
char *name = NULL, *handlers = NULL, *key = NULL, *rel = NULL;
size_t len;
str_list_t *handler_list;
hd_dev_num_t dev_num = { type: 'c', range: 1 };
input = read_file("/proc/bus/input/devices", 0, 0);
ADD2LOG("----- /proc/bus/input/devices -----\n");
for(sl = input; sl; sl = sl->next) {
ADD2LOG(" %s", sl->str);
}
ADD2LOG("----- /proc/bus/input/devices end -----\n");
for(ok = 0, sl = input; sl; sl = sl->next) {
if(*sl->str == '\n') {
ADD2LOG("bus = %u, name = %s\n", bus, name);
if(handlers) ADD2LOG(" handlers = %s\n", handlers);
if(key) ADD2LOG(" key = %s\n", key);
if(rel) ADD2LOG(" rel = %s\n", rel);
mouse_buttons = 0;
if(key) {
for(u = BTN_MOUSE; u < BTN_MOUSE + 8; u++) {
if(test_bit(key, u)) mouse_buttons++;
}
}
ADD2LOG(" mouse buttons = %u\n", mouse_buttons);
mouse_wheels = 0;
if(rel) {
for(u = REL_HWHEEL; u <= REL_MAX; u++) {
if(test_bit(rel, u)) mouse_wheels++;
}
}
ADD2LOG(" mouse wheels = %u\n", mouse_wheels);
if(ok && handlers) {
handler_list = hd_split(' ', handlers);
if(bus == BUS_USB) {
s = NULL;
for(sl1 = handler_list; sl1; sl1 = sl1->next) {
if(sscanf(sl1->str, "mouse%u", &u) == 1) {
str_printf(&s, 0, "/dev/input/mouse%u", u);
break;
}
}
if(s) {
for(hd = hd_data->hd; hd; hd = hd->next) {
if(hd->unix_dev_name2 && !strcmp(hd->unix_dev_name2, s)) {
hd->compat_vendor.id = MAKE_ID(TAG_SPECIAL, 0x0210);
hd->compat_device.id = MAKE_ID(TAG_SPECIAL, (mouse_wheels << 4) + mouse_buttons);
}
}
}
s = free_mem(s);
}
else {
if(search_str_list(handler_list, "kbd") && test_bit(key, KEY_1)) {
hd = add_hd_entry(hd_data, __LINE__, 0);
hd->base_class.id = bc_keyboard;
hd->sub_class.id = sc_keyboard_kbd;
hd->bus.id = bus_ps2;
hd->vendor.id = MAKE_ID(TAG_SPECIAL, 0x0211);
hd->device.id = MAKE_ID(TAG_SPECIAL, 0x0001);
hd->device.name = new_str(name);
for(sl1 = handler_list; sl1; sl1 = sl1->next) {
if(sscanf(sl1->str, "event%u", &u) == 1) {
str_printf(&hd->unix_dev_name, 0, "/dev/input/event%u", u);
dev_num.major = 13;
dev_num.minor = 64 + u;
hd->unix_dev_num = dev_num;
break;
}
}
}
else if(strstr(handlers, "mouse")) {
hd = add_hd_entry(hd_data, __LINE__, 0);
hd->base_class.id = bc_mouse;
hd->sub_class.id = sc_mou_ps2;
hd->bus.id = bus_ps2;
hd->vendor.id = MAKE_ID(TAG_SPECIAL, 0x0210);
hd->device.id = MAKE_ID(TAG_SPECIAL, (mouse_wheels << 4) + mouse_buttons);
hd->device.name = new_str(name);
/* Synaptics/Alps TouchPad */
if(vendor == 2 && (product == 7 || product == 8)) {
hd->compat_vendor.id = hd->vendor.id;
hd->compat_device.id = hd->device.id;
hd->vendor.id = MAKE_ID(TAG_SPECIAL, 0x0212);
hd->device.id = MAKE_ID(TAG_SPECIAL, product - 6);
}
hd->unix_dev_name = new_str(DEV_MICE);
dev_num.major = 13;
dev_num.minor = 63;
hd->unix_dev_num = dev_num;
for(sl1 = handler_list; sl1; sl1 = sl1->next) {
if(sscanf(sl1->str, "mouse%u", &u) == 1) {
str_printf(&hd->unix_dev_name2, 0, "/dev/input/mouse%u", u);
dev_num.major = 13;
dev_num.minor = 32 + u;
hd->unix_dev_num2 = dev_num;
break;
}
}
}
}
handler_list = free_str_list(handler_list);
}
ok = 0;
name = free_mem(name);
handlers = free_mem(handlers);
key = free_mem(key);
rel = free_mem(rel);
}
if(sscanf(sl->str, "I: Bus=%04x Vendor=%04x Product=%04x Version=%04x", &bus, &vendor, &product, &version) == 4) {
ok = 1;
continue;
}
if(!strncmp(sl->str, INP_NAME, sizeof INP_NAME - 1)) {
s = sl->str + sizeof INP_NAME;
len = strlen(s);
if(len > 2) {
name = canon_str(s, len - 2);
}
continue;
}
if(!strncmp(sl->str, INP_HANDLERS, sizeof INP_HANDLERS - 1)) {
s = sl->str + sizeof INP_HANDLERS - 1;
handlers = canon_str(s, strlen(s));
continue;
}
if(!strncmp(sl->str, INP_KEY, sizeof INP_KEY - 1)) {
s = sl->str + sizeof INP_KEY - 1;
key = canon_str(s, strlen(s));
key = all_bits(key);
continue;
}
if(!strncmp(sl->str, INP_REL, sizeof INP_REL - 1)) {
s = sl->str + sizeof INP_REL - 1;
rel = canon_str(s, strlen(s));
rel = all_bits(rel);
continue;
}
}
free_str_list(input);
}
char *all_bits(char *str)
{
str_list_t *sl, *sl0;
char *s = NULL;
unsigned u;
if(!str) return NULL;
sl = sl0 = hd_split(' ', str);
for(; sl; sl = sl->next) {
u = strtoul(sl->str, NULL, 16);
str_printf(&s, -1, "%08x", u);
}
free_str_list(sl0);
free_mem(str);
return s;
}
int test_bit(char *str, unsigned bit)
{
size_t len, ofs;
unsigned u, mask;
if(!str) return 0;
len = strlen(str);
ofs = bit >> 2;
mask = 1 << (bit & 3);
if(ofs >= len) return 0;
ofs = len - ofs - 1;
u = str[ofs] >= 'a' ? str[ofs] - 'a' + 10 : str[ofs] - '0';
return (u & mask) ? 1 : 0;
}

View File

@@ -0,0 +1 @@
void hd_scan_input(hd_data_t *hd_data);

1147
src/hwinfo/src/hd/int.c Normal file

File diff suppressed because it is too large Load Diff

1
src/hwinfo/src/hd/int.h Normal file
View File

@@ -0,0 +1 @@
void hd_scan_int(hd_data_t *hd_data);

114
src/hwinfo/src/hd/isa.c Normal file
View File

@@ -0,0 +1,114 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "hd.h"
#include "hd_int.h"
#include "isa.h"
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
* isa cards
*
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
*/
#if defined(__i386__)
static void scan_isa_isdn(hd_data_t *hd_data);
static isa_isdn_t *free_isa_isdn(isa_isdn_t *ii);
static void dump_isa_isdn_data(hd_data_t *hd_data, isa_isdn_t *ii);
void hd_scan_isa(hd_data_t *hd_data)
{
if(!hd_probe_feature(hd_data, pr_isa)) return;
hd_data->module = mod_isa;
/* some clean-up */
remove_hd_entries(hd_data);
// hd_data->isa = NULL;
if(hd_probe_feature(hd_data, pr_isa_isdn)) {
scan_isa_isdn(hd_data);
}
}
void scan_isa_isdn(hd_data_t *hd_data)
{
isa_isdn_t *ii0, *ii;
hd_t *hd;
hd_res_t *res;
PROGRESS(1, 0, "isdn");
ii0 = isdn_detect();
dump_isa_isdn_data(hd_data, ii0);
PROGRESS(1, 1, "isdn");
for(ii = ii0; ii; ii = ii->next) {
hd = add_hd_entry(hd_data, __LINE__, 0);
hd->bus.id = bus_isa;
hd->base_class.id = bc_isdn;
hd->vendor.id = MAKE_ID(TAG_SPECIAL, 0x3000 + ii->type);
hd->device.id = MAKE_ID(TAG_SPECIAL, ((ii->type << 8) + (ii->subtype & 0xff)) & 0xffff);
if(ii->has_io) {
res = add_res_entry(&hd->res, new_mem(sizeof *res));
res->io.type = res_io;
res->io.enabled = 1;
res->io.base = ii->io;
res->io.access = acc_rw;
}
if(ii->has_irq) {
res = add_res_entry(&hd->res, new_mem(sizeof *res));
res->irq.type = res_irq;
res->irq.enabled = 1;
res->irq.base = ii->irq;
}
// #### ask libihw? -> isdn.c
}
free_isa_isdn(ii0);
}
isa_isdn_t *new_isa_isdn(isa_isdn_t **ii)
{
while(*ii) ii = &(*ii)->next;
return *ii = new_mem(sizeof **ii);
}
isa_isdn_t *free_isa_isdn(isa_isdn_t *ii)
{
isa_isdn_t *l;
for(; ii; ii = (l = ii)->next, free_mem(l));
return NULL;
}
void dump_isa_isdn_data(hd_data_t *hd_data, isa_isdn_t *ii)
{
ADD2LOG("---------- ISA ISDN raw data ----------\n");
for(; ii; ii = ii->next) {
ADD2LOG(" type %d, subtype %d", ii->type, ii->subtype);
if(ii->has_mem) ADD2LOG(", mem 0x%04x", ii->mem);
if(ii->has_io) ADD2LOG(", io 0x%04x", ii->io);
if(ii->has_irq) ADD2LOG(", irq %d", ii->irq);
ADD2LOG("\n");
}
ADD2LOG("---------- ISA ISDN raw data end ----------\n");
}
#endif /* defined(__i386__) */

12
src/hwinfo/src/hd/isa.h Normal file
View File

@@ -0,0 +1,12 @@
typedef struct isa_isdn_s {
struct isa_isdn_s *next;
unsigned has_mem:1, has_io:1, has_irq:1;
unsigned type, subtype, mem, io, irq;
} isa_isdn_t;
isa_isdn_t *new_isa_isdn(isa_isdn_t **ii);
void hd_scan_isa(hd_data_t *hd_data);
isa_isdn_t *isdn_detect(void);

438
src/hwinfo/src/hd/isapnp.c Normal file
View File

@@ -0,0 +1,438 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "hd.h"
#include "hd_int.h"
#include "hddb.h"
#include "isapnp.h"
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
* isapnp stuff
*
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
*/
#if defined(__i386__) || defined(__alpha__)
static void get_pnp_devs(hd_data_t *hd_data);
#if 0
static void get_read_port(hd_data_t *hd_data, isapnp_t *);
static void build_list(hd_data_t *hd_data, str_list_t *isapnp_list);
#endif
void hd_scan_isapnp(hd_data_t *hd_data)
{
#if 0
hd_t *hd;
hd_res_t *res;
int isapnp_ok;
str_list_t *isapnp_list = NULL, *sl;
#endif
if(!hd_probe_feature(hd_data, pr_isapnp)) return;
hd_data->module = mod_isapnp;
/* some clean-up */
remove_hd_entries(hd_data);
PROGRESS(1, 0, "pnp devices");
get_pnp_devs(hd_data);
#if 0
PROGRESS(1, 0, "read port");
if(!hd_data->isapnp) {
hd_data->isapnp = new_mem(sizeof *hd_data->isapnp);
}
else {
hd_data->isapnp->cards = 0;
/* just in case... */
hd_data->isapnp->card = free_mem(hd_data->isapnp->card);
/* keep the port */
}
if(!hd_data->isapnp->read_port) get_read_port(hd_data, hd_data->isapnp);
PROGRESS(3, 0, "get pnp data");
isapnp_list = read_file(PROC_ISAPNP, 0, 0);
if((hd_data->debug & HD_DEB_ISAPNP)) {
ADD2LOG("----- %s -----\n", PROC_ISAPNP);
for(sl = isapnp_list; sl; sl = sl->next) {
ADD2LOG(" %s", sl->str);
}
ADD2LOG("----- %s end -----\n", PROC_ISAPNP);
}
isapnp_ok = isapnp_list && hd_data->isapnp->read_port ? 1 : 1;
PROGRESS(4, 0, "build list");
if(isapnp_ok) {
hd = add_hd_entry(hd_data, __LINE__, 0);
hd->bus.id = bus_isa;
hd->base_class.id = bc_internal;
hd->sub_class.id = sc_int_isapnp_if;
res = add_res_entry(&hd->res, new_mem(sizeof *res));
res->io.type = res_io;
res->io.enabled = 1;
res->io.base = ISAPNP_ADDR_PORT;
res->io.range = 1;
res->io.access = acc_wo;
res = add_res_entry(&hd->res, new_mem(sizeof *res));
res->io.type = res_io;
res->io.enabled = 1;
res->io.base = ISAPNP_DATA_PORT;
res->io.range = 1;
res->io.access = acc_wo;
res = add_res_entry(&hd->res, new_mem(sizeof *res));
res->io.type = res_io;
res->io.enabled = 1;
res->io.base = hd_data->isapnp->read_port;
res->io.range = 1;
res->io.access = acc_ro;
}
build_list(hd_data, isapnp_list);
free_str_list(isapnp_list);
#endif
}
void get_pnp_devs(hd_data_t *hd_data)
{
hd_t *hd;
char *s, *t, buf[4];
unsigned u1, u2, u3;
struct sysfs_bus *sf_bus;
struct dlist *sf_dev_list;
struct sysfs_device *sf_dev;
struct sysfs_device *sf_dev_2;
sf_bus = sysfs_open_bus("pnp");
if(!sf_bus) {
ADD2LOG("sysfs: no such bus: pnp\n");
return;
}
sf_dev_list = sysfs_get_bus_devices(sf_bus);
if(sf_dev_list) dlist_for_each_data(sf_dev_list, sf_dev, struct sysfs_device) {
ADD2LOG(
" pnp device: name = %s, bus_id = %s, bus = %s\n path = %s\n",
sf_dev->name,
sf_dev->bus_id,
sf_dev->bus,
hd_sysfs_id(sf_dev->path)
);
if((s = hd_attr_str(sysfs_get_device_attr(sf_dev, "id")))) {
if(sscanf(s, "%3s%4x", buf, &u1) == 2 && (u2 = name2eisa_id(buf))) {
ADD2LOG(" id = %s %04x\n", eisa_vendor_str(u2), u1);
hd = add_hd_entry(hd_data, __LINE__, 0);
hd->sysfs_id = new_str(hd_sysfs_id(sf_dev->path));
hd->sysfs_bus_id = new_str(sf_dev->bus_id);
hd->bus.id = bus_isa;
hd->is.isapnp = 1;
hd->sub_vendor.id = u2;
hd->sub_device.id = MAKE_ID(TAG_EISA, u1);
if(sscanf(hd->sysfs_bus_id, "%2x:%2x.%2x", &u1, &u2, &u3) == 3) {
hd->slot = u2;
hd->func = u3;
}
s = new_str(sf_dev->path);
if((t = strrchr(s, '/'))) *t = 0;
sf_dev_2 = sysfs_open_device_path(s);
if(sf_dev_2) {
if((t = hd_attr_str(sysfs_get_device_attr(sf_dev_2, "card_id")))) {
if(sscanf(t, "%3s%4x", buf, &u1) == 2 && (u2 = name2eisa_id(buf))) {
ADD2LOG(" card id = %s %04x\n", eisa_vendor_str(u2), u1);
hd->vendor.id = u2;
hd->device.id = MAKE_ID(TAG_EISA, u1);
}
}
if((t = hd_attr_str(sysfs_get_device_attr(sf_dev_2, "name")))) {
hd->device.name = canon_str(t, strlen(t));
if(!strcasecmp(hd->device.name, "unknown")) {
hd->device.name = free_mem(hd->device.name);
}
}
sysfs_close_device(sf_dev_2);
}
free_mem(s);
if(hd->sub_vendor.id == hd->vendor.id && hd->sub_device.id == hd->device.id) {
hd->sub_vendor.id = hd->sub_device.id = 0;
}
}
}
}
sysfs_close_bus(sf_bus);
}
#if 0
unsigned char *add_isapnp_card_res(isapnp_card_t *ic, int len, int type)
{
ic->res = add_mem(ic->res, sizeof *ic->res, ic->res_len);
ic->res[ic->res_len].len = len;
ic->res[ic->res_len].type = type;
ic->res[ic->res_len].data = new_mem(len);
if(type == RES_LOG_DEV_ID) { /* logical device id */
ic->log_devs++;
}
return ic->res[ic->res_len++].data;
}
isapnp_card_t *add_isapnp_card(isapnp_t *ip, int csn)
{
isapnp_card_t *c;
ip->card = add_mem(ip->card, sizeof *ip->card, ip->cards);
c = ip->card + ip->cards++;
c->csn = csn;
c->serial = new_mem(sizeof *c->serial * 8);
c->card_regs = new_mem(sizeof *c->card_regs * 0x30);
return c;
}
void get_read_port(hd_data_t *hd_data, isapnp_t *p)
{
hd_res_t *res;
p->read_port = 0;
res = NULL;
gather_resources(hd_data->misc, &res, "ISAPnP", W_IO);
if(res && res->any.type == res_io) p->read_port = res->io.base;
free_res_list(res);
}
void build_list(hd_data_t *hd_data, str_list_t *isapnp_list)
{
hd_t *hd = NULL;
str_list_t *sl;
char s1[4], s2[100];
int card, ldev, cdev_id, ldev_active = 0;
char *dev_name = NULL, *ldev_name = NULL;
unsigned dev_id = 0, vend_id = 0, base_class = 0, sub_class = 0, ldev_id;
unsigned u, ux[5];
int i, j;
hd_res_t *res;
for(sl = isapnp_list; sl; sl = sl->next) {
if(sscanf(sl->str, "Card %d '%3s%4x:%99[^']", &card, s1, &dev_id, s2) == 4) {
// ADD2LOG("\n\n** card %d >%s< %04x >%s<**\n", card, s1, dev_id, s2);
dev_name = free_mem(dev_name);
if(strcmp(s2, "Unknown")) dev_name = new_str(s2);
dev_id = MAKE_ID(TAG_EISA, dev_id);
vend_id = name2eisa_id(s1);
base_class = sub_class = 0;
if((u = device_class(hd_data, vend_id, dev_id))) {
base_class = u >> 8;
sub_class = u & 0xff;
}
#if 0
// ########## FIXME
if(
(ID_VALUE(vend_id) || ID_VALUE(dev_id)) &&
!((db_name = hd_device_name(hd_data, vend_id, dev_id)) && *db_name)
) {
if(dev_name) {
add_device_name(hd_data, vend_id, dev_id, dev_name);
}
}
#endif
continue;
}
if(sscanf(sl->str, " Logical device %d '%3s%4x:%99[^']", &ldev, s1, &ldev_id, s2) == 4) {
// ADD2LOG("\n\n** ldev %d >%s< %04x >%s<**\n", ldev, s1, ldev_id, s2);
ldev_name = free_mem(ldev_name);
if(strcmp(s2, "Unknown")) ldev_name = new_str(s2);
hd = add_hd_entry(hd_data, __LINE__, 0);
hd->bus.id = bus_isa;
hd->is.isapnp = 1;
hd->slot = card;
hd->func = ldev;
hd->vendor.id = vend_id;
hd->device.id = dev_id;
hd->base_class.id = base_class;
hd->sub_class.id = sub_class;
hd->sub_device.id = MAKE_ID(TAG_EISA, ldev_id);
hd->sub_vendor.id = name2eisa_id(s1);
if(hd->sub_vendor.id == hd->vendor.id && hd->sub_device.id == hd->device.id) {
hd->sub_vendor.id = hd->sub_device.id = 0;
}
if((u = sub_device_class(hd_data, hd->vendor.id, hd->device.id, hd->sub_vendor.id, hd->sub_device.id))) {
hd->base_class.id = u >> 8;
hd->sub_class.id = u & 0xff;
}
#if 0
# ############# FIXME
if(
(ID_VALUE(hd->sub_vendor.id) || ID_VALUE(hd->sub_device.id)) &&
!hd_sub_device_name(hd_data, hd->vend, hd->dev, hd->sub_vend, hd->sub_device.id)
) {
if(ldev_name) {
add_sub_device_name(hd_data, hd->vend, hd->dev, hd->sub_vend, hd->sub_device.id, ldev_name);
}
}
#endif
continue;
}
if(strstr(sl->str, "Device is not active")) {
ldev_active = 0;
continue;
}
if(strstr(sl->str, "Device is active")) {
ldev_active = 1;
continue;
}
if(hd && sscanf(sl->str, " Compatible device %3s%4x", s1, &cdev_id) == 2) {
// ADD2LOG("\n\n** cdev >%s< %04x **\n", s1, cdev_id);
hd->compat_device.id = MAKE_ID(TAG_EISA, cdev_id);
hd->compat_vendor.id = name2eisa_id(s1);
if(!(hd->base_class.id || hd->sub_class.id)) {
if((u = device_class(hd_data, hd->compat_vendor.id, hd->compat_device.id))) {
hd->base_class.id = u >> 8;
hd->sub_class.id = u & 0xff;
}
else if(hd->compat_vendor.id == MAKE_ID(TAG_EISA, 0x41d0)) {
/* 0x41d0 is 'PNP' */
switch((hd->compat_device.id >> 12) & 0xf) {
case 8:
hd->base_class.id = bc_network;
hd->sub_class.id = 0x80;
break;
case 0xa:
hd->base_class.id = bc_storage;
hd->sub_class.id = 0x80;
break;
case 0xb:
hd->base_class.id = bc_multimedia;
hd->sub_class.id = 0x80;
break;
case 0xc:
case 0xd:
hd->base_class.id = bc_modem;
break;
}
}
}
continue;
}
if(
hd &&
(j = sscanf(sl->str,
" Active port %x, %x, %x, %x, %x, %x",
ux, ux + 1, ux + 2, ux + 3, ux + 4, ux + 5
)) >= 1
) {
for(i = 0; i < j; i++) {
res = add_res_entry(&hd->res, new_mem(sizeof *res));
res->io.type = res_io;
res->io.enabled = ldev_active ? 1 : 0;
res->io.base = ux[i];
res->io.access = acc_rw;
}
continue;
}
if(hd && (j = sscanf(sl->str, " Active IRQ %d [%x], %d [%x]", ux, ux + 1, ux + 2, ux + 3)) >= 1) {
for(i = 0; i < j; i += 2) {
res = add_res_entry(&hd->res, new_mem(sizeof *res));
res->irq.type = res_irq;
res->irq.enabled = ldev_active ? 1 : 0;
res->irq.base = ux[i];
}
continue;
}
if(hd && (j = sscanf(sl->str, " Active DMA %d, %d", ux, ux + 1)) >= 1) {
for(i = 0; i < j; i++) {
res = add_res_entry(&hd->res, new_mem(sizeof *res));
res->dma.type = res_dma;
res->dma.enabled = ldev_active ? 1 : 0;
res->dma.base = ux[i];
}
continue;
}
}
free_mem(dev_name);
free_mem(ldev_name);
}
#endif
#endif /* defined(__i386__) || defined(__alpha__) */

View File

@@ -0,0 +1,57 @@
/*
* These are fixed and write only. Reads are done from a port with a
* relocatable address...
*/
#define ISAPNP_ADDR_PORT 0x279
#define ISAPNP_DATA_PORT 0xa79
/*
* ISA PnP resource types
*/
#define RES_PNP_VERSION 0x01
#define RES_LOG_DEV_ID 0x02
#define RES_COMPAT_DEV_ID 0x03
#define RES_IRQ 0x04
#define RES_DMA 0x05
#define RES_START_DEP 0x06
#define RES_END_DEP 0x07
#define RES_IO 0x08
#define RES_FIXED_IO 0x09
#define RES_VENDOR_SMALL 0x0e
#define RES_END 0x0f
#define RES_MEM_RANGE 0x81
#define RES_ANSI_NAME 0x82
#define RES_UNICODE_NAME 0x83
#define RES_VENDOR_LARGE 0x84
#define RES_MEM32_RANGE 0x85
#define RES_FIXED_MEM32_RANGE 0x86
/*
* ISA PnP configuration regs
*/
#define CFG_MEM24 0x40
#define CFG_MEM32_0 0x76
#define CFG_MEM32_1 0x80
#define CFG_MEM32_2 0x90
#define CFG_MEM32_3 0xa0
#define CFG_IO_HI_BASE 0x60
#define CFG_IO_LO_BASE 0x61
#define CFG_IRQ 0x70
#define CFG_IRQ_TYPE 0x71
#define CFG_DMA 0x74
/* gather ISA-PnP info */
void hd_scan_isapnp(hd_data_t *hd_data);
/*
* Interface functions to the pnpdump lib.
*/
int pnpdump(hd_data_t *hd_data, int read_boards);
unsigned char *add_isapnp_card_res(isapnp_card_t *, int, int);
isapnp_card_t *add_isapnp_card(isapnp_t *, int);

311
src/hwinfo/src/hd/isdn.c Normal file
View File

@@ -0,0 +1,311 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "hd.h"
#include "hd_int.h"
#include "isdn.h"
#undef ISDN_TEST
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
* identify isdn cards
*
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
*/
#ifndef LIBHD_TINY
#if !defined(__s390__) && !defined(__s390x__) && !defined(__alpha__)
void hd_scan_isdn(hd_data_t *hd_data)
{
hd_t *hd;
cdb_isdn_card *cic;
if(!hd_probe_feature(hd_data, pr_isdn)) return;
hd_data->module = mod_isdn;
/* some clean-up */
remove_hd_entries(hd_data);
PROGRESS(1, 0, "list");
#ifdef ISDN_TEST
{
hd_res_t *res;
hd = add_hd_entry(hd_data, __LINE__, 0);
hd->bus.id = bus_isa;
hd->base_class.id = bc_isdn;
hd->vendor.id = MAKE_ID(TAG_SPECIAL, 0x3005);
hd->device.id = MAKE_ID(TAG_SPECIAL, 0x0500); // type, subtype
res = add_res_entry(&hd->res, new_mem(sizeof *res));
res->io.type = res_io;
res->io.enabled = 1;
res->io.base = 0x0300;
res->io.access = acc_rw;
hd = add_hd_entry(hd_data, __LINE__, 0);
hd->bus.id = bus_isa;
hd->base_class.id = bc_isdn;
hd->vendor.id = MAKE_ID(TAG_EISA, 0x1593);
hd->device.id = MAKE_ID(TAG_EISA, 0x0133); // type, subtype
res = add_res_entry(&hd->res, new_mem(sizeof *res));
res->io.type = res_io;
res->io.enabled = 1;
res->io.base = 0x0240;
res->io.access = acc_rw;
res = add_res_entry(&hd->res, new_mem(sizeof *res));
res->irq.type = res_irq;
res->irq.enabled = 1;
res->irq.base = 99;
hd = add_hd_entry(hd_data, __LINE__, 0);
hd->bus.id = bus_isa;
hd->base_class.id = bc_isdn;
hd->vendor.id = MAKE_ID(TAG_EISA, 0x0e98);
hd->device.id = MAKE_ID(TAG_EISA, 0x0000); // type, subtype
res = add_res_entry(&hd->res, new_mem(sizeof *res));
res->io.type = res_io;
res->io.enabled = 1;
res->io.base = 0x0180;
res->io.access = acc_rw;
res = add_res_entry(&hd->res, new_mem(sizeof *res));
res->io.type = res_io;
res->io.enabled = 1;
res->io.base = 0x0540;
res->io.access = acc_rw;
res = add_res_entry(&hd->res, new_mem(sizeof *res));
res->irq.type = res_irq;
res->irq.enabled = 1;
res->irq.base = 77;
hd = add_hd_entry(hd_data, __LINE__, 0);
hd->bus.id = bus_pci;
hd->base_class.id = bc_isdn;
hd->vendor.id = MAKE_ID(TAG_PCI, 0x1244);
hd->device.id = MAKE_ID(TAG_PCI, 0x0a00); // type, subtype
res = add_res_entry(&hd->res, new_mem(sizeof *res));
res->io.type = res_io;
res->io.enabled = 1;
res->io.base = 0xe000;
res->io.access = acc_rw;
hd = add_hd_entry(hd_data, __LINE__, 0);
hd->bus.id = bus_isa;
hd->base_class.id = bc_isdn;
hd->vendor.id = MAKE_ID(TAG_SPECIAL, 0x3001);
hd->device.id = MAKE_ID(TAG_SPECIAL, 0x0100); // type, subtype
res = add_res_entry(&hd->res, new_mem(sizeof *res));
res->io.type = res_io;
res->io.enabled = 1;
res->io.base = 0xe80;
res->io.access = acc_rw;
hd = add_hd_entry(hd_data, __LINE__, 0);
hd->bus.id = bus_isa;
hd->base_class.id = bc_isdn;
hd->vendor.id = MAKE_ID(TAG_SPECIAL, 0x3000);
hd->device.id = MAKE_ID(TAG_SPECIAL, 0x1a00); // type, subtype
res = add_res_entry(&hd->res, new_mem(sizeof *res));
res->io.type = res_io;
res->io.enabled = 1;
res->io.base = 0x400;
res->io.access = acc_rw;
}
#endif
for(hd = hd_data->hd; hd; hd = hd->next) {
if((cic = get_isdn_info(hd))) {
hd->base_class.id = bc_isdn;
hd->sub_class.id = 0;
free_mem(cic);
}
}
}
cdb_isdn_card *get_isdn_info(hd_t *hd)
{
cdb_isdn_card *cic0, *cic;
unsigned u0, u1;
if(hd->bus.id == bus_pci ||
hd->bus.id == bus_isa ||
hd->bus.id == bus_usb ||
hd->bus.id == bus_pcmcia ||
hd->bus.id == bus_cardbus) {
cic = NULL;
u0 = ID_VALUE(hd->vendor.id);
if(
hd->bus.id == bus_isa &&
ID_TAG(hd->vendor.id) == TAG_SPECIAL &&
u0 >= 0x3000 && u0 <= 0x3006 &&
ID_TAG(hd->device.id) == TAG_SPECIAL
) {
u0 = ID_VALUE(hd->device.id);
cic = hd_cdbisdn_get_card_from_type(u0 >> 8, u0 & 0xff);
}
if(
hd->bus.id == bus_isa &&
ID_TAG(hd->vendor.id) == TAG_EISA &&
ID_TAG(hd->device.id) == TAG_EISA
) {
u0 = ID_VALUE(hd->vendor.id);
u1 = ID_VALUE(hd->device.id);
cic = hd_cdbisdn_get_card_from_id(((u0 & 0xff) << 8) + ((u0 >> 8) & 0xff),
((u1 & 0xff) << 8) + ((u1 >> 8) & 0xff),
0xffff,0xffff);
}
if(hd->bus.id == bus_pci) {
cic = hd_cdbisdn_get_card_from_id(ID_VALUE(hd->vendor.id), ID_VALUE(hd->device.id),
ID_VALUE(hd->sub_vendor.id), ID_VALUE(hd->sub_device.id));
}
if(hd->bus.id == bus_usb &&
ID_TAG(hd->vendor.id) == TAG_USB &&
ID_TAG(hd->device.id) == TAG_USB) {
if (hd->revision.id == 0 && hd->revision.name) {
/* the revision is usually saved as string (1.00) */
sscanf(hd->revision.name, "%x.%x", &u1, &u0);
u0 = u0 | u1 << 8;
} else
u0 = ID_VALUE(hd->revision.id);
cic = hd_cdbisdn_get_card_from_id(ID_VALUE(hd->vendor.id), ID_VALUE(hd->device.id),
u0, 0xffff);
if (!cic) /* to get cards without revision info in database */
cic = hd_cdbisdn_get_card_from_id(ID_VALUE(hd->vendor.id), ID_VALUE(hd->device.id),
0xffff, 0xffff);
}
if((hd->bus.id == bus_pcmcia || hd->bus.id == bus_cardbus) &&
(hd->base_class.id == bc_network || hd->base_class.id == bc_isdn)) {
if (hd->drivers && hd->drivers->str) {
if (0 == strcmp(hd->drivers->str, "teles_cs")) {
cic = hd_cdbisdn_get_card_from_type(8, 0);
} else if (0 == strcmp(hd->drivers->str, "sedlbauer_cs")) {
cic = hd_cdbisdn_get_card_from_type(22, 2);
} else if (0 == strcmp(hd->drivers->str, "avma1_cs")) {
cic = hd_cdbisdn_get_card_from_type(26, 0);
} else if (0 == strcmp(hd->drivers->str, "fcpcmcia_cs")) {
cic = hd_cdbisdn_get_card_from_type(8002, 5);
} else if (0 == strcmp(hd->drivers->str, "elsa_cs")) {
cic = hd_cdbisdn_get_card_from_type(10, 11);
} else if (0 == strcmp(hd->drivers->str, "avm_cs")) {
cic = hd_cdbisdn_get_card_from_type(8001, 2);
}
}
}
if (cic && cic->Class && strcmp(cic->Class, "DSL")) {
cic0 = new_mem(sizeof *cic0);
memcpy(cic0, cic, sizeof *cic0);
return cic0;
}
}
return NULL;
}
void hd_scan_dsl(hd_data_t *hd_data)
{
hd_t *hd;
cdb_isdn_card *cic;
if(!hd_probe_feature(hd_data, pr_isdn)) return;
hd_data->module = mod_dsl;
/* some clean-up */
remove_hd_entries(hd_data);
PROGRESS(1, 0, "list");
#ifdef DSL_TEST
{
hd_res_t *res;
hd = add_hd_entry(hd_data, __LINE__, 0);
hd->bus.id = bus_pci;
hd->base_class.id = bc_dsl;
hd->vendor.id = MAKE_ID(TAG_SPECIAL, 0x1244);
hd->device.id = MAKE_ID(TAG_SPECIAL, 0x2700); // type, subtype
}
#endif
for(hd = hd_data->hd; hd; hd = hd->next) {
if((cic = get_dsl_info(hd))) {
free_mem(cic);
}
}
}
cdb_isdn_card *get_dsl_info(hd_t *hd)
{
cdb_isdn_card *cic0, *cic;
cdb_isdn_vario *civ;
unsigned u0, u1;
if(hd->bus.id == bus_pci ||
hd->bus.id == bus_usb) {
cic = NULL;
if(hd->bus.id == bus_pci) {
cic = hd_cdbisdn_get_card_from_id(ID_VALUE(hd->vendor.id), ID_VALUE(hd->device.id),
ID_VALUE(hd->sub_vendor.id), ID_VALUE(hd->sub_device.id));
}
if(hd->bus.id == bus_usb &&
ID_TAG(hd->vendor.id) == TAG_USB &&
ID_TAG(hd->device.id) == TAG_USB) {
if (hd->revision.id == 0 && hd->revision.name) {
/* the revision is usually saved as string (1.00) */
sscanf(hd->revision.name, "%x.%x", &u1, &u0);
u0 = u0 | u1 << 8;
} else
u0 = ID_VALUE(hd->revision.id);
cic = hd_cdbisdn_get_card_from_id(ID_VALUE(hd->vendor.id), ID_VALUE(hd->device.id),
u0, 0xffff);
if (!cic) /* to get cards without revision info in database */
cic = hd_cdbisdn_get_card_from_id(ID_VALUE(hd->vendor.id), ID_VALUE(hd->device.id),
0xffff, 0xffff);
}
if (cic && cic->Class && !strcmp(cic->Class, "DSL")) {
hd->base_class.id = bc_dsl;
hd->sub_class.id = sc_dsl_unknown;
civ = hd_cdbisdn_get_vario(cic->vario);
if (civ && civ->interface) {
if (0 == strncmp(civ->interface, "CAPI20", 6)) {
hd->sub_class.id = sc_dsl_capi;
} else if (0 == strncmp(civ->interface, "pppoe", 5)) {
hd->sub_class.id = sc_dsl_pppoe;
}
}
cic0 = new_mem(sizeof *cic0);
memcpy(cic0, cic, sizeof *cic0);
return cic0;
}
}
return NULL;
}
#endif /* !defined(__s390__) && !defined(__s390x__) && !defined(__alpha__) */
#endif /* !defined(LIBHD_TINY) */

4
src/hwinfo/src/hd/isdn.h Normal file
View File

@@ -0,0 +1,4 @@
void hd_scan_isdn(hd_data_t *hd_data);
void hd_scan_dsl(hd_data_t *hd_data);
cdb_isdn_card *get_isdn_info(hd_t *hd);
cdb_isdn_card *get_dsl_info(hd_t *hd);

308
src/hwinfo/src/hd/kbd.c Normal file
View File

@@ -0,0 +1,308 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <termios.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/ioctl.h>
#include <linux/serial.h>
#ifdef __sparc__
struct serial_struct {
int type;
int line;
unsigned long port;
int irq;
int flags;
int xmit_fifo_size;
int custom_divisor;
int baud_base;
unsigned short close_delay;
char io_type;
char reserved_char[1];
int hub6;
unsigned short closing_wait; /* time to wait before closing */
unsigned short closing_wait2; /* no longer used... */
unsigned char *iomem_base;
unsigned short iomem_reg_shift;
int reserved[2];
};
#ifdef DIET
typedef unsigned int u_int;
#endif
#include <asm/kbio.h>
#include <asm/openpromio.h>
#endif
#include "hd.h"
#include "hd_int.h"
#include "kbd.h"
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
*
* Look for keyboards not covered by kernel input device driver, mainly
* some sort of serial consoles.
*
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
*/
#ifdef __sparc__
static void add_sun_console(hd_data_t *hd_data);
#else
static void add_serial_console(hd_data_t *hd_data);
#endif
void hd_scan_kbd(hd_data_t *hd_data)
{
hd_t *hd;
if(!hd_probe_feature(hd_data, pr_kbd)) return;
hd_data->module = mod_kbd;
/* some clean-up */
remove_hd_entries(hd_data);
PROGRESS(2, 0, "uml");
if(hd_is_uml(hd_data)) {
hd = add_hd_entry(hd_data, __LINE__, 0);
hd->base_class.id = bc_keyboard;
hd->sub_class.id = sc_keyboard_kbd;
hd->bus.id = bus_none;
hd->vendor.id = MAKE_ID(TAG_SPECIAL, 0x0201);
hd->device.id = MAKE_ID(TAG_SPECIAL, 2);
}
PROGRESS(3, 0, "serial console");
#ifdef __sparc__
add_sun_console(hd_data);
#else
add_serial_console(hd_data);
#endif
}
#ifndef __sparc__
void add_serial_console(hd_data_t *hd_data)
{
hd_t *hd;
hd_res_t *res = NULL;
int fd, i;
str_list_t *cmd, *cmd0, *sl;
unsigned u, u1;
struct serial_struct ser_info;
unsigned tty_major = 0, tty_minor = 0;
char c, *dev = NULL, *s;
/* first, try console= option */
cmd = cmd0 = get_cmdline(hd_data, "console");
/* use last console entry */
if(cmd) while(cmd->next) cmd = cmd->next;
if(
cmd &&
(
/* everything != "ttyN" */
strncmp(cmd->str, "tty", 3) ||
!(cmd->str[3] == 0 || (cmd->str[3] >= '0' && cmd->str[3] <= '9'))
)
) {
sl = hd_split(',', cmd->str);
s = sl->str;
if(!strncmp(s, "/dev/", sizeof "/dev/" - 1)) s += sizeof "/dev/" - 1;
dev = new_str(s);
if(sl->next && (i = sscanf(sl->next->str, "%u%c%u", &u, &c, &u1)) >= 1) {
res = add_res_entry(&res, new_mem(sizeof *res));
res->baud.type = res_baud;
res->baud.speed = u;
if(i >= 2) res->baud.parity = c;
if(i >= 3) res->baud.bits = u1;
}
free_str_list(sl);
}
#ifdef __UCLIBC__
if(!dev && (fd = open(DEV_CONSOLE, O_RDWR | O_NONBLOCK | O_NOCTTY)) >= 0) {
/*
if(ioctl(fd, TIOCGDEV, &u) != -1) {
tty_major = (u >> 8) & 0xfff;
tty_minor = (u & 0xff) | ((u >> 12) & 0xfff00);
ADD2LOG(DEV_CONSOLE ": major %u, minor %u\n", tty_major, tty_minor);
}
*/
if(tty_major == 229 /* iseries hvc */) {
if (tty_minor >= 128) {
str_printf(&dev, 0, "hvsi%u", tty_minor-128);
} else {
str_printf(&dev, 0, "hvc%u", tty_minor);
}
}
else if(!ioctl(fd, TIOCGSERIAL, &ser_info)) {
ADD2LOG("serial console at line %d\n", ser_info.line);
str_printf(&dev, 0, "ttyS%d", ser_info.line);
}
close(fd);
}
#endif
if(dev) {
hd = add_hd_entry(hd_data, __LINE__, 0);
hd->base_class.id = bc_keyboard;
hd->sub_class.id = sc_keyboard_console;
hd->bus.id = bus_serial;
hd->device.name = new_str("serial console");
if(*dev) str_printf(&hd->unix_dev_name, 0, "/dev/%s", dev);
hd->res = res;
free_mem(dev);
}
free_str_list(cmd0);
}
#else /* defined(__sparc__) */
void add_sun_console(hd_data_t *hd_data)
{
int fd, kid, kid2, klay, ser_cons, i;
unsigned u, u1, u2;
char c1, c2;
struct serial_struct ser_info;
unsigned char buf[OPROMMAXPARAM];
struct openpromio *opio = (struct openpromio *) buf;
hd_t *hd;
hd_res_t *res;
if((fd = open(DEV_CONSOLE, O_RDWR | O_NONBLOCK | O_NOCTTY)) >= 0)
{
if(ioctl(fd, TIOCGSERIAL, &ser_info))
{
ser_cons = -1;
}
else
{
ser_cons = ser_info.line;
ADD2LOG("serial console at line %d\n", ser_cons);
}
close(fd);
if(ser_cons >= 0 && (fd = open(DEV_OPENPROM, O_RDWR | O_NONBLOCK)) >= 0)
{
sprintf(opio->oprom_array, "tty%c-mode", (ser_cons & 1) + 'a');
opio->oprom_size = sizeof buf - 0x100;
if(!ioctl(fd, OPROMGETOPT, opio))
{
if(opio->oprom_size < 0x100)
{
opio->oprom_array[opio->oprom_size] = 0;
ADD2LOG(
"prom(tty%c-mode) = \"%s\" (%d bytes)\n",
(ser_cons & 1) + 'a', opio->oprom_array,
opio->oprom_size
);
hd = add_hd_entry(hd_data, __LINE__, 0);
hd->base_class.id = bc_keyboard;
hd->sub_class.id = sc_keyboard_console;
hd->bus.id = bus_serial;
hd->vendor.id = MAKE_ID(TAG_SPECIAL, 0x0203);
hd->device.id = MAKE_ID(TAG_SPECIAL, 0x0000);
str_printf(&hd->unix_dev_name, 0, "/dev/ttyS%d", ser_cons);
if((i = sscanf(opio->oprom_array, "%u,%u,%c,%u,%c",
&u, &u1, &c1, &u2, &c2)) >= 1)
{
res = add_res_entry(&hd->res, new_mem(sizeof *res));
res->baud.type = res_baud;
res->baud.speed = u;
if(i >= 2) res->baud.bits = u1;
if(i >= 3) res->baud.parity = c1;
if(i >= 4) res->baud.stopbits = u2;
if(i >= 5) res->baud.handshake = c2;
}
}
}
close(fd);
/* We have a serial console, so don't test for keyboard. Else
we will always find a PS/2 keyboard */
return;
}
}
PROGRESS(1, 0, "sun kbd");
if((fd = open(DEV_KBD, O_RDWR | O_NONBLOCK | O_NOCTTY)) >= 0)
{
if(ioctl(fd, KIOCTYPE, &kid)) kid = -1;
if(ioctl(fd, KIOCLAYOUT, &klay)) klay = -1;
close(fd);
if(kid != -1)
{
ADD2LOG("sun keyboard: type %d, layout %d\n", kid, klay);
hd = add_hd_entry(hd_data, __LINE__, 0);
hd->base_class.id = bc_keyboard;
hd->sub_class.id = sc_keyboard_kbd;
hd->bus.id = bus_serial;
if(kid == 4 && klay >= 0)
hd->prog_if.id = klay;
hd->vendor.id = MAKE_ID(TAG_SPECIAL, 0x0202);
kid2 = kid;
if(kid == 4 && klay > 0x20)
kid2 = 5;
hd->device.id = MAKE_ID(TAG_SPECIAL, kid2);
if(kid2 == 5) {
if(klay == 0x22 || klay == 0x51)
{
hd->sub_vendor.id = MAKE_ID(TAG_SPECIAL, 0x0202);
hd->sub_device.id = MAKE_ID(TAG_SPECIAL, 0x0001);
}
else if(!(
klay == 0x21 || (klay >= 0x2f && klay <= 0x31) ||
klay == 0x50 || (klay >= 0x5e && klay <= 0x60)
))
{
hd->sub_vendor.id = MAKE_ID(TAG_SPECIAL, 0x0202);
hd->sub_device.id = MAKE_ID(TAG_SPECIAL, 0x0002);
}
}
}
}
else
{
for(hd = hd_data->hd; hd; hd = hd->next) {
if(hd->base_class.id == bc_keyboard) break;
}
if(!hd) {
/* We must have a PS/2 Keyboard */
hd = add_hd_entry(hd_data, __LINE__, 0);
hd->base_class.id = bc_keyboard;
hd->sub_class.id = sc_keyboard_kbd;
hd->bus.id = bus_ps2;
hd->vendor.id = MAKE_ID(TAG_SPECIAL, 0x0201);
hd->device.id = MAKE_ID(TAG_SPECIAL, 1);
}
}
}
#endif /* __sparc__ */

1
src/hwinfo/src/hd/kbd.h Normal file
View File

@@ -0,0 +1 @@
void hd_scan_kbd(hd_data_t *hd_data);

153
src/hwinfo/src/hd/klog.c Normal file
View File

@@ -0,0 +1,153 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/klog.h>
#include "hd.h"
#include "hd_int.h"
#include "klog.h"
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
* kernel log info
*
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
*/
static int str_ok(str_list_t *sl);
static int str_list_cmp(str_list_t *sl1, str_list_t *sl2);
/*
* Check if a string starts with '<[0-9]>'.
*/
int str_ok(str_list_t *sl)
{
return sl->str[0] == '<' && sl->str[2] == '>' && sl->str[1] >= '0' && sl->str[1] <= '9';
}
/*
* Check if sl1 is idential to sl2; sl1 may be shorter as sl2.
*
* Returns 0/1 if they are equal/not equal. If sl1 is NULL, 0 is returned.
*/
int str_list_cmp(str_list_t *sl1, str_list_t *sl2)
{
for(; sl1; sl1 = sl1->next, sl2 = sl2->next) {
if(!sl2 || strcmp(sl1->str, sl2->str)) return 1;
}
return 0;
}
/*
* Read kernel log info. Combine with /var/log/boot.msg.
*/
void read_klog(hd_data_t *hd_data)
{
char buf[0x2000 + 1], *s;
int i, j, len, n;
str_list_t *sl, *sl1, *sl2, *sl_last, **ssl, *sl_next;
/* some clean-up */
hd_data->klog = free_str_list(hd_data->klog);
sl1 = read_file(KLOG_BOOT, 0, 0);
sl2 = NULL;
/*
* remove non-canonical lines (not starting with <[0-9]>) at the start and
* at the end
*/
/* note: the implementations assumes that at least *one* line is ok */
for(sl_last = NULL, sl = sl1; sl; sl = (sl_last = sl)->next) {
if(str_ok(sl)) {
if(sl_last) {
sl_last->next = NULL;
free_str_list(sl1);
sl1 = sl;
}
break;
}
}
for(sl_last = NULL, sl = sl1; sl; sl = (sl_last = sl)->next) {
if(!str_ok(sl)) {
if(sl_last) {
sl_last->next = NULL;
free_str_list(sl);
}
break;
}
}
n = klogctl(3, buf, sizeof buf - 1);
if(n <= 0) {
hd_data->klog = sl1;
return;
}
if(n > (int) sizeof buf - 1) n = sizeof buf - 1;
buf[n] = 0;
for(i = j = 0; i < n; i++) {
if(buf[i] == '\n') {
len = i - j + 1;
s = new_mem(len + 1);
memcpy(s, buf + j, len);
add_str_list(&sl2, s);
s = free_mem(s);
j = i + 1;
}
}
/* the 1st line may be incomplete */
if(sl2 && !str_ok(sl2)) {
sl_next = sl2->next;
sl2->next = NULL;
free_str_list(sl2);
sl2 = sl_next;
}
if(!sl1) {
hd_data->klog = sl2;
return;
}
if(sl1 && !sl2) {
hd_data->klog = sl1;
return;
}
/* now, try to join sl1 & sl2 */
for(sl_last = NULL, sl = sl1; sl; sl = (sl_last = sl)->next) {
if(!str_list_cmp(sl, sl2)) {
free_str_list(sl);
if(sl_last)
sl_last->next = NULL;
else
sl1 = NULL;
break;
}
}
/* append sl2 to sl1 */
for(ssl = &sl1; *ssl; ssl = &(*ssl)->next);
*ssl = sl2;
hd_data->klog = sl1;
}
/*
* Add some klog data to the global log.
*/
void dump_klog(hd_data_t *hd_data)
{
str_list_t *sl;
ADD2LOG("----- kernel log -----\n");
for(sl = hd_data->klog; sl; sl = sl->next) {
ADD2LOG(" %s", sl->str);
}
ADD2LOG("----- kernel log end -----\n");
}

2
src/hwinfo/src/hd/klog.h Normal file
View File

@@ -0,0 +1,2 @@
void read_klog(hd_data_t *hd_data);
void dump_klog(hd_data_t *hd_data);

1549
src/hwinfo/src/hd/manual.c Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,2 @@
void hd_scan_manual(hd_data_t *hd_data);
void hd_scan_manual2(hd_data_t *hd_data);

206
src/hwinfo/src/hd/memory.c Normal file
View File

@@ -0,0 +1,206 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/stat.h>
#include "hd.h"
#include "hd_int.h"
#include "memory.h"
#include "klog.h"
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
* memory stuff
*
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
*/
uint64_t kcore_mem(hd_data_t *hd_data);
uint64_t klog_mem(hd_data_t *hd_data, uint64_t *alt);
uint64_t klog_mem2(hd_data_t *hd_data);
uint64_t meminfo_mem(hd_data_t *hd_data);
void hd_scan_memory(hd_data_t *hd_data)
{
hd_t *hd;
uint64_t kcore, klog, klog_alt, klog2, meminfo, msize0, msize1, u;
hd_res_t *res;
int i;
int exact;
if(!hd_probe_feature(hd_data, pr_memory)) return;
hd_data->module = mod_memory;
/* some clean-up */
remove_hd_entries(hd_data);
PROGRESS(1, 0, "main memory size");
kcore = kcore_mem(hd_data);
klog = klog_mem(hd_data, &klog_alt);
klog2 = klog_mem2(hd_data);
if(klog2 > klog) klog = klog2;
meminfo = meminfo_mem(hd_data);
msize0 = meminfo > klog ? meminfo : klog;
if(!msize0) msize0 = kcore;
exact = 0;
if(msize0 && kcore >= msize0 && ((kcore - msize0) << 4) / msize0 == 0) {
/* trust kcore value if it's approx. msize0 */
msize0 = kcore;
exact = 1;
}
msize1 = msize0;
if(meminfo > msize1) { msize1 = meminfo; exact = 0; }
if(klog_alt > msize0) msize0 = klog_alt;
hd = add_hd_entry(hd_data, __LINE__, 0);
hd->base_class.id = bc_internal;
hd->sub_class.id = sc_int_main_mem;
res = add_res_entry(&hd->res, new_mem(sizeof *res));
res->mem.type = res_mem;
res->mem.range = msize0;
res->mem.access = acc_rw;
res->mem.enabled = 1;
/* round it somewhat */
for(i = 0, u = msize1; u; i++) {
u >>= 1;
}
if(i > 10) { /* We *do* have at least 1k memory, do we? */
msize1 >>= i - (exact ? 8 : 5);
msize1++;
msize1 >>= 1;
msize1 <<= i - (exact ? 7 : 4);
}
res = add_res_entry(&hd->res, new_mem(sizeof *res));
res->phys_mem.type = res_phys_mem;
res->phys_mem.range = msize1;
}
uint64_t kcore_mem(hd_data_t *hd_data)
{
uint64_t u = 0;
size_t ps = getpagesize();
struct stat sb;
if(!stat(PROC_KCORE, &sb)) {
u = sb.st_size;
if(u > ps) u -= ps;
#if 0
/* we'll assume no mem modules with less than 256k */
u += 1 << 17;
u &= -1 << 18;
#endif
}
ADD2LOG(" kcore mem: 0x%"PRIx64"\n", u);
return u;
}
uint64_t klog_mem(hd_data_t *hd_data, uint64_t *alt)
{
uint64_t u = 0, u0, u1, u2, u3, mem0 = 0, mem1 = 0;
str_list_t *sl;
char *s;
int i;
if(!hd_data->klog) read_klog(hd_data);
for(sl = hd_data->klog; sl; sl = sl->next) {
if(strstr(sl->str, "<6>Memory: ") == sl->str) {
if(sscanf(sl->str, "<6>Memory: %"SCNu64"k/%"SCNu64"k", &u0, &u1) == 2) {
mem0 = u1 << 10;
}
if(
(i = sscanf(sl->str, "<6>Memory: %"SCNu64"k available (%"SCNu64"k kernel code, %"SCNu64"k data, %"SCNu64"k", &u0, &u1, &u2, &u3)) == 4 || i == 1
) {
mem0 = (i == 1 ? u0 : u0 + u1 + u2 + u3) << 10;
}
if(
(s = strstr(sl->str, "[")) &&
sscanf(s, "[%"SCNx64",%"SCNx64"]", &u0, &u1) == 2 &&
u1 > u0
) {
mem1 = u1 - u0;
}
break;
}
}
u = mem0 ? mem0 : mem1;
#if 0
/* round it somewhat */
for(i = 0, u0 = u; u0; i++) {
u0 >>= 1;
}
if(i > 10) { /* We *do* have at least 1k memory, do we? */
u >>= i - 6;
u++;
u >>= 1;
u <<= i - 5;
}
#endif
ADD2LOG(" klog mem 0: 0x%"PRIx64"\n", mem0);
ADD2LOG(" klog mem 1: 0x%"PRIx64"\n", mem1);
ADD2LOG(" klog mem: 0x%"PRIx64"\n", u);
*alt = mem1;
return u;
}
uint64_t klog_mem2(hd_data_t *hd_data)
{
uint64_t u0, u1, mem = 0;
str_list_t *sl;
char buf[64];
if(!hd_data->klog) read_klog(hd_data);
for(sl = hd_data->klog; sl; sl = sl->next) {
if(strstr(sl->str, "<6>BIOS-provided physical RAM map:") == sl->str) {
for(sl = sl->next ; sl; sl = sl->next) {
ADD2LOG(" -- %s", sl->str);
if(sscanf(sl->str, "<4> BIOS-e820: %"SCNx64" - %"SCNx64" (%63s", &u0, &u1, buf) != 3) break;
if(strcmp(buf, "usable)")) continue;
if(u1 < u0) break;
mem += u1 - u0;
}
break;
}
}
ADD2LOG(" bios mem: 0x%"PRIx64"\n", mem);
return mem;
}
uint64_t meminfo_mem(hd_data_t *hd_data)
{
uint64_t u = 0, u0;
str_list_t *sl;
sl = read_file(PROC_MEMINFO, 0, 1);
if(sl && sscanf(sl->str, "MemTotal: %"SCNu64"", &u0) == 1) {
u = u0 << 10;
}
free_str_list(sl);
ADD2LOG(" meminfo: 0x%"PRIx64"\n", u);
return u;
}

View File

@@ -0,0 +1 @@
void hd_scan_memory(hd_data_t *hd_data);

742
src/hwinfo/src/hd/misc.c Normal file
View File

@@ -0,0 +1,742 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <linux/hdreg.h>
#include "hd.h"
#include "hd_int.h"
#include "misc.h"
#include "klog.h"
static void read_ioports(misc_t *m);
static void read_dmas(misc_t *m);
static void read_irqs(misc_t *m);
static int active_vga_card(hd_t *);
static void dump_misc_proc_data(hd_data_t *hd_data);
static void dump_misc_data(hd_data_t *hd_data);
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
* misc info
*
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
*/
void hd_scan_misc(hd_data_t *hd_data)
{
hd_t *hd;
hd_res_t *res;
int fd, i;
char *s = NULL;
bios_info_t *bt = NULL;
char par[] = "parport0";
int fd_ser0, fd_ser1;
if(!hd_probe_feature(hd_data, pr_misc)) return;
hd_data->module = mod_misc;
/* some clean-up */
remove_hd_entries(hd_data);
hd_data->misc = free_misc(hd_data->misc);
PROGRESS(9, 0, "kernel log");
read_klog(hd_data);
if((hd_data->debug & HD_DEB_MISC)) dump_klog(hd_data);
PROGRESS(1, 0, "misc data");
hd_data->misc = new_mem(sizeof *hd_data->misc);
/* this is enough to load the module */
fd_ser0 = fd_ser1 = -1;
#if !defined(__sparc__)
/* On sparc, the close needs too long */
if(hd_probe_feature(hd_data, pr_misc_serial)) {
PROGRESS(1, 1, "open serial");
fd_ser0 = open("/dev/ttyS0", O_RDONLY | O_NONBLOCK);
fd_ser1 = open("/dev/ttyS1", O_RDONLY | O_NONBLOCK);
/* keep the devices open until the resources have been read */
}
#endif
/* this is enough to load the module */
if(!hd_data->flags.no_parport && hd_probe_feature(hd_data, pr_misc_par)) {
PROGRESS(1, 2, "open parallel");
/* what can the BIOS tell us? */
for(hd = hd_data->hd; hd; hd = hd->next) {
if(
hd->base_class.id == bc_internal &&
hd->sub_class.id == sc_int_bios &&
hd->detail &&
hd->detail->type == hd_detail_bios &&
hd->detail->bios.data
) break;
}
if(hd) {
bt = hd->detail->bios.data;
if(bt->par_port0) {
str_printf(&s, 0, "io=0x%x", bt->par_port0);
if(bt->par_port1) {
str_printf(&s, -1, ",0x%x", bt->par_port1);
if(bt->par_port2) str_printf(&s, -1, ",0x%x", bt->par_port2);
}
str_printf(&s, -1, " irq=none,none,none");
}
unload_module(hd_data, "parport_probe");
unload_module(hd_data, "lp");
unload_module(hd_data, "parport_pc");
unload_module(hd_data, "parport");
/* now load it with the right io */
load_module(hd_data, "parport");
load_module_with_params(hd_data, "parport_pc", s);
free_mem(s);
}
/* now load the rest of the modules */
fd = open("/dev/lp0", O_RDONLY | O_NONBLOCK);
if(fd >= 0) close(fd);
}
/*
* floppy driver resources are allocated only temporarily,
* so we access it just before we read the resources
*/
if(hd_probe_feature(hd_data, pr_misc_floppy)) {
/* look for a floppy *device* entry... */
for(hd = hd_data->hd; hd; hd = hd->next) {
if(
hd->base_class.id == bc_storage_device &&
hd->sub_class.id == sc_sdev_floppy &&
hd->unix_dev_name &&
!strncmp(hd->unix_dev_name, "/dev/fd", sizeof "/dev/fd" - 1)
) {
PROGRESS(1, 3, "read floppy");
i = 5;
hd->block0 = read_block0(hd_data, hd->unix_dev_name, &i);
hd->is.notready = hd->block0 ? 0 : 1;
if(i < 0) {
hd->tag.remove = 1;
ADD2LOG("misc.floppy: removing floppy entry %u (timed out)\n", hd->idx);
}
if(!hd->is.notready) {
struct hd_geometry geo;
int fd;
unsigned size, blk_size = 0x200;
fd = open(hd->unix_dev_name, O_RDONLY | O_NONBLOCK);
if(fd >= 0) {
if(!ioctl(fd, HDIO_GETGEO, &geo)) {
ADD2LOG("floppy ioctl(geo) ok\n");
res = add_res_entry(&hd->res, new_mem(sizeof *res));
res->disk_geo.type = res_disk_geo;
res->disk_geo.cyls = geo.cylinders;
res->disk_geo.heads = geo.heads;
res->disk_geo.sectors = geo.sectors;
res->disk_geo.geotype = geo_logical;
size = geo.cylinders * geo.heads * geo.sectors;
for(res = hd->res; res; res = res->next) {
if(res->any.type == res_size && res->size.unit == size_unit_sectors) {
res->size.val1 = size; res->size.val2 = blk_size;
break;
}
}
if(!res) {
res = add_res_entry(&hd->res, new_mem(sizeof *res));
res->size.type = res_size;
res->size.unit = size_unit_sectors;
res->size.val1 = size; res->size.val2 = blk_size;
}
}
close(fd);
}
}
break;
}
}
remove_tagged_hd_entries(hd_data);
}
PROGRESS(2, 1, "io");
read_ioports(hd_data->misc);
PROGRESS(2, 2, "dma");
read_dmas(hd_data->misc);
PROGRESS(2, 3, "irq");
read_irqs(hd_data->misc);
if((hd_data->debug & HD_DEB_MISC)) dump_misc_proc_data(hd_data);
if(fd_ser0 >= 0) close(fd_ser0);
if(fd_ser1 >= 0) close(fd_ser1);
/* now create some system generic entries */
/* FPU */
PROGRESS(3, 0, "FPU");
res = NULL;
gather_resources(hd_data->misc, &res, "fpu", 0);
if(res) {
hd = add_hd_entry(hd_data, __LINE__, 0);
hd->base_class.id = bc_internal;
hd->sub_class.id = sc_int_fpu;
hd->res = res;
}
/* DMA */
PROGRESS(3, 1, "DMA");
res = NULL;
gather_resources(hd_data->misc, &res, "dma1", 0);
gather_resources(hd_data->misc, &res, "dma2", 0);
gather_resources(hd_data->misc, &res, "dma page reg", 0);
gather_resources(hd_data->misc, &res, "cascade", W_DMA);
if(res) {
hd = add_hd_entry(hd_data, __LINE__, 0);
hd->base_class.id = bc_system;
hd->sub_class.id = sc_sys_dma;
hd->res = res;
}
/* PIC */
PROGRESS(3, 2, "PIC");
res = NULL;
gather_resources(hd_data->misc, &res, "pic1", 0);
gather_resources(hd_data->misc, &res, "pic2", 0);
gather_resources(hd_data->misc, &res, "cascade", W_IRQ);
if(res) {
hd = add_hd_entry(hd_data, __LINE__, 0);
hd->base_class.id = bc_system;
hd->sub_class.id = sc_sys_pic;
hd->res = res;
}
/* timer */
PROGRESS(3, 3, "timer");
res = NULL;
gather_resources(hd_data->misc, &res, "timer", 0);
if(res) {
hd = add_hd_entry(hd_data, __LINE__, 0);
hd->base_class.id = bc_system;
hd->sub_class.id = sc_sys_timer;
hd->res = res;
}
/* real time clock */
PROGRESS(3, 4, "RTC");
res = NULL;
gather_resources(hd_data->misc, &res, "rtc", 0);
if(res) {
hd = add_hd_entry(hd_data, __LINE__, 0);
hd->base_class.id = bc_system;
hd->sub_class.id = sc_sys_rtc;
hd->res = res;
}
/* keyboard */
res = NULL;
gather_resources(hd_data->misc, &res, "keyboard", 0);
if(res) {
hd = add_hd_entry(hd_data, __LINE__, 0);
hd->base_class.id = bc_input;
hd->sub_class.id = sc_inp_keyb;
hd->res = res;
}
/* parallel ports */
for(i = 0; i < 1; i++, par[sizeof par - 2]++) {
res = NULL;
gather_resources(hd_data->misc, &res, par, 0);
if(res) {
hd = add_hd_entry(hd_data, __LINE__, 0);
hd->base_class.id = bc_comm;
hd->sub_class.id = sc_com_par;
str_printf(&hd->unix_dev_name, 0, "/dev/lp%d", i);
hd->res = res;
}
}
/* floppy controller */
res = NULL;
gather_resources(hd_data->misc, &res, "floppy", 0);
gather_resources(hd_data->misc, &res, "floppy DIR", 0);
if(res) {
/* look for an existing entry */
for(hd = hd_data->hd; hd; hd = hd->next) {
if(hd->base_class.id == bc_storage && hd->sub_class.id == sc_sto_floppy) break;
}
/* missing, so create one */
if(!hd) {
hd = add_hd_entry(hd_data, __LINE__, 0);
hd->base_class.id = bc_storage;
hd->sub_class.id = sc_sto_floppy;
}
hd->res = res;
}
/*
* look for PS/2 port
*
* The catch is, that sometimes /dev/psaux is accessible only for root,
* so the open() may fail but there are irq events registered.
*
*/
fd = open(DEV_PSAUX, O_RDONLY | O_NONBLOCK);
if(fd >= 0) close(fd);
res = NULL;
gather_resources(hd_data->misc, &res, "PS/2 Mouse", 0);
if(res || fd >= 0) {
hd = add_hd_entry(hd_data, __LINE__, 0);
hd->base_class.id = bc_ps2;
if(res) {
hd->res = res;
}
}
}
void hd_scan_misc2(hd_data_t *hd_data)
{
hd_t *hd, *hd1;
misc_t *m;
hd_res_t *res, *res1, *res2;
int i;
if(!hd_probe_feature(hd_data, pr_misc)) return;
hd_data->module = mod_misc;
PROGRESS(5, 0, "misc data");
/* create some more system generic entries */
/* IDE */
// ###### add special ide detail to hd_t!!!
res = NULL;
gather_resources(hd_data->misc, &res, "ide0", 0);
gather_resources(hd_data->misc, &res, "ide1", 0);
gather_resources(hd_data->misc, &res, "ide2", 0);
gather_resources(hd_data->misc, &res, "ide3", 0);
if(res) {
for(hd = hd_data->hd; hd; hd = hd->next) {
if(
hd->base_class.id == bc_storage &&
hd->sub_class.id == sc_sto_ide &&
have_common_res(hd->res, res)
) break;
}
if(!hd) {
/* eg. non-PCI IDE controller */
hd = add_hd_entry(hd_data, __LINE__, 0);
hd->base_class.id = bc_storage;
hd->sub_class.id = sc_sto_ide;
/* use join_res to join the i/o ranges of ide0/1 */
join_res_io(&hd->res, res);
join_res_irq(&hd->res, res);
join_res_dma(&hd->res, res);
free_res_list(res);
}
else {
/* eg. PCI IDE controller, add resources */
join_res_io(&hd->res, res);
join_res_irq(&hd->res, res);
join_res_dma(&hd->res, res);
free_res_list(res);
}
}
/* VGA */
res = NULL;
gather_resources(hd_data->misc, &res, "vga+", 0);
gather_resources(hd_data->misc, &res, "vesafb", 0);
if(res) {
for(i = 0, hd1 = NULL, hd = hd_data->hd; hd; hd = hd->next) {
if(hd->base_class.id == bc_display && hd->sub_class.id == sc_dis_vga) {
i++;
hd1 = hd;
}
}
if(i == 0) {
/* non-PCI VGA card ??? - really, we shouldn't care... */
/* FIX THIS !!! ############### */
#ifdef __alpha__
free_res_list(res);
#else
hd = add_hd_entry(hd_data, __LINE__, 0);
hd->base_class.id = bc_display;
hd->sub_class.id = sc_dis_vga;
hd->res = res;
#endif
}
else if(i == 1) {
/* 1 PCI vga card, add resources */
join_res_io(&hd1->res, res);
join_res_irq(&hd1->res, res);
join_res_dma(&hd1->res, res);
free_res_list(res);
hd_data->display = hd1->idx;
}
else {
/* more than 1: look again, now only 'active' cards */
for(i = 0, hd1 = NULL, hd = hd_data->hd; hd; hd = hd->next) {
if(
hd->base_class.id == bc_display &&
hd->sub_class.id == sc_dis_vga &&
active_vga_card(hd)
) {
i++;
hd1 = hd;
}
}
if(i == 1) {
/* 'the' active PCI vga card, add resources */
join_res_io(&hd1->res, res);
join_res_irq(&hd1->res, res);
join_res_dma(&hd1->res, res);
hd_data->display = hd1->idx;
}
else {
/* now, what??? */
ADD2LOG("Oopy, could not figure out *the* active display adapter!\n");
}
free_res_list(res);
}
}
/* serial ports */
res = NULL;
gather_resources(hd_data->misc, &res, "serial(auto)", 0);
gather_resources(hd_data->misc, &res, "serial(set)", 0);
gather_resources(hd_data->misc, &res, "serial", 0);
for(hd = hd_data->hd; hd; hd = hd->next) {
if(hd->base_class.id == bc_comm && hd->sub_class.id == sc_com_ser) {
for(res1 = hd->res; res1; res1 = res1->next) {
for(res2 = res; res2; res2 = res2->next) {
if(res1->any.type == res2->any.type) {
switch(res1->any.type) {
case res_irq:
if(res1->irq.base == res2->irq.base) {
res2->any.type = res_any;
}
break;
case res_io:
if(
res1->io.base == res2->io.base &&
(!res1->io.range || res1->io.range == res2->io.range)
) {
res1->io.range = res2->io.range;
res2->any.type = res_any;
}
break;
default: /* gcc -Wall */
break;
}
}
}
}
}
}
/* if any of the serial resources are unaccounted for, make an extra entry */
for(res2 = res; res2; res2 = res2->next) {
if(res2->any.type != res_any) {
hd = add_hd_entry(hd_data, __LINE__, 0);
hd->base_class.id = bc_comm;
hd->sub_class.id = sc_com_ser;
hd->prog_if.id = 0x80;
for(; res2; res2 = res2->next) {
if(res2->any.type != res_any) {
res1 = add_res_entry(&hd->res, new_mem(sizeof *res));
*res1 = *res2;
res1->next = NULL;
}
}
break;
}
}
free_res_list(res);
/* go through our list and assign event counts to irq entries */
m = hd_data->misc;
for(hd = hd_data->hd; hd; hd = hd->next) {
for(res = hd->res; res; res = res->next) {
if(res->irq.type == res_irq) {
for(i = 0; (unsigned) i < m->irq_len; i++) {
if(res->irq.base == m->irq[i].irq) {
res->irq.triggered = m->irq[i].events;
break;
}
}
}
}
}
/* look for entries with matching start address */
m = hd_data->misc;
for(hd = hd_data->hd; hd; hd = hd->next) {
for(res = hd->res; res; res = res->next) {
if(res->io.type == res_io) {
for(i = 0; (unsigned) i < m->io_len; i++) {
if(res->io.base == m->io[i].addr && res->io.range < m->io[i].size) {
res->io.range = m->io[i].size;
break;
}
}
}
}
}
if((hd_data->debug & HD_DEB_MISC)) dump_misc_data(hd_data);
}
/*
* read /proc/ioports
*/
void read_ioports(misc_t *m)
{
char buf[100];
misc_io_t *r;
uint64_t u, v;
str_list_t *sl;
if(!(m->proc_io = read_file(PROC_IOPORTS, 0, 0))) return;
for(sl = m->proc_io; sl; sl = sl->next) {
if(sscanf(sl->str, " %"PRIx64" - %"PRIx64" : %99[^\n]", &u, &v, buf) == 3) {
m->io = add_mem(m->io, sizeof *m->io, m->io_len);
r = m->io + m->io_len++;
r->addr = u;
r->size = v >= u ? v - u + 1 : 0;
r->dev = new_str(buf);
}
}
}
/*
* read /proc/dma
*/
void read_dmas(misc_t *m)
{
char buf[100];
misc_dma_t *d;
unsigned u;
str_list_t *sl;
if(!(m->proc_dma = read_file(PROC_DMA, 0, 0))) return;
for(sl = m->proc_dma; sl; sl = sl->next) {
if(sscanf(sl->str, " %u : %99[^\n]", &u, buf) == 2) {
m->dma = add_mem(m->dma, sizeof *m->dma, m->dma_len);
d = m->dma + m->dma_len++;
d->channel = u;
d->dev = new_str(buf);
}
}
}
/*
* read /proc/interrupts
*
* This is somewhat more tricky, as the irq event counts are done separately
* per cpu *and* there may be irq sharing.
*/
void read_irqs(misc_t *m)
{
char buf[100], buf2[100], *s;
misc_irq_t *ir;
int i, j;
unsigned u, v, k;
str_list_t *sl;
if(!(m->proc_irq = read_file(PROC_INTERRUPTS, 1, 0))) return;
for(sl = m->proc_irq; sl; sl = sl->next) {
/* irq */
i = 0;
if(sscanf(sl->str, " %u: %n", &u, &i) < 1) continue;
v = 0;
j = i;
/* add up all event counters */
while(j < (int) strlen(sl->str) && sscanf(sl->str + j, " %u %n", &k, &i) >= 1) {
if(!i) break;
v += k;
j += i;
}
/* device driver name string */
#if defined(__PPC__)
if(
sscanf(sl->str + j, " %*s Edge %99[^\n]", buf) == 1 ||
sscanf(sl->str + j, " %*s Level %99[^\n]", buf) == 1 ||
sscanf(sl->str + j, " %*s %99[^\n]", buf) == 1
) {
#else
#if defined(__alpha__) || defined(__sparc__)
if(sscanf(sl->str + j, " %99[^\n]", buf) == 1) {
#else /* __i386__ || __x86_64__ || __ia64__ */
if(sscanf(sl->str + j, " %*s %99[^\n]", buf) == 1) {
#endif
#endif
m->irq = add_mem(m->irq, sizeof *m->irq, m->irq_len);
ir = m->irq + m->irq_len++;
ir->irq = u;
ir->events = v;
/* split device driver names (separated by ',') */
s = buf;
while(*s && sscanf(s, " %99[^,] %n", buf2, &j) >= 1) {
ir->dev = add_mem(ir->dev, sizeof *ir->dev, ir->devs);
ir->dev[ir->devs++] = new_str(buf2);
s += j;
if(*s) s++; /* skip ',' */
}
}
}
}
void gather_resources(misc_t *m, hd_res_t **r, char *name, unsigned which)
{
int i, j;
hd_res_t *res;
if(!m) return;
if(!which) which = W_IO | W_DMA | W_IRQ;
if((which & W_IO)) for(i = 0; (unsigned) i < m->io_len; i++) {
if(!strcmp(name, m->io[i].dev)) {
res = add_res_entry(r, new_mem(sizeof **r));
res->io.type = res_io;
res->io.enabled = 1;
res->io.base = m->io[i].addr;
res->io.range = m->io[i].size;
res->io.access = acc_rw;
m->io[i].tag++;
}
}
if((which & W_DMA)) for(i = 0; (unsigned) i < m->dma_len; i++) {
if(!strcmp(name, m->dma[i].dev)) {
res = add_res_entry(r, new_mem(sizeof **r));
res->dma.type = res_dma;
res->dma.enabled = 1;
res->dma.base = m->dma[i].channel;
m->dma[i].tag++;
}
}
if((which & W_IRQ)) for(i = 0; (unsigned) i < m->irq_len; i++) {
for(j = 0; j < m->irq[i].devs; j++) {
if(!strcmp(name, m->irq[i].dev[j])) {
res = add_res_entry(r, new_mem(sizeof **r));
res->irq.type = res_irq;
res->irq.enabled = 1;
res->irq.base = m->irq[i].irq;
res->irq.triggered = m->irq[i].events;
m->irq[i].tag++;
}
}
}
}
int active_vga_card(hd_t *hd)
{
hd_res_t *res;
if(hd->bus.id != bus_pci) return 1;
for(res = hd->res; res; res = res->next) {
if(
(res->mem.type == res_mem && res->mem.enabled) ||
(res->io.type == res_io && res->io.enabled)
) return 1;
}
return 0;
}
/*
* Add some proc info to the global log.
*/
void dump_misc_proc_data(hd_data_t *hd_data)
{
str_list_t *sl;
ADD2LOG("----- /proc/ioports -----\n");
for(sl = hd_data->misc->proc_io; sl; sl = sl->next) {
ADD2LOG(" %s", sl->str);
}
ADD2LOG("----- /proc/ioports end -----\n");
ADD2LOG("----- /proc/interrupts -----\n");
for(sl = hd_data->misc->proc_irq; sl; sl = sl->next) {
ADD2LOG(" %s", sl->str);
}
ADD2LOG("----- /proc/interrupts end -----\n");
ADD2LOG("----- /proc/dma -----\n");
for(sl = hd_data->misc->proc_dma; sl; sl = sl->next) {
ADD2LOG(" %s", sl->str);
}
ADD2LOG("----- /proc/dma end -----\n");
}
/*
* Add the resource usage to the global log.
*/
void dump_misc_data(hd_data_t *hd_data)
{
misc_t *m = hd_data->misc;
int i, j;
ADD2LOG("----- misc resources -----\n");
for(i = 0; (unsigned) i < m->io_len; i++) {
ADD2LOG(
"i/o:%u 0x%04"PRIx64" - 0x%04"PRIx64" (0x%02"PRIx64") \"%s\"\n",
m->io[i].tag,
m->io[i].addr, m->io[i].addr + m->io[i].size - 1,
m->io[i].size, m->io[i].dev
);
}
for(i = 0; (unsigned) i < m->irq_len; i++) {
ADD2LOG(
"irq:%u %2u (%9u)",
m->irq[i].tag, m->irq[i].irq, m->irq[i].events
);
for(j = 0; j < m->irq[i].devs; j++) {
ADD2LOG(" \"%s\"", m->irq[i].dev[j]);
}
ADD2LOG("\n");
}
for(i = 0; (unsigned) i < m->dma_len; i++) {
ADD2LOG(
"dma:%u %u \"%s\"\n",
m->dma[i].tag, m->dma[i].channel, m->dma[i].dev
);
}
ADD2LOG("----- misc resources end -----\n");
}

2
src/hwinfo/src/hd/misc.h Normal file
View File

@@ -0,0 +1,2 @@
void hd_scan_misc(hd_data_t *hd_data);
void hd_scan_misc2(hd_data_t *hd_data);

1083
src/hwinfo/src/hd/modem.c Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1 @@
void hd_scan_modem(hd_data_t *hd_data);

600
src/hwinfo/src/hd/monitor.c Normal file
View File

@@ -0,0 +1,600 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "hd.h"
#include "hd_int.h"
#include "hddb.h"
#include "monitor.h"
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
* monitor info
*
* Read the info out of the 'SuSE=' entry in /proc/cmdline. It contains
* (among others) info from the EDID record got by our syslinux extension.
*
* We will try to look up our monitor id in the id file to get additional
* info.
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
*/
#ifdef __PPC__
static void add_old_mac_monitor(hd_data_t *hd_data);
static void add_monitor(hd_data_t *hd_data, devtree_t *dt);
#endif
static int chk_edid_info(hd_data_t *hd_data, unsigned char *edid);
#if !defined(__PPC__)
static void add_lcd_info(hd_data_t *hd_data, hd_t *hd, bios_info_t *bt);
#endif
static void add_edid_info(hd_data_t *hd_data, hd_t *hd, unsigned char *edid);
static void add_monitor_res(hd_t *hd, unsigned x, unsigned y, unsigned hz, unsigned il);
static void fix_edid_info(hd_data_t *hd_data, unsigned char *edid);
#if !defined(__PPC__)
void hd_scan_monitor(hd_data_t *hd_data)
{
hd_t *hd;
int i, j, k;
char *s, *s0, *s1, *se, m[8], *t;
unsigned u;
hd_res_t *res;
monitor_info_t *mi = NULL;
bios_info_t *bt;
if(!hd_probe_feature(hd_data, pr_monitor)) return;
hd_data->module = mod_monitor;
/* some clean-up */
remove_hd_entries(hd_data);
PROGRESS(1, 0, "ddc");
for(hd = hd_data->hd; hd; hd = hd->next) {
if(hd->base_class.id == bc_internal && hd->sub_class.id == sc_int_bios) break;
}
/* first, see if we got the full edid record from bios */
bt = NULL;
#if 0
/* for testing: LIBHD_EDID points to a file with valid edid record */
{
char *s = getenv("LIBHD_EDID");
unsigned char edid[0x80];
FILE *f;
if(s && (f = fopen(s, "r"))) {
if(fread(edid, sizeof edid, 1, f) == 1) {
hd = add_hd_entry(hd_data, __LINE__, 0);
hd->base_class.id = bc_monitor;
add_edid_info(hd_data, hd, edid);
}
fclose(f);
return;
}
}
#endif
if(
hd &&
hd->detail &&
hd->detail->type == hd_detail_bios &&
(bt = hd->detail->bios.data) &&
bt->vbe.ok
) {
if(chk_edid_info(hd_data, bt->vbe.ddc)) {
hd = add_hd_entry(hd_data, __LINE__, 0);
hd->base_class.id = bc_monitor;
hd_set_hw_class(hd, hw_vbe);
add_edid_info(hd_data, hd, bt->vbe.ddc);
return;
}
}
/* Maybe a LCD panel? */
if(bt && bt->lcd.width) {
hd = add_hd_entry(hd_data, __LINE__, 0);
hd->base_class.id = bc_monitor;
hd->sub_class.id = sc_mon_lcd;
hd_set_hw_class(hd, hw_vbe);
add_lcd_info(hd_data, hd, bt);
return;
}
/* Maybe we have hidden edid info here? */
if(!(s = s0 = t = get_cmd_param(hd_data, 0))) return; /* no :-( */
s = strsep(&t, "^");
se = s + strlen(s);
if(se - s < 7 + 2 * 4) {
free_mem(s0);
return;
}
/* Ok, we've got it. Now we split the fields. */
memcpy(m, s, 7); m[7] = 0; s += 7;
hd = add_hd_entry(hd_data, __LINE__, 0);
hd->base_class.id = bc_monitor;
hd->vendor.id = name2eisa_id(m);
if(sscanf(m + 3, "%x", &u) == 1) hd->device.id = MAKE_ID(TAG_EISA, u);
if((u = device_class(hd_data, hd->vendor.id, hd->device.id))) {
if((u >> 8) == bc_monitor) hd->sub_class.id = u & 0xff;
}
i = hex(s, 2); j = hex(s + 2, 2); s += 4;
if(i > 0 && j > 0) {
res = add_res_entry(&hd->res, new_mem(sizeof *res));
res->size.type = res_size;
res->size.unit = size_unit_cm;
res->size.val1 = i; /* width */
res->size.val2 = j; /* height */
}
i = hex(s, 2); s+= 2;
if(i & (1 << 7)) add_monitor_res(hd, 720, 400, 70, 0);
if(i & (1 << 6)) add_monitor_res(hd, 720, 400, 88, 0);
if(i & (1 << 5)) add_monitor_res(hd, 640, 480, 60, 0);
if(i & (1 << 4)) add_monitor_res(hd, 640, 480, 67, 0);
if(i & (1 << 3)) add_monitor_res(hd, 640, 480, 72, 0);
if(i & (1 << 2)) add_monitor_res(hd, 640, 480, 75, 0);
if(i & (1 << 1)) add_monitor_res(hd, 800, 600, 56, 0);
if(i & (1 << 0)) add_monitor_res(hd, 800, 600, 60, 0);
i = hex(s, 2); s+= 2;
if(i & (1 << 7)) add_monitor_res(hd, 800, 600, 72, 0);
if(i & (1 << 6)) add_monitor_res(hd, 800, 600, 75, 0);
if(i & (1 << 5)) add_monitor_res(hd, 832, 624, 75, 0);
if(i & (1 << 4)) add_monitor_res(hd, 1024, 768, 87, 1);
if(i & (1 << 3)) add_monitor_res(hd, 1024, 768, 60, 0);
if(i & (1 << 2)) add_monitor_res(hd, 1024, 768, 70, 0);
if(i & (1 << 1)) add_monitor_res(hd, 1024, 768, 75, 0);
if(i & (1 << 0)) add_monitor_res(hd, 1280, 1024, 75, 0);
if(((se - s) & 1) || se - s > 8 * 4 + 2) {
ADD2LOG(" ddc oops: %d bytes left?\n", (int) (se - s));
free_mem(s0);
return;
}
while(s + 4 <= se) {
i = (hex(s, 2) + 31) * 8; j = hex(s + 2, 2); s += 4;
k = 0;
switch((j >> 6) & 3) {
case 1: k = (i * 3) / 4; break;
case 2: k = (i * 4) / 5; break;
case 3: k = (i * 9) / 16; break;
}
if(k) add_monitor_res(hd, i, k, (j & 0x3f) + 60, 0);
}
u = 0;
if(se - s == 2) u = hex(s, 2) + 1990;
if(u || t) {
mi = new_mem(sizeof *mi);
if(u) mi->manu_year = u;
while((s = strsep(&t, "^"))) {
for(s1 = s; *s1++; ) if(*s1 == '_') *s1 = ' ';
switch(*s) {
case '0':
if(!mi->name && s[1]) mi->name = canon_str(s + 1, strlen(s + 1));
break;
case '1':
u = 0;
if(strlen(s) == 9) {
i = hex(s + 1, 2);
j = hex(s + 3, 2);
if(i > j || !i) u = 1;
mi->min_vsync = i;
mi->max_vsync = j;
i = hex(s + 5, 2);
j = hex(s + 7, 2);
if(i > j || !i) u = 1;
mi->min_hsync = i;
mi->max_hsync = j;
}
else {
u = 1;
}
if(u) {
mi->min_vsync = mi->max_vsync = mi->min_hsync = mi->max_hsync = 0;
ADD2LOG(" ddc oops: invalid freq data\n");
}
break;
case '2':
if(!mi->vendor && s[1]) mi->vendor = canon_str(s + 1, strlen(s + 1));
break;
case '3':
if(!mi->serial && s[1]) mi->serial = canon_str(s + 1, strlen(s + 1));
break;
default:
ADD2LOG(" ddc oops: invalid tag 0x%02x\n", *s);
}
}
}
if(mi) {
hd->detail = new_mem(sizeof *hd->detail);
hd->detail->type = hd_detail_monitor;
hd->detail->monitor.data = mi;
hd->serial = new_str(mi->serial);
#if 0
// ########### FIXME
if(
mi->vendor &&
ID_VALUE(hd->vendor.id) &&
!hd_vendor_name(hd_data, hd->vendor.id)
) {
add_vendor_name(hd_data, hd->vend, mi->vendor);
}
#endif
#if 0
// ########### FIXME
if(
mi->name &&
(ID_VALUE(hd->vendor.id) || ID_VALUE(hd->device.id)) &&
!hd_device_name(hd_data, hd->vend, hd->device.id)
) {
add_device_name(hd_data, hd->vend, hd->dev, mi->name);
}
#endif
if(hd_data->debug) {
ADD2LOG("----- DDC info -----\n");
if(mi->vendor) {
ADD2LOG(" vendor: \"%s\"\n", mi->vendor);
}
if(mi->name) {
ADD2LOG(" model: \"%s\"\n", mi->name);
}
if(mi->serial) {
ADD2LOG(" serial: \"%s\"\n", mi->serial);
}
if(mi->min_hsync) {
ADD2LOG(" hsync: %u-%u kHz\n", mi->min_hsync, mi->max_hsync);
}
if(mi->min_vsync) {
ADD2LOG(" vsync: %u-%u Hz\n", mi->min_vsync, mi->max_vsync);
}
if(mi->manu_year) {
ADD2LOG(" manu. year: %u\n", mi->manu_year);
}
ADD2LOG("----- DDC info end -----\n");
}
}
free_mem(s0);
}
#endif /* !defined(__PPC__) */
#if defined(__PPC__)
void hd_scan_monitor(hd_data_t *hd_data)
{
devtree_t *dt;
int found;
if(!hd_probe_feature(hd_data, pr_monitor)) return;
hd_data->module = mod_monitor;
/* some clean-up */
remove_hd_entries(hd_data);
PROGRESS(1, 0, "prom");
found = 0;
for(dt = hd_data->devtree; dt; dt = dt->next) {
if(dt->edid) {
add_monitor(hd_data, dt);
found = 1;
}
}
if(!found) {
add_old_mac_monitor(hd_data);
}
}
void add_old_mac_monitor(hd_data_t *hd_data)
{
hd_t *hd;
unsigned u1, u2;
str_list_t *sl;
static struct {
unsigned width, height, vfreq, interlaced;
} mode_list[20] = {
{ 512, 384, 60, 1 },
{ 512, 384, 60, 0 },
{ 640, 480, 50, 1 },
{ 640, 480, 60, 1 },
{ 640, 480, 60, 0 },
{ 640, 480, 67, 0 },
{ 640, 870, 75, 0 },
{ 768, 576, 50, 1 },
{ 800, 600, 56, 0 },
{ 800, 600, 60, 0 },
{ 800, 600, 72, 0 },
{ 800, 600, 75, 0 },
{ 832, 624, 75, 0 },
{ 1024, 768, 60, 0 },
{ 1024, 768, 70, 0 },
{ 1024, 768, 75, 0 },
{ 1024, 768, 75, 0 },
{ 1152, 870, 75, 0 },
{ 1280, 960, 75, 0 },
{ 1280, 1024, 75, 0 }
};
for(sl = hd_data->klog; sl; sl = sl->next) {
if(sscanf(sl->str, "<%*d>Monitor sense value = %i, using video mode %i", &u1, &u2) == 2) {
u2--;
hd = add_hd_entry(hd_data, __LINE__, 0);
hd->base_class.id = bc_monitor;
hd->vendor.id = MAKE_ID(TAG_SPECIAL, 0x0401);
hd->device.id = MAKE_ID(TAG_SPECIAL, (u1 & 0xfff) + 0x1000);
if((u1 = hd_display_adapter(hd_data))) {
hd->attached_to = u1;
}
if(u2 < sizeof mode_list / sizeof *mode_list) {
add_monitor_res(hd, mode_list[u2].width, mode_list[u2].height, mode_list[u2].vfreq, mode_list[u2].interlaced);
}
break;
}
}
}
void add_monitor(hd_data_t *hd_data, devtree_t *dt)
{
hd_t *hd, *hd2;
unsigned char *edid = dt->edid;
if(!chk_edid_info(hd_data, edid)) return;
hd = add_hd_entry(hd_data, __LINE__, 0);
hd->base_class.id = bc_monitor;
for(hd2 = hd_data->hd; hd2; hd2 = hd2->next) {
if(
hd2->detail &&
hd2->detail->type == hd_detail_devtree &&
hd2->detail->devtree.data == dt
) {
hd->attached_to = hd2->idx;
break;
}
}
add_edid_info(hd_data, hd, edid);
}
#endif /* defined(__PPC__) */
/* do some checks to ensure we got a reasonable block */
int chk_edid_info(hd_data_t *hd_data, unsigned char *edid)
{
// no vendor or model info
if(!(edid[0x08] || edid[0x09] || edid[0x0a] || edid[0x0b])) return 0;
// no edid version or revision
if(!(edid[0x12] || edid[0x13])) return 0;
return 1;
}
#if !defined(__PPC__)
void add_lcd_info(hd_data_t *hd_data, hd_t *hd, bios_info_t *bt)
{
monitor_info_t *mi = NULL;
hd->vendor.name = new_str(bt->lcd.vendor);
hd->device.name = new_str(bt->lcd.name);
add_monitor_res(hd, bt->lcd.width, bt->lcd.height, 60, 0);
mi = new_mem(sizeof *mi);
hd->detail = new_mem(sizeof *hd->detail);
hd->detail->type = hd_detail_monitor;
hd->detail->monitor.data = mi;
mi->min_vsync = 50;
mi->min_hsync = 31;
mi->max_vsync = 75;
mi->max_hsync = (mi->max_vsync * bt->lcd.height * 12) / 10000;
}
#endif
void add_edid_info(hd_data_t *hd_data, hd_t *hd, unsigned char *edid)
{
hd_res_t *res;
monitor_info_t *mi = NULL;
int i;
unsigned u, u1, u2;
fix_edid_info(hd_data, edid);
u = (edid[8] << 8) + edid[9];
hd->vendor.id = MAKE_ID(TAG_EISA, u);
u = (edid[0xb] << 8) + edid[0xa];
hd->device.id = MAKE_ID(TAG_EISA, u);
if((u = device_class(hd_data, hd->vendor.id, hd->device.id))) {
if((u >> 8) == bc_monitor) hd->sub_class.id = u & 0xff;
}
if(edid[0x15] > 0 && edid[0x16] > 0) {
res = add_res_entry(&hd->res, new_mem(sizeof *res));
res->size.type = res_size;
res->size.unit = size_unit_cm;
res->size.val1 = edid[0x15]; /* width */
res->size.val2 = edid[0x16]; /* height */
}
u = edid[0x23];
if(u & (1 << 7)) add_monitor_res(hd, 720, 400, 70, 0);
if(u & (1 << 6)) add_monitor_res(hd, 720, 400, 88, 0);
if(u & (1 << 5)) add_monitor_res(hd, 640, 480, 60, 0);
if(u & (1 << 4)) add_monitor_res(hd, 640, 480, 67, 0);
if(u & (1 << 3)) add_monitor_res(hd, 640, 480, 72, 0);
if(u & (1 << 2)) add_monitor_res(hd, 640, 480, 75, 0);
if(u & (1 << 1)) add_monitor_res(hd, 800, 600, 56, 0);
if(u & (1 << 0)) add_monitor_res(hd, 800, 600, 60, 0);
u = edid[0x24];
if(u & (1 << 7)) add_monitor_res(hd, 800, 600, 72, 0);
if(u & (1 << 6)) add_monitor_res(hd, 800, 600, 75, 0);
if(u & (1 << 5)) add_monitor_res(hd, 832, 624, 75, 0);
if(u & (1 << 4)) add_monitor_res(hd, 1024, 768, 87, 1);
if(u & (1 << 3)) add_monitor_res(hd, 1024, 768, 60, 0);
if(u & (1 << 2)) add_monitor_res(hd, 1024, 768, 70, 0);
if(u & (1 << 1)) add_monitor_res(hd, 1024, 768, 75, 0);
if(u & (1 << 0)) add_monitor_res(hd, 1280, 1024, 75, 0);
for(i = 0; i < 4; i++) {
u1 = (edid[0x26 + 2 * i] + 31) * 8;
u2 = edid[0x27 + 2 * i];
u = 0;
switch((u2 >> 6) & 3) {
case 1: u = (u1 * 3) / 4; break;
case 2: u = (u1 * 4) / 5; break;
case 3: u = (u1 * 9) / 16; break;
}
if(u) add_monitor_res(hd, u1, u, (u2 & 0x3f) + 60, 0);
}
mi = new_mem(sizeof *mi);
mi->manu_year = 1990 + edid[0x11];
for(i = 0x36; i < 0x36 + 4 * 0x12; i += 0x12) {
if(!(edid[i] || edid[i + 1] || edid[i + 2])) {
switch(edid[i + 3]) {
case 0xfc:
if(edid[i + 5]) {
/* the name entry is splitted some times */
str_printf(&mi->name, -1, "%s%s", mi->name ? " " : "", canon_str(edid + i + 5, 0xd));
}
break;
case 0xfd:
u = 0;
u1 = edid[i + 5];
u2 = edid[i + 6];
if(u1 > u2 || !u1) u = 1;
mi->min_vsync = u1;
mi->max_vsync = u2;
u1 = edid[i + 7];
u2 = edid[i + 8];
if(u1 > u2 || !u1) u = 1;
mi->min_hsync = u1;
mi->max_hsync = u2;
if(u) {
mi->min_vsync = mi->max_vsync = mi->min_hsync = mi->max_hsync = 0;
ADD2LOG(" ddc oops: invalid freq data\n");
}
break;
case 0xfe:
if(!mi->vendor && edid[i + 5]) mi->vendor = canon_str(edid + i + 5, 0xd);
break;
case 0xff:
if(!mi->serial && edid[i + 5]) mi->serial = canon_str(edid + i + 5, 0xd);
break;
default:
ADD2LOG(" ddc oops: invalid tag 0x%02x\n", edid[i + 3]);
}
}
}
if(mi) {
hd->detail = new_mem(sizeof *hd->detail);
hd->detail->type = hd_detail_monitor;
hd->detail->monitor.data = mi;
hd->serial = new_str(mi->serial);
hd->vendor.name = new_str(mi->vendor);
hd->device.name = new_str(mi->name);
if(hd_data->debug) {
ADD2LOG("----- DDC info -----\n");
if(mi->vendor) {
ADD2LOG(" vendor: \"%s\"\n", mi->vendor);
}
if(mi->name) {
ADD2LOG(" model: \"%s\"\n", mi->name);
}
if(mi->serial) {
ADD2LOG(" serial: \"%s\"\n", mi->serial);
}
if(mi->min_hsync) {
ADD2LOG(" hsync: %u-%u kHz\n", mi->min_hsync, mi->max_hsync);
}
if(mi->min_vsync) {
ADD2LOG(" vsync: %u-%u Hz\n", mi->min_vsync, mi->max_vsync);
}
if(mi->manu_year) {
ADD2LOG(" manu. year: %u\n", mi->manu_year);
}
ADD2LOG("----- DDC info end -----\n");
}
}
}
void add_monitor_res(hd_t *hd, unsigned width, unsigned height, unsigned vfreq, unsigned il)
{
hd_res_t *res;
res = add_res_entry(&hd->res, new_mem(sizeof *res));
res->monitor.type = res_monitor;
res->monitor.width = width;
res->monitor.height = height;
res->monitor.vfreq = vfreq;
res->monitor.interlaced = il;
}
/*
* This looks evil, but some Mac displays really lie at us.
*/
void fix_edid_info(hd_data_t *hd_data, unsigned char *edid)
{
unsigned vend, dev;
unsigned timing;
int fix = 0;
vend = (edid[8] << 8) + edid[9];
dev = (edid[0xb] << 8) + edid[0xa];
timing = (edid[0x24] << 8) + edid[0x23];
/* APP9214: Apple Studio Display */
if(vend == 0x0610 && dev == 0x9214 && timing == 0x0800) {
timing = 0x1000;
fix = 1;
}
if(fix) {
edid[0x23] = timing & 0xff;
edid[0x24] = (timing >> 8) & 0xff;
}
}

View File

@@ -0,0 +1 @@
void hd_scan_monitor(hd_data_t *hd_data);

785
src/hwinfo/src/hd/mouse.c Normal file
View File

@@ -0,0 +1,785 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <termios.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/ioctl.h>
#include "hd.h"
#include "hd_int.h"
#include "mouse.h"
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
* mouse info
*
* TODO: reset serial lines to old values (cf. modem.c)
*
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
*/
#ifndef LIBHD_TINY
#if 0
static unsigned read_data(hd_data_t *hd_data, int fd, unsigned char *buf, unsigned buf_size);
static void get_ps2_mouse(hd_data_t *hd_data);
static void test_ps2_open(void *arg);
#endif
static void get_serial_mouse(hd_data_t* hd_data);
static void add_serial_mouse(hd_data_t* hd_data);
static int _setspeed(int fd, int old, int new, int needtowrite, unsigned short flags);
static void setspeed(int fd, int new, int needtowrite, unsigned short flags);
static unsigned chk4id(ser_device_t *mi);
static ser_device_t *add_ser_mouse_entry(ser_device_t **sm, ser_device_t *new_sm);
static void dump_ser_mouse_data(hd_data_t *hd_data);
#if 0
static void get_sunmouse(hd_data_t *hd_data);
#endif
void hd_scan_mouse(hd_data_t *hd_data)
{
ser_device_t *sm, *sm_next;
if(!hd_probe_feature(hd_data, pr_mouse)) return;
hd_data->module = mod_mouse;
/* some clean-up */
remove_hd_entries(hd_data);
hd_data->ser_mouse = NULL;
#if 0
PROGRESS(1, 0, "ps/2");
get_ps2_mouse(hd_data);
#endif
PROGRESS(2, 0, "serial");
hd_fork(hd_data, 20, 20);
if(hd_data->flags.forked) {
get_serial_mouse(hd_data);
hd_move_to_shm(hd_data);
if((hd_data->debug & HD_DEB_MOUSE)) dump_ser_mouse_data(hd_data);
}
else {
/* take data from shm */
hd_data->ser_mouse = ((hd_data_t *) (hd_data->shm.data))->ser_mouse;
if((hd_data->debug & HD_DEB_MOUSE)) dump_ser_mouse_data(hd_data);
}
hd_fork_done(hd_data);
add_serial_mouse(hd_data);
hd_shm_clean(hd_data);
for(sm = hd_data->ser_mouse; sm; sm = sm_next) {
sm_next = sm->next;
free_mem(sm->dev_name);
free_mem(sm);
}
hd_data->ser_mouse = NULL;
#if 0
PROGRESS(3, 0, "sunmouse");
get_sunmouse(hd_data);
#endif
}
#if 0
unsigned read_data(hd_data_t *hd_data, int fd, unsigned char *buf, unsigned buf_size)
{
int k, len = 0;
unsigned char *bp;
while(
(unsigned) len < buf_size &&
(k = read(fd, buf + len, buf_size - len)) >= 0
) len += k;
bp = buf;
if(len && (*bp == 0xfe || *bp == 0xfa)) { bp++; len--; }
for(k = 0; k < len; k++) buf[k] = bp[k];
if((hd_data->debug & HD_DEB_MOUSE)) {
ADD2LOG("ps/2[%d]: ", len);
hexdump(&hd_data->log, 1, len, buf);
ADD2LOG("\n");
}
return len;
}
/*
* How it works:
*
* 1. There must exist a PS/2 controller entry (-> there is a PS/2 port).
* 2. If there are PS/2 mouse irq events, assume a PS/2 mouse is attached.
* 3. Otherwise:
* - open /dev/psaux
* - write the "get mouse info" command (0xe9)
* - read back the response, which should be either 0xfe "resend data"
* or, e.g. (0xfa) 0x20 0x02 0x3c (0xfa = "ACK" (should be swallowed
* by the psaux driver, but isn't), the rest are settings)
* - ignore the first byte if it is 0xfa or 0xfe
* - if there are at least 2 bytes left, assume a mouse is attached.
*
* Note1: we could use the command 0xfe "get mouse ID" instead. But that turned
* out to be less reliable, as this command returns only one byte, which
* is even 0.
* Note2: step 2 is mainly relevant if the mouse is already in use. In that
* case we would have problems reading back the respose of our command.
* (Typically the mouse driver will get it (and choke on it).)
*/
static void get_ps2_mouse(hd_data_t *hd_data)
{
hd_t *hd, *hd1;
hd_res_t *res;
int fd;
fd_set set;
struct timeval tv;
unsigned char cmd_mouse_info = 0xe9; /* read mouse info (3 bytes) */
unsigned char cmd_mouse_id = 0xf2; /* read mouse id (1 byte) */
unsigned char buf[100];
unsigned mouse_id = -1;
static unsigned char intelli_init[] = { 0xf3, 200, 0xf3, 100, 0xf3, 80 };
int buf_len = 0;
#ifdef __PPC__
int always_ps2_mouse = 0;
#endif
for(hd1 = hd_data->hd; hd1; hd1 = hd1->next) {
/* look for a PS/2 controller entry... */
if(hd1->base_class.id == bc_ps2) {
/* ...and see if there were irq events... */
for(res = hd1->res; res; res = res->next) {
if(res->irq.type == res_irq && res->irq.triggered) break;
}
#ifdef __PPC__
/*
* On PReP & CHRP, assume a PS/2 mouse to be attached.
* There seems to be no way to actually *detect* it.
*/
if(!res) {
hd_t *hd;
sys_info_t *st;
if((hd = hd_list(hd_data, hw_sys, 0, NULL))) {
if(
hd->detail &&
hd->detail->type == hd_detail_sys &&
(st = hd->detail->sys.data) &&
(
!strcmp(st->system_type, "PReP") ||
strstr(st->system_type, "CHRP") == st->system_type /* CHRP && CHRP64 */
)
) {
always_ps2_mouse = 1;
}
}
}
#endif
PROGRESS(1, 1, "ps/2");
/* open the mouse device... */
if(hd_timeout(test_ps2_open, NULL, 2) > 0) {
ADD2LOG("ps/2: open(%s) timed out\n", DEV_PSAUX);
fd = -2;
}
else {
fd = open(DEV_PSAUX, O_RDWR | O_NONBLOCK);
}
PROGRESS(1, 2, "ps/2");
if(fd >= 0) {
/* ...write the id command... */
PROGRESS(1, 3, "ps/2");
write(fd, intelli_init, sizeof intelli_init);
usleep(25000);
read_data(hd_data, fd, buf, sizeof buf);
if(write(fd, &cmd_mouse_id, 1) == 1) {
PROGRESS(1, 4, "ps/2");
usleep(50000); /* ...give it a chance to react... */
/* ...read the response... */
buf_len = read_data(hd_data, fd, buf, sizeof buf);
if(buf_len >= 1) mouse_id = buf[buf_len - 1];
// if we didn't get any response, try this
if(buf_len == 0 || (hd_data->debug & HD_DEB_MOUSE)) {
PROGRESS(1, 5, "ps/2");
if(write(fd, &cmd_mouse_info, 1) == 1) {
usleep(50000);
buf_len = read_data(hd_data, fd, buf, sizeof buf);
/*
* Assume a mouse to be attached if at least 2 bytes are
* returned.
*/
if(mouse_id == -1u && buf_len >= 2) mouse_id = 0;
}
}
PROGRESS(1, 6, "ps/2");
}
close(fd);
PROGRESS(1, 7, "ps/2");
/*
* The following code is apparently necessary on some board/mouse
* combinations. Otherwise the PS/2 mouse won't work.
*/
if((fd = open(DEV_PSAUX, O_RDONLY | O_NONBLOCK)) >= 0) {
PROGRESS(1, 8, "ps/2");
FD_ZERO(&set);
FD_SET(fd, &set);
tv.tv_sec = 0; tv.tv_usec = 1;
if(select(fd + 1, &set, NULL, NULL, &tv) == 1) {
PROGRESS(1, 9, "ps/2");
read(fd, buf, sizeof buf);
PROGRESS(1, 10, "ps/2");
}
PROGRESS(1, 11, "ps/2");
close(fd);
PROGRESS(1, 12, "ps/2");
}
}
else {
ADD2LOG("open(" DEV_PSAUX "): %s\n", fd == -1 ? strerror(errno) : "timeout");
}
if(mouse_id == -1u) {
/*
* Assume a PS/2 mouse is attached if the ps/2 controller has
* genetrated some events.
*/
if(
res
#ifdef __PPC__
|| always_ps2_mouse
#endif
) {
PROGRESS(1, 13, "ps/2");
mouse_id = 0;
}
}
if(mouse_id != -1u) {
PROGRESS(1, 14, "ps/2");
hd = add_hd_entry(hd_data, __LINE__, 0);
hd->base_class.id = bc_mouse;
hd->sub_class.id = sc_mou_ps2;
hd->bus.id = bus_ps2;
hd->unix_dev_name = new_str(DEV_MICE);
hd->attached_to = hd1->idx;
hd->vendor.id = MAKE_ID(TAG_SPECIAL, 0x0200);
switch(mouse_id) {
case 3: /* 3 buttons + wheel */
hd->device.id = MAKE_ID(TAG_SPECIAL, 0x0004);
break;
case 4: /* 5 buttons + wheel */
hd->device.id = MAKE_ID(TAG_SPECIAL, 0x0005);
break;
default: /* 0 */
hd->device.id = MAKE_ID(TAG_SPECIAL, 0x0002);
}
}
/* there can only be one... */
break;
}
}
}
void test_ps2_open(void *arg)
{
open(DEV_PSAUX, O_RDWR | O_NONBLOCK);
}
#endif
#if 0
static void get_sunmouse(hd_data_t *hd_data)
{
hd_t *hd;
int fd;
int found;
found = 0;
/* Only search for Sun mouse if we have a Sun keyboard */
for(hd = hd_data->hd; hd; hd = hd->next)
{
if(hd->base_class.id == bc_keyboard &&
hd->sub_class.id == sc_keyboard_kbd &&
ID_TAG(hd->vendor.id) == TAG_SPECIAL && ID_VALUE(hd->vendor.id) == 0x0202)
found = 1;
}
if (found)
{
if ((fd = open(DEV_SUNMOUSE, O_RDONLY)) != -1)
{
/* FIXME: Should probably talk to the mouse to see
if the connector is not empty. */
close (fd);
PROGRESS(1, 1, "Sun Mouse");
hd = add_hd_entry (hd_data, __LINE__, 0);
hd->base_class.id = bc_mouse;
hd->sub_class.id = sc_mou_sun;
hd->bus.id = bus_serial;
hd->unix_dev_name = new_str(DEV_SUNMOUSE);
hd->vendor.id = MAKE_ID(TAG_SPECIAL, 0x0202);
hd->device.id = MAKE_ID(TAG_SPECIAL, 0x0000);
}
}
}
#endif
/*
* Gather serial mouse data and put it into hd_data->ser_mouse.
*/
void get_serial_mouse(hd_data_t *hd_data)
{
hd_t *hd;
int j, fd, fd_max = 0, sel, max_len;
unsigned modem_info;
fd_set set, set0;
struct timeval to;
ser_device_t *sm;
struct termios tio;
FD_ZERO(&set);
for(hd = hd_data->hd; hd; hd = hd->next) {
if(
hd->base_class.id == bc_comm &&
hd->sub_class.id == sc_com_ser &&
hd->unix_dev_name &&
!hd->tag.ser_skip &&
!has_something_attached(hd_data, hd)
) {
if((fd = open(hd->unix_dev_name, O_RDWR | O_NONBLOCK)) >= 0) {
if(tcgetattr(fd, &tio)) continue;
sm = add_ser_mouse_entry(&hd_data->ser_mouse, new_mem(sizeof *sm));
sm->dev_name = new_str(hd->unix_dev_name);
sm->fd = fd;
sm->tio = tio;
sm->hd_idx = hd->idx;
if(fd > fd_max) fd_max = fd;
FD_SET(fd, &set);
/*
* PnP COM spec black magic...
*/
setspeed(fd, 1200, 1, CS7);
modem_info = TIOCM_DTR | TIOCM_RTS;
ioctl(fd, TIOCMBIC, &modem_info);
}
}
}
if(!hd_data->ser_mouse) return;
/*
* 200 ms seems to be too fast for some mice...
*/
usleep(300000); /* PnP protocol */
for(sm = hd_data->ser_mouse; sm; sm = sm->next) {
modem_info = TIOCM_DTR | TIOCM_RTS;
ioctl(sm->fd, TIOCMBIS, &modem_info);
}
/* smaller buffer size, otherwise we might wait really long... */
max_len = sizeof sm->buf < 128 ? sizeof sm->buf : 128;
to.tv_sec = 0; to.tv_usec = 300000;
set0 = set;
for(;;) {
to.tv_sec = 0; to.tv_usec = 300000;
set = set0;
if((sel = select(fd_max + 1, &set, NULL, NULL, &to)) > 0) {
for(sm = hd_data->ser_mouse; sm; sm = sm->next) {
if(FD_ISSET(sm->fd, &set)) {
if((j = read(sm->fd, sm->buf + sm->buf_len, max_len - sm->buf_len)) > 0)
sm->buf_len += j;
if(j <= 0) FD_CLR(sm->fd, &set0); // #####
}
}
}
else {
break;
}
}
for(sm = hd_data->ser_mouse; sm; sm = sm->next) {
chk4id(sm);
/* reset serial lines */
tcflush(sm->fd, TCIOFLUSH);
tcsetattr(sm->fd, TCSAFLUSH, &sm->tio);
close(sm->fd);
}
}
/*
* Go through serial mouse data and add hd entries.
*/
void add_serial_mouse(hd_data_t *hd_data)
{
hd_t *hd;
char buf[4];
ser_device_t *sm;
for(sm = hd_data->ser_mouse; sm; sm = sm->next) {
if(sm->is_mouse) {
hd = add_hd_entry(hd_data, __LINE__, 0);
hd->base_class.id = bc_mouse;
hd->sub_class.id = sc_mou_ser;
hd->bus.id = bus_serial;
hd->unix_dev_name = new_str(sm->dev_name);
hd->attached_to = sm->hd_idx;
if(*sm->pnp_id) {
strncpy(buf, sm->pnp_id, 3);
buf[3] = 0;
hd->vendor.id = name2eisa_id(buf);
if(!hd->vendor.id) { /* in case it's a really strange one... */
hd->vendor.name = new_str(buf);
}
hd->device.id = MAKE_ID(TAG_EISA, strtol(sm->pnp_id + 3, NULL, 16));
hd->serial = new_str(sm->serial);
if(sm->user_name) hd->device.name = new_str(sm->user_name);
if(sm->vend) {
free_mem(hd->vendor.name);
hd->vendor.name = new_str(sm->vend);
}
if(sm->dev_id && strlen(sm->dev_id) >= 7) {
char buf[5], *s;
unsigned u1, u2;
u1 = name2eisa_id(sm->dev_id);
if(u1) {
strncpy(buf, sm->dev_id + 3, 4);
buf[4] = 0;
u2 = strtol(sm->dev_id + 3, &s, 16);
if(!*s) {
hd->compat_vendor.id = u1;
hd->compat_device.id = MAKE_ID(TAG_EISA, u2);
}
}
}
}
else {
hd->vendor.id = MAKE_ID(TAG_SPECIAL, 0x0200);
hd->device.id = MAKE_ID(TAG_SPECIAL, 0x0003);
}
}
}
}
/*
* Baud setting magic taken from gpm.
*/
int _setspeed(int fd, int old, int new, int needtowrite, unsigned short flags)
{
struct termios tty;
char *c;
int err = 0;
flags |= CREAD | CLOCAL | HUPCL;
if(tcgetattr(fd, &tty)) return errno;
tty.c_iflag = IGNBRK | IGNPAR;
tty.c_oflag = 0;
tty.c_lflag = 0;
tty.c_line = 0;
tty.c_cc[VTIME] = 0;
tty.c_cc[VMIN] = 1;
switch (old)
{
case 9600: tty.c_cflag = flags | B9600; break;
case 4800: tty.c_cflag = flags | B4800; break;
case 2400: tty.c_cflag = flags | B2400; break;
case 1200:
default: tty.c_cflag = flags | B1200; break;
}
if(tcsetattr(fd, TCSAFLUSH, &tty)) return errno;
switch (new)
{
case 9600: c = "*q"; tty.c_cflag = flags | B9600; break;
case 4800: c = "*p"; tty.c_cflag = flags | B4800; break;
case 2400: c = "*o"; tty.c_cflag = flags | B2400; break;
case 1200:
default: c = "*n"; tty.c_cflag = flags | B1200; break;
}
if(needtowrite) {
err = 2 - write(fd, c, 2);
}
usleep(100000);
if(tcsetattr(fd, TCSAFLUSH, &tty)) return errno;
return err;
}
void setspeed(int fd, int new, int needtowrite, unsigned short flags)
{
int i, err;
for(i = 9600; i >= 1200; i >>= 1) {
err = _setspeed(fd, i, new, needtowrite, flags);
#if 0
if(err) {
fprintf(stderr, "%d, %d ", i, err);
perror("");
}
#endif
}
}
#if 0
/*
* Check for a PnP info field starting at ofs;
* returns either the length of the field or 0 if none was found.
*
* the minfo_t struct is updated with the PnP data
*/
int is_pnpinfo(ser_device_t *mi, int ofs)
{
int i;
unsigned char *s = mi->buf + ofs;
int len = mi->buf_len - ofs;
if(len <= 0) return 0;
switch(*s) {
case 0x08:
mi->bits = 6; break;
case 0x28:
mi->bits = 7; break;
default:
return 0;
}
if(len < 11) return 0;
/* six bit values */
if((s[1] & ~0x3f) || (s[2] & ~0x3f)) return 0;
mi->pnp_rev = (s[1] << 6) + s[2];
/* the eisa id */
for(i = 0; i < 7; i++) {
mi->pnp_id[i] = s[i + 3];
if(mi->bits == 6) mi->pnp_id[i] += 0x20;
}
mi->pnp_id[7] = 0;
/* now check the id */
for(i = 0; i < 3; i++) {
if(
(mi->pnp_id[i] < 'A' || mi->pnp_id[i] > 'Z') &&
mi->pnp_id[i] != '_'
) return 0;
}
for(i = 3; i < 7; i++) {
if(
(mi->pnp_id[i] < '0' || mi->pnp_id[i] > '9') &&
(mi->pnp_id[i] < 'A' || mi->pnp_id[i] > 'F')
) return 0;
}
if(
(mi->bits == 6 && s[10] == 0x09) ||
(mi->bits == 7 && s[10] == 0x29)
) {
return 11;
}
if(
(mi->bits != 6 || s[10] != 0x3c) &&
(mi->bits != 7 || s[10] != 0x5c)
) {
return 0;
}
/* skip extended info */
for(i = 11; i < len; i++) {
if(
(mi->bits == 6 && s[i] == 0x09) ||
(mi->bits == 7 && s[i] == 0x29)
) {
return i + 1;
}
}
/*
* some mice have problems providing the extended info -> return ok in
* these cases too
*/
if(
(mi->bits == 6 && s[10] == 0x3c) ||
(mi->bits == 7 && s[10] == 0x5c)
) {
return 11;
}
/* no end token... */
return 0;
}
#endif
unsigned chk4id(ser_device_t *mi)
{
int i;
#if 0
unsigned char fake[] =
{
// fake pnp data
};
mi->buf_len = sizeof fake;
memcpy(mi->buf, fake, mi->buf_len);
// for(i = 0; i < mi->buf_len; i++) mi->buf[i] += ' ';
#endif
if(!mi->buf_len) return 0;
for(i = 0; i < mi->buf_len; i++) {
if((mi->pnp = is_pnpinfo(mi, i))) break;
}
if(i == mi->buf_len) {
/* non PnP, but MS compatible */
if(*mi->buf == 'M')
mi->non_pnp = mi->buf_len - 1;
else
return 0;
}
mi->garbage = i;
for(i = 0; i < mi->garbage; i++) {
if(mi->buf[i] == 'M') {
mi->non_pnp = mi->garbage - i;
mi->garbage = i;
break;
}
}
if(mi->non_pnp || mi->bits == 6) mi->is_mouse = 1;
return mi->is_mouse;
}
ser_device_t *add_ser_mouse_entry(ser_device_t **sm, ser_device_t *new_sm)
{
while(*sm) sm = &(*sm)->next;
return *sm = new_sm;
}
void dump_ser_mouse_data(hd_data_t *hd_data)
{
int j;
ser_device_t *sm;
if(!(sm = hd_data->ser_mouse)) return;
ADD2LOG("----- serial mice -----\n");
for(; sm; sm = sm->next) {
ADD2LOG("%s\n", sm->dev_name);
if(sm->serial) ADD2LOG("serial: \"%s\"\n", sm->serial);
if(sm->class_name) ADD2LOG("class_name: \"%s\"\n", sm->class_name);
if(sm->dev_id) ADD2LOG("dev_id: \"%s\"\n", sm->dev_id);
if(sm->user_name) ADD2LOG("user_name: \"%s\"\n", sm->user_name);
if(sm->garbage) {
ADD2LOG(" garbage[%u]: ", sm->garbage);
hexdump(&hd_data->log, 1, sm->garbage, sm->buf);
ADD2LOG("\n");
}
if(sm->non_pnp) {
ADD2LOG(" non-pnp[%u]: ", sm->non_pnp);
hexdump(&hd_data->log, 1, sm->non_pnp, sm->buf + sm->garbage);
ADD2LOG("\n");
}
if(sm->pnp) {
ADD2LOG(" pnp[%u]: ", sm->pnp);
hexdump(&hd_data->log, 1, sm->pnp, sm->buf + sm->garbage + sm->non_pnp);
ADD2LOG("\n");
}
if((j = sm->buf_len - (sm->garbage + sm->non_pnp + sm->pnp))) {
ADD2LOG(" moves[%u]: ", j);
hexdump(&hd_data->log, 1, j, sm->buf + sm->garbage + sm->non_pnp + sm->pnp);
ADD2LOG("\n");
}
if(sm->is_mouse) ADD2LOG(" is mouse\n");
if(sm->pnp) {
ADD2LOG(" bits: %u\n", sm->bits);
ADD2LOG(" PnP Rev: %u.%02u\n", sm->pnp_rev / 100, sm->pnp_rev % 100);
ADD2LOG(" PnP ID: \"%s\"\n", sm->pnp_id);
}
if(sm->next) ADD2LOG("\n");
}
ADD2LOG("----- serial mice end -----\n");
}
#endif /* !defined(LIBHD_TINY) */

View File

@@ -0,0 +1 @@
void hd_scan_mouse(hd_data_t *hd_data);

546
src/hwinfo/src/hd/net.c Normal file
View File

@@ -0,0 +1,546 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <inttypes.h>
#include <errno.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#define u8 uint8_t
#define u16 uint16_t
#define u32 uint32_t
#define u64 uint64_t
#include <linux/if.h>
#include <linux/sockios.h>
#include <linux/ethtool.h>
#include <linux/if_arp.h>
#include "hd.h"
#include "hd_int.h"
#include "net.h"
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
* gather network interface info
*
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
*/
static void get_driverinfo(hd_data_t *hd_data, hd_t *hd);
static void get_linkstate(hd_data_t *hd_data, hd_t *hd);
static void add_xpnet(hd_data_t *hdata);
static void add_iseries(hd_data_t *hdata);
static void add_uml(hd_data_t *hdata);
/*
* This is independent of the other scans.
*/
void hd_scan_net(hd_data_t *hd_data)
{
unsigned u;
int if_type;
hd_t *hd, *hd_card;
char *s, *hw_addr;
hd_res_t *res, *res1;
uint64_t ul0;
struct sysfs_class *sf_class;
struct sysfs_class_device *sf_cdev;
struct sysfs_device *sf_dev;
struct sysfs_driver *sf_drv;
struct dlist *sf_cdev_list;
if(!hd_probe_feature(hd_data, pr_net)) return;
hd_data->module = mod_net;
/* some clean-up */
remove_hd_entries(hd_data);
hd_data->net = free_str_list(hd_data->net);
PROGRESS(1, 0, "get network data");
sf_class = sysfs_open_class("net");
if(!sf_class) {
ADD2LOG("sysfs: no such class: net\n");
return;
}
sf_cdev_list = sysfs_get_class_devices(sf_class);
if(sf_cdev_list) dlist_for_each_data(sf_cdev_list, sf_cdev, struct sysfs_class_device) {
hd_card = NULL;
ADD2LOG(
" net interface: name = %s, classname = %s, path = %s\n",
sf_cdev->name,
sf_cdev->classname,
hd_sysfs_id(sf_cdev->path)
);
if_type = -1;
if(hd_attr_uint(sysfs_get_classdev_attr(sf_cdev, "type"), &ul0, 0)) {
if_type = ul0;
ADD2LOG(" type = %d\n", if_type);
}
hw_addr = NULL;
if((s = hd_attr_str(sysfs_get_classdev_attr(sf_cdev, "address")))) {
hw_addr = canon_str(s, strlen(s));
ADD2LOG(" hw_addr = %s\n", hw_addr);
}
sf_dev = sysfs_get_classdev_device(sf_cdev);
if(sf_dev) {
ADD2LOG(" net device: path = %s\n", hd_sysfs_id(sf_dev->path));
}
sf_drv = sysfs_get_classdev_driver(sf_cdev);
if(sf_drv) {
ADD2LOG(
" net driver: name = %s, path = %s\n",
sf_drv->name,
hd_sysfs_id(sf_drv->path)
);
}
hd = add_hd_entry(hd_data, __LINE__, 0);
hd->base_class.id = bc_network_interface;
hd->sub_class.id = sc_nif_other;
res1 = NULL;
if(hw_addr && strspn(hw_addr, "0:") != strlen(hw_addr)) {
res1 = new_mem(sizeof *res1);
res1->hwaddr.type = res_hwaddr;
res1->hwaddr.addr = new_str(hw_addr);
add_res_entry(&hd->res, res1);
}
hw_addr = free_mem(hw_addr);
hd->unix_dev_name = new_str(sf_cdev->name);
hd->sysfs_id = new_str(hd_sysfs_id(sf_cdev->path));
if(sf_drv) {
add_str_list(&hd->drivers, sf_drv->name);
}
else if(hd->res) {
get_driverinfo(hd_data, hd);
}
if(sf_dev) {
hd->sysfs_device_link = new_str(hd_sysfs_id(sf_dev->path));
hd_card = hd_find_sysfs_id(hd_data, hd_sysfs_id(sf_dev->path));
if(hd_card) {
hd->attached_to = hd_card->idx;
/* for cards with strange pci classes */
hd_set_hw_class(hd_card, hw_network_ctrl);
/* add hw addr to network card */
if(res1) {
u = 0;
for(res = hd_card->res; res; res = res->next) {
if(
res->any.type == res_hwaddr &&
!strcmp(res->hwaddr.addr, res1->hwaddr.addr)
) {
u = 1;
break;
}
}
if(!u) {
res = new_mem(sizeof *res);
res->hwaddr.type = res_hwaddr;
res->hwaddr.addr = new_str(res1->hwaddr.addr);
add_res_entry(&hd_card->res, res);
}
}
/* add interface names */
if(hd->unix_dev_name) {
if(!search_str_list(hd_card->unix_dev_names, hd->unix_dev_name)) {
add_str_list(&hd_card->unix_dev_names, hd->unix_dev_name);
}
if(!hd_card->unix_dev_name) {
hd_card->unix_dev_name = new_str(hd->unix_dev_name);
}
}
}
}
#if 0
"ctc" sc_nif_ctc
"iucv" sc_nif_iucv
"hsi" sc_nif_hsi
"qeth" sc_nif_qeth
"escon" sc_nif_escon
"myri" sc_nif_myrinet
"wlan" sc_nif_wlan
"xp" sc_nif_xp
"usb" sc_nif_usb
#endif
switch(if_type) {
case ARPHRD_ETHER: /* eth */
hd->sub_class.id = sc_nif_ethernet;
break;
case ARPHRD_LOOPBACK: /* lo */
hd->sub_class.id = sc_nif_loopback;
break;
case ARPHRD_SIT: /* sit */
hd->sub_class.id = sc_nif_sit;
break;
case ARPHRD_FDDI: /* fddi */
hd->sub_class.id = sc_nif_fddi;
break;
case ARPHRD_IEEE802_TR: /* tr */
hd->sub_class.id = sc_nif_tokenring;
break;
#if 0
case ARPHRD_IEEE802: /* fc */
hd->sub_class.id = sc_nif_fc;
break;
#endif
}
if(!strcmp(hd->unix_dev_name, "lo")) {
hd->sub_class.id = sc_nif_loopback;
}
else if(sscanf(hd->unix_dev_name, "eth%u", &u) == 1) {
hd->sub_class.id = sc_nif_ethernet;
hd->slot = u;
}
else if(sscanf(hd->unix_dev_name, "tr%u", &u) == 1) {
hd->sub_class.id = sc_nif_tokenring;
hd->slot = u;
}
else if(sscanf(hd->unix_dev_name, "fddi%u", &u) == 1) {
hd->sub_class.id = sc_nif_fddi;
hd->slot = u;
}
else if(sscanf(hd->unix_dev_name, "ctc%u", &u) == 1) {
hd->sub_class.id = sc_nif_ctc;
hd->slot = u;
}
else if(sscanf(hd->unix_dev_name, "iucv%u", &u) == 1) {
hd->sub_class.id = sc_nif_iucv;
hd->slot = u;
}
else if(sscanf(hd->unix_dev_name, "hsi%u", &u) == 1) {
hd->sub_class.id = sc_nif_hsi;
hd->slot = u;
}
else if(sscanf(hd->unix_dev_name, "qeth%u", &u) == 1) {
hd->sub_class.id = sc_nif_qeth;
hd->slot = u;
}
else if(sscanf(hd->unix_dev_name, "escon%u", &u) == 1) {
hd->sub_class.id = sc_nif_escon;
hd->slot = u;
}
else if(sscanf(hd->unix_dev_name, "myri%u", &u) == 1) {
hd->sub_class.id = sc_nif_myrinet;
hd->slot = u;
}
else if(sscanf(hd->unix_dev_name, "sit%u", &u) == 1) {
hd->sub_class.id = sc_nif_sit; /* ipv6 over ipv4 tunnel */
hd->slot = u;
}
else if(sscanf(hd->unix_dev_name, "wlan%u", &u) == 1) {
hd->sub_class.id = sc_nif_wlan;
hd->slot = u;
}
else if(sscanf(hd->unix_dev_name, "xp%u", &u) == 1) {
hd->sub_class.id = sc_nif_xp;
hd->slot = u;
}
else if(sscanf(hd->unix_dev_name, "usb%u", &u) == 1) {
hd->sub_class.id = sc_nif_usb;
hd->slot = u;
}
/* ##### add more interface names here */
hd->bus.id = bus_none;
/* fix card type */
if(hd_card) {
if(
(hd_card->base_class.id == 0 && hd_card->sub_class.id == 0) ||
(hd_card->base_class.id == bc_network && hd_card->sub_class.id == 0x80)
) {
switch(hd->sub_class.id) {
case sc_nif_ethernet:
hd_card->base_class.id = bc_network;
hd_card->sub_class.id = 0;
break;
case sc_nif_usb:
hd_card->base_class.id = bc_network;
hd_card->sub_class.id = 0x91;
break;
}
}
}
}
sysfs_close_class(sf_class);
if(hd_is_sgi_altix(hd_data)) add_xpnet(hd_data);
if(hd_is_iseries(hd_data)) add_iseries(hd_data);
add_uml(hd_data);
/* add link status info */
for(hd = hd_data->hd ; hd; hd = hd->next) {
if(
hd->module == hd_data->module &&
hd->base_class.id == bc_network_interface
) {
get_linkstate(hd_data, hd);
if(!(hd_card = hd_get_device_by_idx(hd_data, hd->attached_to))) continue;
for(res = hd->res; res; res = res->next) {
if(res->any.type == res_link) break;
}
if(res) {
for(res1 = hd_card->res; res1; res1 = res1->next) {
if(res1->any.type == res_link) break;
}
if(res && !res1) {
res1 = new_mem(sizeof *res1);
res1->link.type = res_link;
res1->link.state = res->link.state;
add_res_entry(&hd_card->res, res1);
}
}
}
}
}
/*
* Get it the classical way, for drivers that don't support sysfs (veth).
*/
void get_driverinfo(hd_data_t *hd_data, hd_t *hd)
{
int fd;
struct ethtool_drvinfo drvinfo = { cmd:ETHTOOL_GDRVINFO };
struct ifreq ifr;
if(!hd->unix_dev_name) return;
if(strlen(hd->unix_dev_name) > sizeof ifr.ifr_name - 1) return;
if((fd = socket(PF_INET, SOCK_DGRAM, 0)) == -1) return;
/* get driver info */
memset(&ifr, 0, sizeof ifr);
strcpy(ifr.ifr_name, hd->unix_dev_name);
ifr.ifr_data = (caddr_t) &drvinfo;
if(ioctl(fd, SIOCETHTOOL, &ifr) == 0) {
ADD2LOG(" ethtool driver: %s\n", drvinfo.driver);
ADD2LOG(" ethtool bus: %s\n", drvinfo.bus_info);
add_str_list(&hd->drivers, drvinfo.driver);
}
else {
ADD2LOG(" GDRVINFO ethtool error: %s\n", strerror(errno));
}
close(fd);
}
/*
* Check network link status.
*/
void get_linkstate(hd_data_t *hd_data, hd_t *hd)
{
int fd;
struct ethtool_value linkstatus = { cmd:ETHTOOL_GLINK };
struct ifreq ifr;
hd_res_t *res;
if(!hd->unix_dev_name) return;
if(strlen(hd->unix_dev_name) > sizeof ifr.ifr_name - 1) return;
if((fd = socket(PF_INET, SOCK_DGRAM, 0)) == -1) return;
/* get driver info */
memset(&ifr, 0, sizeof ifr);
strcpy(ifr.ifr_name, hd->unix_dev_name);
ifr.ifr_data = (caddr_t) &linkstatus;
if(ioctl(fd, SIOCETHTOOL, &ifr) == 0) {
ADD2LOG(" %s: ethtool link state: %d\n", hd->unix_dev_name, linkstatus.data);
res = new_mem(sizeof *res);
res->link.type = res_link;
res->link.state = linkstatus.data ? 1 : 0;
add_res_entry(&hd->res, res);
}
else {
ADD2LOG(" %s: GLINK ethtool error: %s\n", hd->unix_dev_name, strerror(errno));
}
close(fd);
}
/*
* SGI Altix cross partition network.
*/
void add_xpnet(hd_data_t *hd_data)
{
hd_t *hd, *hd_card;
hd_res_t *res, *res2;
hd_card = add_hd_entry(hd_data, __LINE__, 0);
hd_card->base_class.id = bc_network;
hd_card->sub_class.id = 0x83;
hd_card->vendor.id = MAKE_ID(TAG_SPECIAL, 0x4002);
hd_card->device.id = MAKE_ID(TAG_SPECIAL, 1);
if(hd_module_is_active(hd_data, "xpnet")) {
add_str_list(&hd_card->drivers, "xpnet");
}
for(hd = hd_data->hd ; hd; hd = hd->next) {
if(
hd->module == hd_data->module &&
hd->base_class.id == bc_network_interface &&
hd->sub_class.id == sc_nif_xp
) {
hd->attached_to = hd_card->idx;
for(res = hd->res; res; res = res->next) {
if(res->any.type == res_hwaddr) break;
}
if(res) {
res2 = new_mem(sizeof *res2);
res2->hwaddr.type = res_hwaddr;
res2->hwaddr.addr = new_str(res->hwaddr.addr);
add_res_entry(&hd_card->res, res2);
}
break;
}
}
}
/*
* iSeries veth devices.
*/
void add_iseries(hd_data_t *hd_data)
{
hd_t *hd, *hd_card;
hd_res_t *res, *res2;
unsigned i, cardmask = 0, card_cnt = 0;
str_list_t *sl0, *sl;
for(hd = hd_data->hd ; hd; hd = hd->next) {
if(
hd->module == hd_data->module &&
hd->base_class.id == bc_network_interface &&
search_str_list(hd->drivers, "veth")
) {
hd_card = add_hd_entry(hd_data, __LINE__, 0);
hd_card->base_class.id = bc_network;
hd_card->sub_class.id = 0x00;
hd_card->vendor.id = MAKE_ID(TAG_SPECIAL, 0x6001); // IBM
hd_card->device.id = MAKE_ID(TAG_SPECIAL, 0x1000);
add_str_list(&hd_card->drivers, "iseries_veth");
hd_card->slot = card_cnt++;
str_printf(&hd_card->device.name, 0, "Virtual Ethernet card");
hd->attached_to = hd_card->idx;
for(res = hd->res; res; res = res->next) {
if(res->any.type == res_hwaddr) break;
}
if(res) {
unsigned int slotno;
res2 = new_mem(sizeof *res2);
res2->hwaddr.type = res_hwaddr;
res2->hwaddr.addr = new_str(res->hwaddr.addr);
add_res_entry(&hd_card->res, res2);
if (sscanf(res->hwaddr.addr, "02:01:ff:%x:ff:", &slotno)) {
hd_card->slot = slotno;
str_printf(&hd_card->device.name, 0, "Virtual Ethernet card %d", hd_card->slot);
}
}
}
}
if(!card_cnt) {
sl0 = read_file("/proc/iSeries/config", 0, 0);
for(sl = sl0; sl; sl = sl->next) {
if(sscanf(sl->str, "AVAILABLE_VETH=%x", &cardmask) == 1)
break;
}
free_str_list(sl0);
for (i = 0; i < 16; i++) {
if ((0x8000 >> i) & cardmask) {
hd_card = add_hd_entry(hd_data, __LINE__, 0);
hd_card->base_class.id = bc_network;
hd_card->sub_class.id = 0x00;
hd_card->vendor.id = MAKE_ID(TAG_SPECIAL, 0x6001); // IBM
hd_card->device.id = MAKE_ID(TAG_SPECIAL, 0x1000);
hd_card->slot = i;
str_printf(&hd_card->device.name, 0, "Virtual Ethernet card %d", i);
}
}
}
}
/*
* UML veth devices.
*/
void add_uml(hd_data_t *hd_data)
{
hd_t *hd, *hd_card;
hd_res_t *res, *res2;
unsigned card_cnt = 0;
for(hd = hd_data->hd ; hd; hd = hd->next) {
if(
hd->module == hd_data->module &&
hd->base_class.id == bc_network_interface &&
search_str_list(hd->drivers, "uml virtual ethernet")
) {
hd_card = add_hd_entry(hd_data, __LINE__, 0);
hd_card->base_class.id = bc_network;
hd_card->sub_class.id = 0x00;
hd_card->vendor.id = MAKE_ID(TAG_SPECIAL, 0x6010); // UML
hd_card->device.id = MAKE_ID(TAG_SPECIAL, 0x0001);
hd_card->slot = card_cnt++;
str_printf(&hd_card->device.name, 0, "Virtual Ethernet card %d", hd_card->slot);
// add_str_list(&hd_card->drivers, "veth");
hd->attached_to = hd_card->idx;
for(res = hd->res; res; res = res->next) {
if(res->any.type == res_hwaddr) break;
}
if(res) {
res2 = new_mem(sizeof *res2);
res2->hwaddr.type = res_hwaddr;
res2->hwaddr.addr = new_str(res->hwaddr.addr);
add_res_entry(&hd_card->res, res2);
}
}
}
}

1
src/hwinfo/src/hd/net.h Normal file
View File

@@ -0,0 +1 @@
void hd_scan_net(hd_data_t *hd_data);

View File

@@ -0,0 +1,295 @@
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "hd.h"
#include "hd_int.h"
#include "parallel.h"
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
* parallel port device info
*
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
*/
#ifndef LIBHD_TINY
static void do_lp(hd_data_t *hd_data);
static void do_zip(hd_data_t *hd_data);
static void dump_parallel_data(hd_data_t *hd_data, str_list_t *sl);
void hd_scan_parallel(hd_data_t *hd_data)
{
if(!hd_probe_feature(hd_data, pr_parallel)) return;
hd_data->module = mod_parallel;
/* some clean-up */
remove_hd_entries(hd_data);
if(hd_probe_feature(hd_data, pr_parallel_lp)) do_lp(hd_data);
if(hd_probe_feature(hd_data, pr_parallel_zip)) do_zip(hd_data);
}
void do_lp(hd_data_t *hd_data)
{
hd_t *hd, *hd_i;
str_list_t *sl, *sl0;
hd_res_t *res;
char *pp = NULL, buf[256], unix_dev[] = "/dev/lp0", *s = NULL;
char *base_class, *device, *vendor, *cmd_set;
int i, j, port;
str_list_t *log = NULL;
PROGRESS(1, 0, "pp mod");
for(hd = hd_data->hd; hd; hd = hd->next) {
if(hd->base_class.id == bc_comm && hd->sub_class.id == sc_com_par) break;
}
/* ... if there seems to be a parallel interface, try to load it */
if(hd || 1) { /* always load it */
if(hd_data->kernel_version == KERNEL_22) {
unload_module(hd_data, "parport_probe");
probe_module(hd_data, "parport_probe");
} else {
unload_module(hd_data, "lp");
unload_module(hd_data, "parport_pc");
probe_module(hd_data, "parport_pc");
}
}
for(i = 0; i < 3; i++, unix_dev[sizeof unix_dev - 2]++) {
PROGRESS(2, 1 + i, "lp read info");
port = 0;
// ##### read modes as well? (e.g: SPP,ECP,ECPEPP,ECPPS2)
if(hd_data->kernel_version == KERNEL_22)
str_printf(&pp, 0, PROC_PARPORT_22 "%d/hardware", i);
else
str_printf(&pp, 0, PROC_PARPORT_24 "%d/base-addr", i);
sl0 = read_file(pp, 0, 0);
if(!sl0) continue; /* file doesn't exist -> no parport entry */
str_printf(&s, 0, "%s\n", pp);
add_str_list(&log, s);
for(sl = sl0; sl; sl = sl->next) {
str_printf(&s, 0, " %s", sl->str);
add_str_list(&log, s);
if(hd_data->kernel_version == KERNEL_22) {
if(sscanf(sl->str, "base: %i", &j) == 1) port = j;
} else {
if(sscanf(sl->str, "%i", &j) == 1) port = j;
}
}
free_str_list(sl0);
if(hd_data->kernel_version == KERNEL_22)
str_printf(&pp, 0, PROC_PARPORT_22 "%d/autoprobe", i);
else
str_printf(&pp, 0, PROC_PARPORT_24 "%d/autoprobe", i);
sl0 = read_file(pp, 0, 0);
str_printf(&s, 0, "%s\n", pp);
add_str_list(&log, s);
base_class = device = vendor = cmd_set = NULL;
for(sl = sl0; sl; sl = sl->next) {
str_printf(&s, 0, " %s", sl->str);
add_str_list(&log, s);
// fprintf(stderr, "str = \"%s\"\n", sl->str);
if(sscanf(sl->str, "CLASS: %255[^\n;]", buf) == 1) base_class = new_str(buf);
if(sscanf(sl->str, "MODEL: %255[^\n;]", buf) == 1) device = new_str(buf);
if(sscanf(sl->str, "MANUFACTURER: %255[^\n;]", buf) == 1) vendor = new_str(buf);
if(sscanf(sl->str, "COMMAND SET: %255[^\n;]", buf) == 1) cmd_set = new_str(buf);
}
free_str_list(sl0);
/* default to printer */
if(!base_class && vendor && device) base_class = new_str("printer");
s = free_mem(s);
// fprintf(stderr, "port <0x%x\n", port);
// fprintf(stderr, "class <%s>\n", base_class);
// fprintf(stderr, "device <%s>\n", device);
// fprintf(stderr, "vendor <%s>\n", vendor);
// fprintf(stderr, "cmds <%s>\n", cmd_set);
for(hd = hd_data->hd; hd; hd = hd->next) {
if(
hd->base_class.id == bc_comm &&
hd->sub_class.id == sc_com_par &&
hd->unix_dev_name &&
!strcmp(hd->unix_dev_name, unix_dev)
) break;
}
if(!hd) {
/* no entry ??? */
hd = add_hd_entry(hd_data, __LINE__, 0);
hd->base_class.id = bc_comm;
hd->sub_class.id = sc_com_par;
hd->unix_dev_name = new_str(unix_dev);
if(port) {
res = add_res_entry(&hd->res, new_mem(sizeof *res));
res->io.type = res_io;
res->io.enabled = 1;
res->io.base = port;
res->io.access = acc_rw;
}
}
// ##### check if ports match?
if(
base_class ||
(device && strcmp(device, "Unknown device")) ||
(vendor && strcmp(vendor, "Unknown vendor"))
) {
hd_i = hd;
hd = add_hd_entry(hd_data, __LINE__, 0);
hd->attached_to = hd_i->idx;
hd->unix_dev_name = new_str(hd_i->unix_dev_name);
hd->base_class.id = bc_none;
if(base_class && !strcasecmp(base_class, "printer")) hd->base_class.id = bc_printer;
hd->bus.id = bus_parallel;
hd->vendor.name = new_str(vendor);
hd->device.name = new_str(device);
}
free_mem(base_class);
free_mem(device);
free_mem(vendor);
free_mem(cmd_set);
}
pp = free_mem(pp);
if((hd_data->debug & HD_DEB_PARALLEL)) dump_parallel_data(hd_data, log);
free_str_list(log);
}
void do_zip(hd_data_t *hd_data)
{
hd_t *hd, *hd_i;
int i, j, port, is_imm, is_ppa, is_imm0, is_ppa0;
char *pp = NULL, *s = NULL, *unix_dev = NULL;
str_list_t *log = NULL, *sl, *sl0;
int do_imm = hd_probe_feature(hd_data, pr_parallel_imm);
is_imm = is_imm0 = hd_module_is_active(hd_data, "imm");
is_ppa = is_ppa0 = hd_module_is_active(hd_data, "ppa");
if(!(is_imm || is_ppa)) {
for(hd = hd_data->hd; hd; hd = hd->next) {
if(hd->base_class.id == bc_comm && hd->sub_class.id == sc_com_par) break;
}
/* ... if there seems to be a parallel interface, try to load it */
if(hd) {
if(do_imm) {
PROGRESS(5, 0, "imm mod");
load_module(hd_data, "imm");
}
PROGRESS(5, 0, "ppa mod");
load_module(hd_data, "ppa");
is_imm = hd_module_is_active(hd_data, "imm");
is_ppa = hd_module_is_active(hd_data, "ppa");
if(do_imm && !is_imm) {
int fd;
char flush[2] = { 4, 12 };
fd = open("/dev/lp0", O_NONBLOCK | O_WRONLY);
if(fd != -1) {
write(fd, flush, sizeof flush);
close(fd);
}
}
}
}
if(!(is_imm || is_ppa)) return;
PROGRESS(6, 0, "zip read info");
for(i = 0; i < 16; i++) {
str_printf(&pp, 0, PROC_SCSI "/%s/%d", (i % 2) ? "ppa" : "imm", i / 2);
sl0 = read_file(pp, 0, 0);
if(!sl0) continue;
str_printf(&s, 0, "%s\n", pp);
add_str_list(&log, s);
port = -1;
for(sl = sl0; sl; sl = sl->next) {
str_printf(&s, 0, " %s", sl->str);
add_str_list(&log, s);
if(sscanf(sl->str, "Parport : parport%d", &j) == 1) port = j;
}
free_str_list(sl0);
pp = free_mem(pp);
s = free_mem(s);
unix_dev = free_mem(unix_dev);
if(port >= 0) {
str_printf(&unix_dev, 0, "/dev/lp%d", port);
}
hd = NULL;
if(unix_dev) {
for(hd = hd_data->hd; hd; hd = hd->next) {
if(
hd->base_class.id == bc_comm &&
hd->sub_class.id == sc_com_par &&
hd->unix_dev_name &&
!strcmp(hd->unix_dev_name, unix_dev)
) break;
}
if(!hd) {
/* no entry ??? */
hd = add_hd_entry(hd_data, __LINE__, 0);
hd->base_class.id = bc_comm;
hd->sub_class.id = sc_com_par;
hd->unix_dev_name = new_str(unix_dev);
}
}
hd_i = hd;
hd = add_hd_entry(hd_data, __LINE__, 0);
if(hd_i) {
hd->attached_to = hd_i->idx;
hd->unix_dev_name = new_str(hd_i->unix_dev_name);
}
hd->base_class.id = bc_storage;
hd->sub_class.id = sc_sto_scsi;
hd->bus.id = bus_parallel;
hd->vendor.id = MAKE_ID(TAG_SPECIAL, 0x1800);
hd->device.id = MAKE_ID(TAG_SPECIAL, (i % 2) ? 2 : 1);
}
if(!is_imm0) unload_module(hd_data, "imm");
if(!is_ppa0) unload_module(hd_data, "ppa");
if((hd_data->debug & HD_DEB_PARALLEL)) dump_parallel_data(hd_data, log);
free_mem(unix_dev);
free_str_list(log);
}
void dump_parallel_data(hd_data_t *hd_data, str_list_t *sl)
{
ADD2LOG("----- parallel info -----\n");
for(; sl; sl = sl->next) {
ADD2LOG("%s", sl->str);
}
ADD2LOG("----- parallel info end -----\n");
}
#endif /* ifndef LIBHD_TINY */

View File

@@ -0,0 +1 @@
void hd_scan_parallel(hd_data_t *hd_data);

604
src/hwinfo/src/hd/pci.c Normal file
View File

@@ -0,0 +1,604 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <fcntl.h>
#include <ctype.h>
#include <sys/stat.h>
#include <sys/types.h>
typedef unsigned long kernel_ulong_t;
#include <linux/types.h>
#ifdef __UCLIBC__
#include <linux/pci.h>
#else
#include <sys/pci.h>
#endif
#include "hd.h"
#include "hd_int.h"
#include "hddb.h"
#include "pci.h"
/*
* linux/ioport.h
*/
#define IORESOURCE_BITS 0x000000ff
#define IORESOURCE_IO 0x00000100
#define IORESOURCE_MEM 0x00000200
#define IORESOURCE_IRQ 0x00000400
#define IORESOURCE_DMA 0x00000800
#define IORESOURCE_PREFETCH 0x00001000
#define IORESOURCE_READONLY 0x00002000
#define IORESOURCE_CACHEABLE 0x00004000
#define IORESOURCE_DISABLED 0x10000000
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
* pci stuff
*
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
*/
static struct sysfs_attribute *hd_read_single_sysfs_attribute(char *path, char *name);
static void get_pci_data(hd_data_t *hd_data);
static void add_pci_data(hd_data_t *hd_data);
static void add_driver_info(hd_data_t *hd_data);
static pci_t *add_pci_entry(hd_data_t *hd_data, pci_t *new_pci);
static unsigned char pci_cfg_byte(pci_t *pci, int fd, unsigned idx);
static void dump_pci_data(hd_data_t *hd_data);
void hd_scan_sysfs_pci(hd_data_t *hd_data)
{
if(!hd_probe_feature(hd_data, pr_pci)) return;
hd_data->module = mod_pci;
/* some clean-up */
remove_hd_entries(hd_data);
hd_data->pci = NULL;
PROGRESS(1, 0, "sysfs drivers");
hd_sysfs_driver_list(hd_data);
PROGRESS(2, 0, "get sysfs pci data");
get_pci_data(hd_data);
if(hd_data->debug) dump_pci_data(hd_data);
add_pci_data(hd_data);
}
/*
* sysfs_get_device_attr() reads *all* device attributes, then returns the
* requested one.
*
* This leads to problems where some attribute *must not* be read.
*/
struct sysfs_attribute *hd_read_single_sysfs_attribute(char *path, char *name)
{
char *attr_path = NULL;
struct sysfs_attribute *attr;
str_printf(&attr_path, 0, "%s/%s", path, name);
attr = sysfs_open_attribute(attr_path);
free_mem(attr_path);
sysfs_read_attribute(attr);
return attr;
}
/*
* Get the (raw) PCI data, taken from /sys/bus/pci/.
*
* Note: non-root users can only read the first 64 bytes (of 256)
* of the device headers.
*/
void get_pci_data(hd_data_t *hd_data)
{
uint64_t ul0, ul1, ul2;
unsigned u, u0, u1, u2, u3;
unsigned char nxt;
str_list_t *sl;
char *s;
pci_t *pci;
int fd;
struct sysfs_bus *sf_bus;
struct dlist *sf_dev_list;
struct sysfs_device *sf_dev;
struct sysfs_attribute *attr;
sf_bus = sysfs_open_bus("pci");
if(!sf_bus) {
ADD2LOG("sysfs: no such bus: pci\n");
return;
}
sf_dev_list = sysfs_get_bus_devices(sf_bus);
if(sf_dev_list) dlist_for_each_data(sf_dev_list, sf_dev, struct sysfs_device) {
ADD2LOG(
" pci device: name = %s, bus_id = %s, bus = %s\n path = %s\n",
sf_dev->name,
sf_dev->bus_id,
sf_dev->bus,
hd_sysfs_id(sf_dev->path)
);
if(sscanf(sf_dev->bus_id, "%x:%x:%x.%x", &u0, &u1, &u2, &u3) != 4) continue;
pci = add_pci_entry(hd_data, new_mem(sizeof *pci));
pci->sysfs_id = new_str(sf_dev->path);
pci->sysfs_bus_id = new_str(sf_dev->bus_id);
pci->bus = (u0 << 8) + u1;
pci->slot = u2;
pci->func = u3;
if(hd_attr_uint(attr = hd_read_single_sysfs_attribute(sf_dev->path, "class"), &ul0, 0)) {
ADD2LOG(" class = 0x%x\n", (unsigned) ul0);
pci->prog_if = ul0 & 0xff;
pci->sub_class = (ul0 >> 8) & 0xff;
pci->base_class = (ul0 >> 16) & 0xff;
}
sysfs_close_attribute(attr);
if(hd_attr_uint(attr = hd_read_single_sysfs_attribute(sf_dev->path, "vendor"), &ul0, 0)) {
ADD2LOG(" vendor = 0x%x\n", (unsigned) ul0);
pci->vend = ul0 & 0xffff;
}
sysfs_close_attribute(attr);
if(hd_attr_uint(attr = hd_read_single_sysfs_attribute(sf_dev->path, "device"), &ul0, 0)) {
ADD2LOG(" device = 0x%x\n", (unsigned) ul0);
pci->dev = ul0 & 0xffff;
}
sysfs_close_attribute(attr);
if(hd_attr_uint(attr = hd_read_single_sysfs_attribute(sf_dev->path, "subsystem_vendor"), &ul0, 0)) {
ADD2LOG(" subvendor = 0x%x\n", (unsigned) ul0);
pci->sub_vend = ul0 & 0xffff;
}
sysfs_close_attribute(attr);
if(hd_attr_uint(attr = hd_read_single_sysfs_attribute(sf_dev->path, "subsystem_device"), &ul0, 0)) {
ADD2LOG(" subdevice = 0x%x\n", (unsigned) ul0);
pci->sub_dev = ul0 & 0xffff;
}
sysfs_close_attribute(attr);
if(hd_attr_uint(attr = hd_read_single_sysfs_attribute(sf_dev->path, "irq"), &ul0, 0)) {
ADD2LOG(" irq = %d\n", (unsigned) ul0);
pci->irq = ul0;
}
sysfs_close_attribute(attr);
sl = hd_attr_list(attr = hd_read_single_sysfs_attribute(sf_dev->path, "resource"));
for(u = 0; sl; sl = sl->next, u++) {
if(
sscanf(sl->str, "0x%"SCNx64" 0x%"SCNx64" 0x%"SCNx64, &ul0, &ul1, &ul2) == 3 &&
ul1 &&
u < sizeof pci->base_addr / sizeof *pci->base_addr
) {
ADD2LOG(" res[%u] = 0x%"PRIx64" 0x%"PRIx64" 0x%"PRIx64"\n", u, ul0, ul1, ul2);
pci->base_addr[u] = ul0;
pci->base_len[u] = ul1 + 1 - ul0;
pci->addr_flags[u] = ul2;
}
}
sysfs_close_attribute(attr);
s = NULL;
str_printf(&s, 0, "%s/config", sf_dev->path);
if((fd = open(s, O_RDONLY)) != -1) {
pci->data_len = pci->data_ext_len = read(fd, pci->data, 0x40);
ADD2LOG(" config[%u]\n", pci->data_len);
if(pci->data_len >= 0x40) {
pci->hdr_type = pci->data[PCI_HEADER_TYPE] & 0x7f;
pci->cmd = pci->data[PCI_COMMAND] + (pci->data[PCI_COMMAND + 1] << 8);
if(pci->hdr_type == 1 || pci->hdr_type == 2) { /* PCI or CB bridge */
pci->secondary_bus = pci->data[PCI_SECONDARY_BUS];
/* PCI_SECONDARY_BUS == PCI_CB_CARD_BUS */
}
for(u = 0; u < sizeof pci->base_addr / sizeof *pci->base_addr; u++) {
if((pci->addr_flags[u] & IORESOURCE_IO)) {
if(!(pci->cmd & PCI_COMMAND_IO)) pci->addr_flags[u] |= IORESOURCE_DISABLED;
}
if((pci->addr_flags[u] & IORESOURCE_MEM)) {
if(!(pci->cmd & PCI_COMMAND_MEMORY)) pci->addr_flags[u] |= IORESOURCE_DISABLED;
}
}
/* let's get through the capability list */
if(
pci->hdr_type == PCI_HEADER_TYPE_NORMAL &&
(nxt = pci->data[PCI_CAPABILITY_LIST])
) {
/*
* Cut out after 16 capabilities to avoid infinite recursion due
* to (potentially) malformed data. 16 is more or less
* arbitrary, though (the capabilities are bits in a byte, so 8 entries
* should suffice).
*/
for(u = 0; u < 16 && nxt && nxt <= 0xfe; u++) {
switch(pci_cfg_byte(pci, fd, nxt)) {
case PCI_CAP_ID_PM:
pci->flags |= (1 << pci_flag_pm);
break;
case PCI_CAP_ID_AGP:
pci->flags |= (1 << pci_flag_agp);
break;
}
nxt = pci_cfg_byte(pci, fd, nxt + 1);
}
}
}
close(fd);
}
s = free_mem(s);
pci->rev = pci->data[PCI_REVISION_ID];
if((pci->addr_flags[6] & IORESOURCE_MEM)) {
if(!(pci->data[PCI_ROM_ADDRESS] & PCI_ROM_ADDRESS_ENABLE)) {
pci->addr_flags[6] |= IORESOURCE_DISABLED;
}
}
pci->flags |= (1 << pci_flag_ok);
}
sysfs_close_bus(sf_bus);
}
void add_pci_data(hd_data_t *hd_data)
{
hd_t *hd, *hd2;
pci_t *pci, *pnext;
hd_res_t *res;
unsigned u;
char *s, *t;
PROGRESS(4, 0, "build list");
for(pci = hd_data->pci; pci; pci = pnext) {
pnext = pci->next;
hd = add_hd_entry(hd_data, __LINE__, 0);
hd->sysfs_id = new_str(hd_sysfs_id(pci->sysfs_id));
s = hd_sysfs_find_driver(hd_data, hd->sysfs_id, 1);
if(s) add_str_list(&hd->drivers, s);
if(pci->sysfs_bus_id && *pci->sysfs_bus_id) {
hd->sysfs_bus_id = new_str(pci->sysfs_bus_id);
}
hd->bus.id = bus_pci;
hd->slot = pci->slot + (pci->bus << 8);
hd->func = pci->func;
hd->base_class.id = pci->base_class;
hd->sub_class.id = pci->sub_class;
hd->prog_if.id = pci->prog_if;
/* fix up old VGA's entries */
if(hd->base_class.id == bc_none && hd->sub_class.id == 0x01) {
hd->base_class.id = bc_display;
hd->sub_class.id = sc_dis_vga;
}
if(pci->dev || pci->vend) {
hd->device.id = MAKE_ID(TAG_PCI, pci->dev);
hd->vendor.id = MAKE_ID(TAG_PCI, pci->vend);
}
if(pci->sub_dev || pci->sub_vend) {
hd->sub_device.id = MAKE_ID(TAG_PCI, pci->sub_dev);
hd->sub_vendor.id = MAKE_ID(TAG_PCI, pci->sub_vend);
}
hd->revision.id = pci->rev;
if((u = device_class(hd_data, hd->vendor.id, hd->device.id))) {
hd->base_class.id = u >> 8;
hd->sub_class.id = u & 0xff;
}
for(u = 0; u < sizeof pci->base_addr / sizeof *pci->base_addr; u++) {
if((pci->addr_flags[u] & IORESOURCE_IO)) {
res = new_mem(sizeof *res);
res->io.type = res_io;
res->io.enabled = pci->addr_flags[u] & IORESOURCE_DISABLED ? 0 : 1;
res->io.base = pci->base_addr[u];
res->io.range = pci->base_len[u];
res->io.access = pci->addr_flags[u] & IORESOURCE_READONLY ? acc_ro : acc_rw;
add_res_entry(&hd->res, res);
}
if((pci->addr_flags[u] & IORESOURCE_MEM)) {
res = new_mem(sizeof *res);
res->mem.type = res_mem;
res->mem.enabled = pci->addr_flags[u] & IORESOURCE_DISABLED ? 0 : 1;
res->mem.base = pci->base_addr[u];
res->mem.range = pci->base_len[u];
res->mem.access = pci->addr_flags[u] & IORESOURCE_READONLY ? acc_ro : acc_rw;
res->mem.prefetch = pci->addr_flags[u] & IORESOURCE_PREFETCH ? flag_yes : flag_no;
add_res_entry(&hd->res, res);
}
}
if(pci->irq) {
res = new_mem(sizeof *res);
res->irq.type = res_irq;
res->irq.enabled = 1;
res->irq.base = pci->irq;
add_res_entry(&hd->res, res);
}
hd->detail = new_mem(sizeof *hd->detail);
hd->detail->type = hd_detail_pci;
hd->detail->pci.data = pci;
if(pci->flags & (1 << pci_flag_agp)) hd->is.agp = 1;
pci->next = NULL;
}
hd_data->pci = NULL;
for(hd = hd_data->hd; hd; hd = hd->next) {
if(hd->bus.id == bus_pci && hd->sysfs_id) {
s = new_str(hd->sysfs_id);
if((t = strrchr(s, '/'))) {
*t = 0;
if((hd2 = hd_find_sysfs_id(hd_data, s))) {
hd->attached_to = hd2->idx;
}
}
free_mem(s);
}
}
add_driver_info(hd_data);
}
/*
* Add driver info in some special cases.
*/
void add_driver_info(hd_data_t *hd_data)
{
hd_t *hd;
hd_res_t *res;
for(hd = hd_data->hd; hd; hd = hd->next) {
if(hd->bus.id != bus_pci) continue;
if(
(
hd->base_class.id == bc_serial &&
hd->sub_class.id == sc_ser_fire
) ||
(
hd->base_class.id == bc_serial &&
hd->sub_class.id == sc_ser_usb
)
) {
for(res = hd->res; res; res = res->next) {
if(res->any.type == res_irq) break;
}
if(!res) hd->is.notready = 1;
continue;
}
}
}
#if 1
/*
* Store a raw PCI entry; just for convenience.
*/
pci_t *add_pci_entry(hd_data_t *hd_data, pci_t *new_pci)
{
pci_t **pci = &hd_data->pci;
while(*pci) pci = &(*pci)->next;
return *pci = new_pci;
}
#else
/*
* Store a raw PCI entry; just for convenience.
*
* Reverse order.
*/
pci_t *add_pci_entry(hd_data_t *hd_data, pci_t *new_pci)
{
new_pci->next = hd_data->pci;
return hd_data->pci = new_pci;
}
#endif
/*
* get a byte from pci config space
*/
unsigned char pci_cfg_byte(pci_t *pci, int fd, unsigned idx)
{
unsigned char uc;
if(idx >= sizeof pci->data) return 0;
if(idx < pci->data_len) return pci->data[idx];
if(idx < pci->data_ext_len && pci->data[idx]) return pci->data[idx];
if(lseek(fd, idx, SEEK_SET) != (off_t) idx) return 0;
if(read(fd, &uc, 1) != 1) return 0;
pci->data[idx] = uc;
if(idx >= pci->data_ext_len) pci->data_ext_len = idx + 1;
return uc;
}
/*
* Add a dump of all raw PCI data to the global log.
*/
void dump_pci_data(hd_data_t *hd_data)
{
pci_t *pci;
char *s = NULL;
char buf[32];
int i, j;
ADD2LOG("---------- PCI raw data ----------\n");
for(pci = hd_data->pci; pci; pci = pci->next) {
if(!(pci->flags & (1 << pci_flag_ok))) str_printf(&s, -1, "oops");
if(pci->flags & (1 << pci_flag_pm)) str_printf(&s, -1, ",pm");
if(pci->flags & (1 << pci_flag_agp)) str_printf(&s, -1, ",agp");
if(!s) str_printf(&s, 0, "%s", "");
*buf = 0;
if(pci->secondary_bus) {
sprintf(buf, "->%02x", pci->secondary_bus);
}
ADD2LOG(
"bus %02x%s, slot %02x, func %x, vend:dev:s_vend:s_dev:rev %04x:%04x:%04x:%04x:%02x\n",
pci->bus, buf, pci->slot, pci->func, pci->vend, pci->dev, pci->sub_vend, pci->sub_dev, pci->rev
);
ADD2LOG(
"class %02x, sub_class %02x prog_if %02x, hdr %x, flags <%s>, irq %u\n",
pci->base_class, pci->sub_class, pci->prog_if, pci->hdr_type, *s == ',' ? s + 1 : s, pci->irq
);
s = free_mem(s);
for(i = 0; i < 6; i++) {
if(pci->base_addr[i] || pci->base_len[i])
ADD2LOG(" addr%d %08"PRIx64", size %08"PRIx64"\n", i, pci->base_addr[i], pci->base_len[i]);
}
if(pci->rom_base_addr)
ADD2LOG(" rom %08"PRIx64"\n", pci->rom_base_addr);
if(pci->log) ADD2LOG("%s", pci->log);
for(i = 0; (unsigned) i < pci->data_ext_len; i += 0x10) {
ADD2LOG(" %02x: ", i);
j = pci->data_ext_len - i;
hexdump(&hd_data->log, 1, j > 0x10 ? 0x10 : j, pci->data + i);
ADD2LOG("\n");
}
if(pci->next) ADD2LOG("\n");
}
ADD2LOG("---------- PCI raw data end ----------\n");
}
/*
* Parse attribute and return integer value.
*/
int hd_attr_uint(struct sysfs_attribute *attr, uint64_t *u, int base)
{
char *s;
uint64_t u2;
int ok;
if(!(s = hd_attr_str(attr))) return 0;
u2 = strtoull(s, &s, base);
ok = !*s || isspace(*s) ? 1 : 0;
if(ok && u) *u = u2;
return ok;
}
/*
* Return attribute as string list.
*/
str_list_t *hd_attr_list(struct sysfs_attribute *attr)
{
static str_list_t *sl = NULL;
free_str_list(sl);
return sl = hd_split('\n', hd_attr_str(attr));
}
/*
* Return attribute as string.
*/
char *hd_attr_str(struct sysfs_attribute *attr)
{
return attr ? attr->value : NULL;
}
/*
* Remove leading "/sys" from path.
*/
char *hd_sysfs_id(char *path)
{
if(!path || !*path) return NULL;
return strchr(path + 1, '/');
}
/*
* Convert '!' to '/'.
*/
char *hd_sysfs_name2_dev(char *str)
{
static char *s = NULL;
if(!str) return NULL;
free_mem(s);
s = str = new_str(str);
while(*str) {
if(*str == '!') *str = '/';
str++;
}
return s;
}
/*
* Convert '/' to '!'.
*/
char *hd_sysfs_dev2_name(char *str)
{
static char *s = NULL;
if(!str) return NULL;
free_mem(s);
s = str = new_str(str);
while(*str) {
if(*str == '/') *str = '!';
str++;
}
return s;
}

1
src/hwinfo/src/hd/pci.h Normal file
View File

@@ -0,0 +1 @@
void hd_scan_sysfs_pci(hd_data_t *hd_data);

272
src/hwinfo/src/hd/pcmcia.c Normal file
View File

@@ -0,0 +1,272 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <dirent.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mount.h>
#include <linux/hdreg.h>
#include "hd.h"
#include "hd_int.h"
#include "pcmcia.h"
static void read_cardinfo(hd_data_t *hd_data);
static void assign_bridges(hd_data_t *hd_data);
static void add_sysfs_stuff(hd_data_t *hd_data, hd_t *hd);
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
* PCMCIA info via cardctl
*
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
*/
void hd_scan_pcmcia(hd_data_t *hd_data)
{
if(!hd_probe_feature(hd_data, pr_pcmcia)) return;
hd_data->module = mod_pcmcia;
/* some clean-up */
remove_hd_entries(hd_data);
read_cardinfo(hd_data);
assign_bridges(hd_data);
}
void read_cardinfo(hd_data_t *hd_data)
{
str_list_t *sl, *sl0, *sl1;
int i0, i1, pcmcia_sock, manf_id0, manf_id1, func, prod_info;
char buf0[256], buf1[256], buf2[256], buf3[256];
hd_t *hd;
unsigned cardbus = 0; /* bitmask: cardbus vs. pc-card */
sl0 = read_file("| /sbin/cardctl status 2>/dev/null", 0, 0);
ADD2LOG("----- cardctl status -----\n");
for(sl = sl0; sl; sl = sl->next) {
ADD2LOG(" %s", sl->str);
}
ADD2LOG("----- cardctl status end -----\n");
for(pcmcia_sock = -1, sl = sl0; sl; sl = sl->next) {
if(sscanf(sl->str, " Socket %d:", &i0) == 1) {
pcmcia_sock = i0;
continue;
}
if(strstr(sl->str, " CardBus card")) {
if(pcmcia_sock >= 0 && pcmcia_sock < 8 * (int) sizeof cardbus) {
cardbus |= 1 << pcmcia_sock;
}
pcmcia_sock = -1;
continue;
}
}
free_str_list(sl0);
sl0 = read_file("| /sbin/cardctl ident 2>/dev/null", 0, 0);
ADD2LOG("----- cardctl ident -----\n");
for(sl = sl0; sl; sl = sl->next) {
ADD2LOG(" %s", sl->str);
}
ADD2LOG("----- cardctl ident end -----\n");
for(
pcmcia_sock = manf_id0 = manf_id1 = func = prod_info = -1, sl = sl0;
sl;
sl = sl->next
) {
if(sscanf(sl->str, " manfid: %i, %i", &i0, &i1) == 2) {
manf_id0 = i0;
manf_id1 = i1;
}
if(sscanf(sl->str, " function: %d", &i0) == 1) {
/*
* "multifunction", "memory", "serial", "parallel",
* "fixed disk", "video", "network", "AIMS",
* "SCSI"
*/
func = i0;
}
if(
(i0 = sscanf(
sl->str,
" product info: \"%255[^\"]\", \"%255[^\"]\", \"%255[^\"]\", \"%255[^\"]\"",
buf0, buf1, buf2, buf3
)) >= 1
) {
prod_info = i0;
}
if(sscanf(sl->str, " Socket %d:", &i0) == 1) {
i1 = 1;
}
else {
i1 = 0;
}
if(i1 || !sl->next) {
if(pcmcia_sock >= 0 && (prod_info >= 1 || manf_id0 != -1)) {
hd = add_hd_entry(hd_data, __LINE__, 0);
hd->bus.id = bus_pcmcia;
hd->slot = pcmcia_sock;
hd->hotplug_slot = pcmcia_sock + 1;
if(manf_id0 != -1 && manf_id1 != -1) {
hd->vendor.id = MAKE_ID(TAG_PCMCIA, manf_id0);
hd->device.id = MAKE_ID(TAG_PCMCIA, manf_id1);
}
if(pcmcia_sock < 8 * (int) sizeof cardbus && (cardbus & (1 << pcmcia_sock))) {
hd->hotplug = hp_cardbus;
}
else {
hd->hotplug = hp_pcmcia;
}
if(func == 6) {
hd->base_class.id = bc_network;
hd->sub_class.id = 0x80; /* other */
}
if(prod_info >= 1) add_str_list(&hd->extra_info, buf0);
if(prod_info >= 2) add_str_list(&hd->extra_info, buf1);
if(prod_info >= 3) add_str_list(&hd->extra_info, buf2);
if(prod_info >= 4) add_str_list(&hd->extra_info, buf3);
if(prod_info >= 2) {
hd->vendor.name = new_str(buf0);
hd->device.name = new_str(buf1);
}
for(sl1 = hd->extra_info; sl1 ; sl1 = sl1->next) {
if(strstr(sl1->str, "Ethernet")) hd->sub_class.id = 0; /* ethernet */
if(
!hd->revision.name &&
!sl1->next &&
(
!strncasecmp(sl1->str, "rev.", sizeof "rev." - 1) ||
(
(sl1->str[0] == 'V' || sl1->str[0] == 'v') &&
(sl1->str[1] >= '0' && sl1->str[1] <= '9')
)
)
) {
hd->revision.name = new_str(sl1->str);
}
}
}
manf_id0 = manf_id1 = func = prod_info = -1;
}
if(i1) pcmcia_sock = i0;
}
free_str_list(sl0);
}
/*
* Identify hotpluggable devices.
*/
void assign_bridges(hd_data_t *hd_data)
{
hd_t *hd, *hd1, *bridge_hd;
unsigned p_sock[8], p_socks, u = 0;
for(hd = hd_data->hd; hd; hd = hd->next) {
if((bridge_hd = hd_get_device_by_idx(hd_data, hd->attached_to))) {
if(
bridge_hd->base_class.id == bc_bridge &&
bridge_hd->sub_class.id == sc_bridge_cardbus
) {
hd->hotplug = hp_cardbus;
}
else if(
bridge_hd->base_class.id == bc_bridge &&
bridge_hd->sub_class.id == sc_bridge_pcmcia
) {
hd->hotplug = hp_pcmcia;
}
}
}
for(p_socks = 0, hd = hd_data->hd; hd; hd = hd->next) {
if(
u < sizeof p_sock / sizeof *p_sock &&
is_pcmcia_ctrl(hd_data, hd)
) {
p_sock[p_socks++] = hd->idx;
}
}
if(p_socks) {
for(hd = hd_data->hd; hd; hd = hd->next) {
if(
!hd->tag.remove &&
hd->bus.id == bus_pcmcia &&
hd->slot < p_socks &&
p_sock[hd->slot]
) {
for(u = p_sock[hd->slot], hd1 = hd_data->hd; hd1; hd1 = hd1->next) {
if(hd1->tag.remove) continue;
if(hd1->status.available == status_no) continue;
if(hd1->attached_to == u) break;
}
if(hd1) {
hd1->hotplug = hd->hotplug;
hd1->hotplug_slot = hd->hotplug_slot;
if(!hd1->extra_info) {
hd1->extra_info = hd->extra_info;
hd->extra_info = NULL;
}
hd->tag.remove = 1;
}
else {
hd->attached_to = p_sock[hd->slot];
add_sysfs_stuff(hd_data, hd);
}
p_sock[hd->slot] = 0;
}
}
remove_tagged_hd_entries(hd_data);
}
}
void add_sysfs_stuff(hd_data_t *hd_data, hd_t *hd)
{
hd_t *hd_par;
char *s = NULL, *s1;
struct sysfs_device *sf_dev;
hd_par = hd_get_device_by_idx(hd_data, hd->attached_to);
if(!hd_par || !hd_par->sysfs_id || hd->sysfs_id) return;
str_printf(&s, 0, "/sys%s/%d.0", hd_par->sysfs_id, hd->slot);
sf_dev = sysfs_open_device_path(s);
if(sf_dev) {
hd->sysfs_id = new_str(hd_sysfs_id(s));
s1 = hd_sysfs_find_driver(hd_data, hd->sysfs_id, 1);
if(s1) add_str_list(&hd->drivers, s1);
}
sysfs_close_device(sf_dev);
s = free_mem(s);
}

View File

@@ -0,0 +1 @@
void hd_scan_pcmcia(hd_data_t *hd_data);

611
src/hwinfo/src/hd/pppoe.c Normal file
View File

@@ -0,0 +1,611 @@
/*
* License: GPL
*
* Much inspired by rp-pppoe from Roaring Penguin Software Inc.
* which itself is inspired by earlier code from Luke Stras.
*/
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
#include <linux/if.h>
#include <net/ethernet.h>
#include <net/if_arp.h>
#include <netinet/in.h>
#include <netpacket/packet.h>
#include "hd.h"
#include "hd_int.h"
#include "pppoe.h"
static hd_data_t *hd_data;
/* Ethernet Frame Types */
#define ETH_PPPOE_DISCOVERY 0x8863
#define ETH_PPPOE_SESSION 0x8864
/* PPPoE Codes */
#define CODE_PADI 0x09
#define CODE_PADO 0x07
#define CODE_PADR 0x19
#define CODE_PADS 0x65
#define CODE_PADT 0xA7
/* PPPoE Tags */
#define TAG_END_OF_LIST 0x0000
#define TAG_SERVICE_NAME 0x0101
#define TAG_AC_NAME 0x0102
#define TAG_HOST_UNIQ 0x0103
#define TAG_AC_COOKIE 0x0104
#define TAG_VENDOR_SPECIFIC 0x0105
#define TAG_RELAY_SESSION_ID 0x0110
#define TAG_SERVICE_NAME_ERROR 0x0201
#define TAG_AC_SYSTEM_ERROR 0x0202
#define TAG_GENERIC_ERROR 0x0203
/* Number of Attempts */
#define MAX_ATTEMPTS 2
/* Timeout for PADO Packets */
#define PADO_TIMEOUT 3
/* A PPPoE Packet, including Ethernet headers */
typedef struct PPPoEPacketStruct {
struct ethhdr ethHdr; /* Ethernet header */
unsigned int ver:4; /* PPPoE Version (must be 1) */
unsigned int type:4; /* PPPoE Type (must be 1) */
unsigned int code:8; /* PPPoE code */
unsigned int session:16; /* PPPoE session */
unsigned int length:16; /* Payload length */
unsigned char payload[ETH_DATA_LEN]; /* A bit of room to spare */
} PPPoEPacket;
/* Header size of a PPPoE Packet */
#define PPPOE_OVERHEAD 6 /* type, code, session, length */
#define HDR_SIZE (sizeof (struct ethhdr) + PPPOE_OVERHEAD)
#define MAX_PPPOE_PAYLOAD (ETH_DATA_LEN - PPPOE_OVERHEAD)
/* PPPoE Tag */
typedef struct PPPoETagStruct {
unsigned int type:16; /* tag type */
unsigned int length:16; /* Length of payload */
unsigned char payload[ETH_DATA_LEN]; /* A LOT of room to spare */
} PPPoETag;
/* Header size of a PPPoE Tag */
#define TAG_HDR_SIZE 4
/* Function passed to parse_packet */
typedef void parse_func (uint16_t type, uint16_t len,
unsigned char* data, void* extra);
/* Keep track of the state of a connection */
typedef struct PPPoEConnectionStruct {
char* ifname; /* Interface name */
int fd; /* Raw socket for discovery frames */
int received_pado; /* Where we are in discovery */
unsigned char my_mac[ETH_ALEN]; /* My MAC address */
unsigned char peer_mac[ETH_ALEN]; /* Peer's MAC address */
hd_t *hd;
} PPPoEConnection;
/* Structure used to determine acceptable PADO packet */
typedef struct PacketCriteriaStruct {
PPPoEConnection* conn;
int acname_ok;
int servicename_ok;
int error;
} PacketCriteria;
/* True if Ethernet address is broadcast or multicast */
#define NOT_UNICAST(e) ((e[0] & 0x01) != 0)
static int
check_room (PPPoEConnection* conn, unsigned char* cursor, unsigned char* start,
uint16_t len)
{
if (cursor - start + len > MAX_PPPOE_PAYLOAD) {
ADD2LOG ("%s: Would create too-long packet\n", conn->ifname);
return 0;
}
return 1;
}
static int
parse_packet (PPPoEConnection* conn, PPPoEPacket* packet, parse_func* func,
void* extra)
{
uint16_t len = ntohs (packet->length);
unsigned char* curTag;
uint16_t tagType, tagLen;
if (packet->ver != 1) {
ADD2LOG ("%s: Invalid PPPoE version (%d)\n", conn->ifname,
(int) packet->ver);
return 0;
}
if (packet->type != 1) {
ADD2LOG ("%s: Invalid PPPoE type (%d)\n", conn->ifname,
(int) packet->type);
return 0;
}
/* Do some sanity checks on packet. */
if (len > ETH_DATA_LEN - 6) { /* 6-byte overhead for PPPoE header */
ADD2LOG ("%s: Invalid PPPoE packet length (%u)\n", conn->ifname, len);
return 0;
}
/* Step through the tags. */
curTag = packet->payload;
while (curTag - packet->payload < len) {
/* Alignment is not guaranteed, so do this by hand. */
tagType = (((uint16_t) curTag[0]) << 8) + (uint16_t) curTag[1];
tagLen = (((uint16_t) curTag[2]) << 8) + (uint16_t) curTag[3];
if (tagType == TAG_END_OF_LIST)
break;
if ((curTag - packet->payload) + tagLen + TAG_HDR_SIZE > len) {
ADD2LOG ("%s: Invalid PPPoE tag length (%u)\n", conn->ifname,
tagLen);
return 0;
}
func (tagType, tagLen, curTag + TAG_HDR_SIZE, extra);
curTag = curTag + TAG_HDR_SIZE + tagLen;
}
return 1;
}
static int
open_interfaces (int n, PPPoEConnection* conns)
{
int ret = 0, i;
for (i = 0; i < n; i++)
{
PPPoEConnection* conn = &conns[i];
conn->fd = socket (PF_PACKET, SOCK_RAW, htons (ETH_PPPOE_DISCOVERY));
if (conn->fd < 0) {
ADD2LOG ("%s: socket failed: %m\n", conn->ifname);
continue;
}
int one = 1;
if (setsockopt (conn->fd, SOL_SOCKET, SO_BROADCAST, &one,
sizeof (one)) < 0) {
ADD2LOG ("%s: setsockopt failed: %m\n", conn->ifname);
goto error;
}
/* Fill in hardware address */
struct ifreq ifr;
struct sockaddr_ll sa;
memset (&sa, 0, sizeof (sa));
strncpy (ifr.ifr_name, conn->ifname, sizeof (ifr.ifr_name));
if (ioctl (conn->fd, SIOCGIFHWADDR, &ifr) < 0) {
ADD2LOG ("%s: ioctl (SIOCGIFHWADDR) failed: %m\n", conn->ifname);
goto error;
}
memcpy (conn->my_mac, ifr.ifr_hwaddr.sa_data, ETH_ALEN);
if (ifr.ifr_hwaddr.sa_family != ARPHRD_ETHER) {
ADD2LOG ("%s: Interface is not ethernet\n", conn->ifname);
goto error;
}
if (NOT_UNICAST (conn->my_mac)) {
ADD2LOG ("%s: Interface has broadcast/multicast MAC address?\n",
conn->ifname);
goto error;
}
/* Sanity check on MTU */
strncpy (ifr.ifr_name, conn->ifname, sizeof (ifr.ifr_name));
if (ioctl (conn->fd, SIOCGIFMTU, &ifr) < 0) {
ADD2LOG ("%s: ioctl (SIOCGIFMTU) failed: %m\n", conn->ifname);
goto error;
}
if (ifr.ifr_mtu < ETH_DATA_LEN) {
ADD2LOG ("%s: Interface has to low MTU\n", conn->ifname);
goto error;
}
/* Get interface index */
sa.sll_family = AF_PACKET;
sa.sll_protocol = htons (ETH_PPPOE_DISCOVERY);
strncpy (ifr.ifr_name, conn->ifname, sizeof (ifr.ifr_name));
if (ioctl (conn->fd, SIOCGIFINDEX, &ifr) < 0) {
ADD2LOG ("%s: ioctl (SIOCFIGINDEX) failed: Could not get interface "
"index\n", conn->ifname);
goto error;
}
sa.sll_ifindex = ifr.ifr_ifindex;
/* We're only interested in packets on specified interface */
if (bind (conn->fd, (struct sockaddr*) &sa, sizeof (sa)) < 0) {
ADD2LOG ("%s: bind failed: %m\n", conn->ifname);
goto error;
}
ret = 1;
continue;
error:
close (conn->fd);
conn->fd = -1;
}
return ret;
}
static void
close_intefaces (int n, PPPoEConnection* conns)
{
int i;
for (i = 0; i < n; i++)
{
PPPoEConnection* conn = &conns[i];
if (conn->fd != -1) {
close (conn->fd);
conn->fd = -1;
}
}
}
static int
send_packet (int fd, PPPoEPacket* pkt, size_t size)
{
if (send (fd, pkt, size, 0) < 0) {
ADD2LOG ("send failed: %m\n");
return 0;
}
return 1;
}
static int
receive_packet (int fd, PPPoEPacket* pkt, size_t* size)
{
int r = recv (fd, pkt, sizeof (PPPoEPacket), 0);
if (r < 0) {
ADD2LOG ("recv failed: %m\n");
return 0;
}
*size = r;
return 1;
}
static void
parse_hostuniq (uint16_t type, uint16_t len, unsigned char* data, void* extra)
{
if (type == TAG_HOST_UNIQ && len == sizeof (pid_t)) {
pid_t tmp;
memcpy (&tmp, data, len);
if (tmp == getpid ()) {
int* val = (int*) extra;
*val = 1;
}
}
}
static int
packet_for_me (PPPoEConnection* conn, PPPoEPacket* packet)
{
/* If packet is not directed to our MAC address, forget it. */
if (memcmp (packet->ethHdr.h_dest, conn->my_mac, ETH_ALEN))
return 0;
/* Check for HostUniq tag. */
int for_me = 0;
parse_packet (conn, packet, parse_hostuniq, &for_me);
return for_me;
}
static void
parse_pado_tags (uint16_t type, uint16_t len, unsigned char* data, void* extra)
{
PacketCriteria* pc = (PacketCriteria*) extra;
PPPoEConnection *conn = pc->conn;
switch (type) {
case TAG_AC_NAME:
pc->acname_ok = 1;
ADD2LOG ("%s: Service-Name is: %.*s\n", conn->ifname, (int) len,
data);
break;
case TAG_SERVICE_NAME:
pc->servicename_ok = len == 0;
break;
case TAG_SERVICE_NAME_ERROR:
ADD2LOG ("%s: Service-Name-Error: %.*s\n", conn->ifname, (int) len,
data);
pc->error = 1;
break;
case TAG_AC_SYSTEM_ERROR:
ADD2LOG ("%s: System-Error: %.*s\n", conn->ifname, (int) len, data);
pc->error = 1;
break;
case TAG_GENERIC_ERROR:
ADD2LOG ("%s: Generic-Error: %.*s\n", conn->ifname, (int) len, data);
pc->error = 1;
break;
}
}
static int
send_padi (int n, PPPoEConnection* conns)
{
int ret = 0, i;
for (i = 0; i < n; i++)
{
PPPoEConnection* conn = &conns[i];
if (conn->fd == -1 || conn->received_pado)
continue;
PPPoEPacket packet;
unsigned char* cursor = packet.payload;
PPPoETag* svc = (PPPoETag*) (&packet.payload);
uint16_t namelen = 0;
uint16_t plen;
namelen = 0;
plen = TAG_HDR_SIZE + namelen;
if (!check_room (conn, cursor, packet.payload, TAG_HDR_SIZE))
continue;
/* Set destination to Ethernet broadcast address */
memset (packet.ethHdr.h_dest, 0xFF, ETH_ALEN);
memcpy (packet.ethHdr.h_source, conn->my_mac, ETH_ALEN);
packet.ethHdr.h_proto = htons (ETH_PPPOE_DISCOVERY);
packet.ver = 1;
packet.type = 1;
packet.code = CODE_PADI;
packet.session = 0;
svc->type = TAG_SERVICE_NAME;
svc->length = htons (0);
if (!check_room (conn, cursor, packet.payload, namelen + TAG_HDR_SIZE))
continue;
cursor += namelen + TAG_HDR_SIZE;
PPPoETag hostUniq;
pid_t pid = getpid ();
hostUniq.type = htons (TAG_HOST_UNIQ);
hostUniq.length = htons (sizeof (pid));
memcpy (hostUniq.payload, &pid, sizeof (pid));
if (!check_room (conn, cursor, packet.payload, sizeof (pid) + TAG_HDR_SIZE))
continue;
memcpy (cursor, &hostUniq, sizeof (pid) + TAG_HDR_SIZE);
cursor += sizeof (pid) + TAG_HDR_SIZE;
plen += sizeof (pid) + TAG_HDR_SIZE;
packet.length = htons (plen);
ADD2LOG ("%s: Sending PADI packet\n", conn->ifname);
if (send_packet (conn->fd, &packet, (int) (plen + HDR_SIZE)))
ret = 1;
}
return ret;
}
static int
wait_for_pado (int n, PPPoEConnection* conns)
{
int r, i, all;
size_t len;
fd_set readable;
PPPoEPacket packet;
PacketCriteria pc;
struct timeval tv;
tv.tv_sec = PADO_TIMEOUT;
tv.tv_usec = 0;
while (1)
{
FD_ZERO (&readable);
for (i = 0; i < n; i++)
if (conns[i].fd != -1)
FD_SET (conns[i].fd, &readable);
do {
r = select (FD_SETSIZE, &readable, NULL, NULL, &tv);
} while (r == -1 && errno == EINTR);
if (r < 0) {
ADD2LOG ("select: %m\n");
return 0;
}
if (r == 0) {
ADD2LOG ("Timeout waiting for PADO packets\n");
return 0;
}
for (i = 0; i < n; i++)
{
PPPoEConnection* conn = &conns[i];
if (conn->fd == -1 || !FD_ISSET (conn->fd, &readable))
continue;
pc.conn = conn;
pc.acname_ok = 0;
pc.servicename_ok = 0;
pc.error = 0;
/* Get the packet */
if (!receive_packet (conn->fd, &packet, &len))
continue;
/* Check length */
if (ntohs (packet.length) + HDR_SIZE > len) {
ADD2LOG ("%s: Bogus PPPoE length field (%u)\n", conn->ifname,
(unsigned int) ntohs (packet.length));
continue;
}
/* If it's not for us, loop again */
if (!packet_for_me (conn, &packet))
continue;
if (packet.code != CODE_PADO)
continue;
if (NOT_UNICAST (packet.ethHdr.h_source)) {
ADD2LOG ("%s: Ignoring PADO packet from non-unicast MAC "
"address\n", conn->ifname);
continue;
}
parse_packet (conn, &packet, parse_pado_tags, &pc);
if (!pc.acname_ok) {
ADD2LOG ("%s: Wrong or missing AC-Name tag\n", conn->ifname);
continue;
}
if (!pc.servicename_ok) {
ADD2LOG ("%s: Wrong or missing Service-Name tag\n",
conn->ifname);
continue;
}
if (pc.error) {
ADD2LOG ("%s: Ignoring PADO packet with some Error tag\n",
conn->ifname);
continue;
}
memcpy (conn->peer_mac, packet.ethHdr.h_source, ETH_ALEN);
ADD2LOG ("%s: Received correct PADO packet\n", conn->ifname);
conn->received_pado = 1;
}
all = 1;
for (i = 0; i < n; i++)
if (conns[i].fd != -1 && !conns[i].received_pado)
all = 0;
if (all)
return 1;
}
}
static void
discovery (int n, PPPoEConnection* conns)
{
int a;
if (open_interfaces (n, conns))
{
for (a = 0; a < MAX_ATTEMPTS; a++)
{
ADD2LOG ("Attempt number %d\n", a + 1);
if (!send_padi (n, conns))
break;
if (wait_for_pado (n, conns))
break;
}
}
close_intefaces (n, conns);
}
void hd_scan_pppoe(hd_data_t *hd_data2)
{
hd_t *hd;
int cnt, interfaces;
PPPoEConnection *conn;
hd_data = hd_data2;
if(!hd_probe_feature(hd_data, pr_pppoe)) return;
hd_data->module = mod_pppoe;
PROGRESS(1, 0, "looking for pppoe");
for(interfaces = 0, hd = hd_data->hd; hd; hd = hd->next) {
if(
hd->base_class.id == bc_network_interface &&
hd->sub_class.id == sc_nif_ethernet &&
hd->unix_dev_name
) {
interfaces++;
}
}
if(!interfaces) return;
conn = new_mem(interfaces * sizeof *conn);
for(cnt = 0, hd = hd_data->hd; hd && cnt < interfaces; hd = hd->next) {
if(
hd->base_class.id == bc_network_interface &&
hd->sub_class.id == sc_nif_ethernet &&
hd->unix_dev_name
) {
conn[cnt].hd = hd;
conn[cnt].fd = -1;
conn[cnt].ifname = hd->unix_dev_name;
cnt++;
}
}
PROGRESS(2, 0, "discovery");
discovery(interfaces, conn);
for(cnt = 0; cnt < interfaces; cnt++) {
conn[cnt].hd->is.pppoe = 0;
if(conn[cnt].received_pado) {
conn[cnt].hd->is.pppoe = 1;
ADD2LOG(
"pppoe %s: my mac %02x:%02x:%02x:%02x:%02x:%02x, "
"peer mac %02x:%02x:%02x:%02x:%02x:%02x\n",
conn[cnt].ifname,
conn[cnt].my_mac[0], conn[cnt].my_mac[1], conn[cnt].my_mac[2],
conn[cnt].my_mac[3], conn[cnt].my_mac[4], conn[cnt].my_mac[5],
conn[cnt].peer_mac[0], conn[cnt].peer_mac[1], conn[cnt].peer_mac[2],
conn[cnt].peer_mac[3], conn[cnt].peer_mac[4], conn[cnt].peer_mac[5]
);
}
}
}

View File

@@ -0,0 +1 @@
void hd_scan_pppoe(hd_data_t *hd_data);

694
src/hwinfo/src/hd/prom.c Normal file
View File

@@ -0,0 +1,694 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <dirent.h>
#include <sys/stat.h>
#include "hd.h"
#include "hd_int.h"
#include "hddb.h"
#include "prom.h"
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
* prom info
*
* Note: make sure that hd_scan_sysfs_pci() has been run!
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
*/
#if defined(__PPC__)
static devtree_t *add_devtree_entry(devtree_t **devtree, devtree_t *new);
static devtree_t *new_devtree_entry(devtree_t *parent);
static void read_str(char *path, char *name, char **str);
static void read_mem(char *path, char *name, unsigned char **mem, unsigned len);
static void read_int(char *path, char *name, int *val);
static void read_devtree(hd_data_t *hd_data);
static void add_pci_prom_devices(hd_data_t *hd_data, hd_t *hd_parent, devtree_t *parent);
static void add_legacy_prom_devices(hd_data_t *hd_data, devtree_t *dt);
static int add_prom_display(hd_data_t *hd_data, devtree_t *dt);
static int add_prom_vscsi(hd_data_t *hd_data, devtree_t *dt);
static int add_prom_veth(hd_data_t *hd_data, devtree_t *dt);
static void add_devices(hd_data_t *hd_data);
static void dump_devtree_data(hd_data_t *hd_data);
static unsigned veth_cnt, vscsi_cnt;
int detect_smp_prom(hd_data_t *hd_data)
{
unsigned cpus;
devtree_t *devtree;
if(!(devtree = hd_data->devtree)) return -1; /* hd_scan_prom() not called */
for(cpus = 0; devtree; devtree = devtree->next) {
if(devtree->device_type && !strcmp(devtree->device_type, "cpu")) cpus++;
}
return cpus > 1 ? cpus : 0;
}
void hd_scan_prom(hd_data_t *hd_data)
{
hd_t *hd;
unsigned char buf[16];
FILE *f;
prom_info_t *pt;
if(!hd_probe_feature(hd_data, pr_prom)) return;
hd_data->module = mod_prom;
/* some clean-up */
remove_hd_entries(hd_data);
hd_data->devtree = free_devtree(hd_data);
veth_cnt = vscsi_cnt = 0;
PROGRESS(1, 0, "devtree");
read_devtree(hd_data);
if(hd_data->debug) dump_devtree_data(hd_data);
add_devices(hd_data);
PROGRESS(2, 0, "color");
hd = add_hd_entry(hd_data, __LINE__, 0);
hd->base_class.id = bc_internal;
hd->sub_class.id = sc_int_prom;
hd->detail = new_mem(sizeof *hd->detail);
hd->detail->type = hd_detail_prom;
hd->detail->prom.data = pt = new_mem(sizeof *pt);
if((f = fopen(PROC_PROM "/color-code", "r"))) {
if(fread(buf, 1, 2, f) == 2) {
pt->has_color = 1;
pt->color = buf[1];
hd_data->color_code = pt->color | 0x10000;
ADD2LOG("color-code: 0x%04x\n", (buf[0] << 8) + buf[1]);
}
fclose(f);
}
}
/* store a device tree entry */
devtree_t *add_devtree_entry(devtree_t **devtree, devtree_t *new)
{
while(*devtree) devtree = &(*devtree)->next;
return *devtree = new;
}
/* create a new device tree entry */
devtree_t *new_devtree_entry(devtree_t *parent)
{
static unsigned idx = 0;
devtree_t *devtree = new_mem(sizeof *devtree);
if(!parent) idx = 0;
devtree->idx = ++idx;
devtree->parent = parent;
devtree->interrupt = devtree->class_code =
devtree->device_id = devtree->vendor_id =
devtree->subdevice_id = devtree->subvendor_id =
devtree->revision_id = -1;
return devtree;
}
void read_str(char *path, char *name, char **str)
{
char *s = NULL;
str_list_t *sl;
str_printf(&s, 0, "%s/%s", path, name);
if((sl = read_file(s, 0, 1))) {
*str = sl->str;
sl->str = NULL;
sl = free_str_list(sl);
}
free_mem(s);
}
void read_mem(char *path, char *name, unsigned char **mem, unsigned len)
{
FILE *f;
char *s = NULL;
unsigned char *m = new_mem(len);
str_printf(&s, 0, "%s/%s", path, name);
if((f = fopen(s, "r"))) {
if(fread(m, len, 1, f) == 1) {
*mem = m;
m = NULL;
}
fclose(f);
}
free_mem(s);
free_mem(m);
}
void read_int(char *path, char *name, int *val)
{
unsigned char *p = NULL;
read_mem(path, name, &p, sizeof (int));
if(p) memcpy(val, p, sizeof (int));
free_mem(p);
}
void read_devtree_entry(hd_data_t *hd_data, devtree_t *parent, char *dirname)
{
DIR *dir;
struct dirent *de;
struct stat sbuf;
char *path, *s;
devtree_t *devtree, *dt2;
devtree = add_devtree_entry(&hd_data->devtree, new_devtree_entry(parent));
devtree->filename = new_str(dirname);
str_printf(&devtree->path, 0, "%s%s%s",
parent ? parent->path : "", parent && *parent->path ? "/" : "", dirname
);
path = 0;
str_printf(&path, 0, PROC_PROM "/%s", devtree->path);
if((dir = opendir(path))) {
while((de = readdir(dir))) {
if(!strcmp(de->d_name, ".") || !strcmp(de->d_name, "..")) continue;
s = NULL;
str_printf(&s, 0, "%s/%s", path, de->d_name);
if(!lstat(s, &sbuf)) {
if(S_ISDIR(sbuf.st_mode)) {
/* prom entries don't always have unique names, unfortunately... */
for(dt2 = hd_data->devtree; dt2; dt2 = dt2->next) {
if(
dt2->parent == devtree &&
!strcmp(dt2->filename, de->d_name)
) break;
}
if(!dt2) read_devtree_entry(hd_data, devtree, de->d_name);
}
}
s = free_mem(s);
}
closedir(dir);
}
read_str(path, "name", &devtree->name);
read_str(path, "model", &devtree->model);
read_str(path, "device_type", &devtree->device_type);
read_str(path, "compatible", &devtree->compatible);
read_int(path, "interrupts", &devtree->interrupt);
read_int(path, "AAPL,interrupts", &devtree->interrupt);
read_int(path, "class-code", &devtree->class_code);
read_int(path, "vendor-id", &devtree->vendor_id);
read_int(path, "device-id", &devtree->device_id);
read_int(path, "subsystem-vendor-id", &devtree->subvendor_id);
read_int(path, "subsystem-id", &devtree->subdevice_id);
read_int(path, "revision-id", &devtree->revision_id);
read_mem(path, "EDID", &devtree->edid, 0x80);
if(!devtree->edid) read_mem(path, "DFP,EDID", &devtree->edid, 0x80);
if(
devtree->class_code != -1 && devtree->vendor_id != -1 &&
devtree->device_id != -1
) {
devtree->pci = 1;
}
path = free_mem(path);
}
void read_devtree(hd_data_t *hd_data)
{
read_devtree_entry(hd_data, NULL, "");
}
void add_pci_prom_devices(hd_data_t *hd_data, hd_t *hd_parent, devtree_t *parent)
{
hd_t *hd;
hd_res_t *res;
devtree_t *dt, *dt2;
int irq, floppy_ctrl_idx;
unsigned sound_ok = 0, net_ok = 0, scsi_ok = 0;
unsigned id;
char *s;
for(dt = hd_data->devtree; dt; dt = dt->next) {
if(
dt->parent == parent ||
(
/* special magic to reach some sound chips */
dt->parent &&
dt->parent->parent == parent &&
!dt->parent->pci
)
) {
if(
dt->device_type &&
(!strcmp(dt->device_type, "block") || !strcmp(dt->device_type, "swim3"))
) {
/* block devices */
s = dt->compatible ? dt->compatible : dt->name;
id = 0;
if(s) {
if(strstr(s, "swim3")) {
id = MAKE_ID(TAG_SPECIAL, 0x0040);
}
}
if(id) {
hd = add_hd_entry(hd_data, __LINE__, 0);
hd->bus.id = bus_none;
hd->base_class.id = bc_storage;
hd->sub_class.id = sc_sto_floppy;
hd->vendor.id = MAKE_ID(TAG_SPECIAL, 0x0401);
hd->device.id = id;
hd->attached_to = hd_parent->idx;
hd->rom_id = new_str(dt->path);
if(dt->interrupt) {
res = add_res_entry(&hd->res, new_mem(sizeof *res));
res->irq.type = res_irq;
res->irq.enabled = 1;
res->irq.base = dt->interrupt;
}
floppy_ctrl_idx = hd->idx;
hd = add_hd_entry(hd_data, __LINE__, 0);
hd->base_class.id = bc_storage_device;
hd->sub_class.id = sc_sdev_floppy;
hd->bus.id = bus_floppy;
hd->unix_dev_name = new_str("/dev/fd0");
res = add_res_entry(&hd->res, new_mem(sizeof *res));
res->size.type = res_size;
res->size.val1 = str2float("3.5", 2);
res->size.unit = size_unit_cinch;
res = add_res_entry(&hd->res, new_mem(sizeof *res));
res->size.type = res_size;
res->size.val1 = 2880;
res->size.val2 = 0x200;
res->size.unit = size_unit_sectors;
hd->attached_to = floppy_ctrl_idx;
}
}
if(
!scsi_ok &&
dt->device_type &&
!strcmp(dt->device_type, "scsi")
) {
/* scsi */
scsi_ok = 1; /* max. 1 controller */
s = dt->compatible ? dt->compatible : dt->name;
id = 0;
if(s) {
if(strstr(s, "mesh")) { /* mesh || chrp,mesh0 */
id = MAKE_ID(TAG_SPECIAL, 0x0030);
}
else if(!strcmp(s, "53c94")) {
id = MAKE_ID(TAG_SPECIAL, 0x0031);
}
}
if(id) {
hd = add_hd_entry(hd_data, __LINE__, 0);
hd->bus.id = bus_none;
hd->base_class.id = bc_storage;
hd->sub_class.id = sc_sto_scsi;
hd->vendor.id = MAKE_ID(TAG_SPECIAL, 0x0401);
hd->device.id = id;
hd->attached_to = hd_parent->idx;
hd->rom_id = new_str(dt->path);
if(dt->interrupt) {
res = add_res_entry(&hd->res, new_mem(sizeof *res));
res->irq.type = res_irq;
res->irq.enabled = 1;
res->irq.base = dt->interrupt;
}
}
}
if(
!net_ok &&
dt->device_type &&
!strcmp(dt->device_type, "network")
) {
/* network */
net_ok = 1; /* max. 1 controller */
s = dt->compatible ? dt->compatible : dt->name;
id = 0;
if(s) {
if(!strcmp(s, "mace")) {
id = MAKE_ID(TAG_SPECIAL, 0x0020);
}
else if(!strcmp(s, "bmac")) {
id = MAKE_ID(TAG_SPECIAL, 0x0021);
}
else if(!strcmp(s, "bmac+")) {
id = MAKE_ID(TAG_SPECIAL, 0x0022);
}
}
if(id) {
hd = add_hd_entry(hd_data, __LINE__, 0);
hd->bus.id = bus_none;
hd->base_class.id = bc_network;
hd->sub_class.id = 0; /* ethernet */
hd->vendor.id = MAKE_ID(TAG_SPECIAL, 0x0401);
hd->device.id = id;
hd->attached_to = hd_parent->idx;
hd->rom_id = new_str(dt->path);
if(dt->interrupt) {
res = add_res_entry(&hd->res, new_mem(sizeof *res));
res->irq.type = res_irq;
res->irq.enabled = 1;
res->irq.base = dt->interrupt;
}
}
}
if(
!sound_ok &&
dt->device_type &&
strstr(dt->device_type, "sound") == dt->device_type
) {
/* sound */
sound_ok = 1; /* max 1 controller */
for(dt2 = dt; dt2; dt2 = dt2->next) {
if(
(
dt2 == dt ||
(dt2->parent && dt2->parent == dt)
) &&
(
!strcmp(dt2->device_type, "sound") ||
!strcmp(dt2->device_type, "soundchip")
)
) break;
}
if(!dt2) dt2 = dt;
hd = add_hd_entry(hd_data, __LINE__, 0);
hd->bus.id = bus_none;
hd->base_class.id = bc_multimedia;
hd->sub_class.id = sc_multi_audio;
hd->attached_to = hd_parent->idx;
hd->rom_id = new_str(dt2->path);
irq = dt2->interrupt;
if(irq <= 1 && dt2->parent && !dt2->parent->pci) {
irq = dt2->parent->interrupt;
}
if(irq > 1) {
res = add_res_entry(&hd->res, new_mem(sizeof *res));
res->irq.type = res_irq;
res->irq.enabled = 1;
res->irq.base = irq;
}
hd->vendor.id = MAKE_ID(TAG_SPECIAL, 0x401); /* Apple */
hd->device.id = MAKE_ID(TAG_SPECIAL, 0x0010);
if(dt2->compatible) {
if(!strcmp(dt2->compatible, "screamer")) {
hd->device.id = MAKE_ID(TAG_SPECIAL, 0x0011);
}
else if(!strcmp(dt2->compatible, "burgundy")) {
hd->device.id = MAKE_ID(TAG_SPECIAL, 0x0012);
}
else if(!strcmp(dt2->compatible, "daca")) {
hd->device.id = MAKE_ID(TAG_SPECIAL, 0x0013);
}
else if(!strcmp(dt2->compatible, "CRUS,CS4236B")) {
hd->vendor.id = MAKE_ID(TAG_SPECIAL, 0x402); /* IBM */
hd->device.id = MAKE_ID(TAG_SPECIAL, 0x0014);
}
}
}
}
}
}
void add_legacy_prom_devices(hd_data_t *hd_data, devtree_t *dt)
{
if(dt->pci) return;
if(add_prom_display(hd_data, dt)) return;
if(add_prom_vscsi(hd_data, dt)) return;
if(add_prom_veth(hd_data, dt)) return;
}
int add_prom_display(hd_data_t *hd_data, devtree_t *dt)
{
hd_t *hd;
hd_res_t *res;
unsigned id;
if(
dt->device_type &&
!strcmp(dt->device_type, "display")
) {
/* display devices */
id = 0;
if(dt->name) {
if(!strcmp(dt->name, "valkyrie")) {
id = MAKE_ID(TAG_SPECIAL, 0x3000);
}
else if(!strcmp(dt->name, "platinum")) {
id = MAKE_ID(TAG_SPECIAL, 0x3001);
}
}
if(id) {
hd = add_hd_entry(hd_data, __LINE__, 0);
hd->bus.id = bus_none;
hd->base_class.id = bc_display;
hd->sub_class.id = sc_dis_other;
hd->vendor.id = MAKE_ID(TAG_SPECIAL, 0x0401);
hd->device.id = id;
hd->rom_id = new_str(dt->path);
if(dt->interrupt) {
res = add_res_entry(&hd->res, new_mem(sizeof *res));
res->irq.type = res_irq;
res->irq.enabled = 1;
res->irq.base = dt->interrupt;
}
return 1;
}
}
return 0;
}
int add_prom_vscsi(hd_data_t *hd_data, devtree_t *dt)
{
hd_t *hd;
char *s, *id;
if(
dt->path &&
dt->device_type &&
!strcmp(dt->device_type, "vscsi")
) {
/* vscsi storage */
if(
(s = strstr(dt->path, "v-scsi@")) &&
*(id = s + sizeof "v-scsi@" - 1)
) {
hd = add_hd_entry(hd_data, __LINE__, 0);
hd->bus.id = bus_none;
hd->base_class.id = bc_storage;
hd->sub_class.id = sc_sto_scsi;
hd->slot = veth_cnt++;
hd->vendor.id = MAKE_ID(TAG_SPECIAL, 0x6001);
hd->device.id = MAKE_ID(TAG_SPECIAL, 0x1001);
str_printf(&hd->device.name, 0, "Virtual SCSI %d", hd->slot);
hd->rom_id = new_str(dt->path);
str_printf(&hd->sysfs_id, 0, "/devices/vio/%s", id);
return 1;
}
}
return 0;
}
int add_prom_veth(hd_data_t *hd_data, devtree_t *dt)
{
hd_t *hd;
char *s, *id;
if(
dt->path &&
dt->device_type &&
dt->compatible &&
!strcmp(dt->device_type, "network") &&
!strcmp(dt->compatible, "IBM,l-lan")
) {
/* veth network */
if(
(s = strstr(dt->path, "l-lan@")) &&
*(id = s + sizeof "l-lan@" - 1)
) {
hd = add_hd_entry(hd_data, __LINE__, 0);
hd->bus.id = bus_none;
hd->base_class.id = bc_network;
hd->sub_class.id = 0x00;
hd->slot = veth_cnt++;
hd->vendor.id = MAKE_ID(TAG_SPECIAL, 0x6001);
hd->device.id = MAKE_ID(TAG_SPECIAL, 0x1002);
str_printf(&hd->device.name, 0, "Virtual Ethernet card %d", hd->slot);
hd->rom_id = new_str(dt->path);
str_printf(&hd->sysfs_id, 0, "/devices/vio/%s", id);
return 1;
}
}
return 0;
}
void add_devices(hd_data_t *hd_data)
{
hd_t *hd;
devtree_t *dt;
#if 0
hd_res_t *res;
unsigned pci_slot = 0, u;
#endif
/* remove old assignments */
for(hd = hd_data->hd; hd; hd = hd->next) {
if(ID_TAG(hd->device.id) == TAG_PCI && ID_TAG(hd->vendor.id) == TAG_PCI) {
hd->rom_id = free_mem(hd->rom_id);
hd->detail = free_hd_detail(hd->detail);
}
}
for(dt = hd_data->devtree; dt; dt = dt->next) {
if(dt->pci) {
for(hd = hd_data->hd; hd; hd = hd->next) {
if(
/* do *not* compare class ids */
/* It would be better to check the slot numbers instead but
* as they are not stored within /proc/device-tree in a consistent
* way, we can't do that.
*/
!hd->rom_id &&
ID_TAG(hd->device.id) == TAG_PCI &&
ID_TAG(hd->vendor.id) == TAG_PCI &&
ID_VALUE(hd->device.id) == dt->device_id &&
ID_VALUE(hd->vendor.id) == dt->vendor_id &&
(dt->subvendor_id == -1 || ID_VALUE(hd->sub_vendor.id) == dt->subvendor_id) &&
(dt->subdevice_id == -1 || ID_VALUE(hd->sub_device.id) == dt->subdevice_id) &&
hd->revision.id == dt->revision_id
) break;
}
if(hd) {
hd->rom_id = new_str(dt->path);
hd->detail = new_mem(sizeof *hd->detail);
hd->detail->type = hd_detail_devtree;
hd->detail->devtree.data = dt;
add_pci_prom_devices(hd_data, hd, dt);
}
}
else {
add_legacy_prom_devices(hd_data, dt);
}
}
}
void dump_devtree_data(hd_data_t *hd_data)
{
unsigned u;
devtree_t *devtree;
devtree = hd_data->devtree;
if(!devtree) return;
ADD2LOG("----- /proc device tree -----\n");
for(; devtree; devtree = devtree->next) {
u = devtree->parent ? devtree->parent->idx : 0;
ADD2LOG(" %02u @%02u %s", devtree->idx, u, devtree->path);
if(devtree->pci) ADD2LOG(" [pci]");
ADD2LOG("\n");
ADD2LOG(
" name \"%s\", model \"%s\", dtype \"%s\", compat \"%s\"\n",
devtree->name ? devtree->name : "",
devtree->model ? devtree->model : "",
devtree->device_type ? devtree->device_type : "",
devtree->compatible ? devtree->compatible : ""
);
if(
devtree->class_code != -1 || devtree->vendor_id != -1 ||
devtree->device_id != -1 || devtree->revision_id != -1 ||
devtree->subdevice_id != -1 || devtree->subvendor_id != -1 ||
devtree->interrupt != -1
) {
ADD2LOG(" ");
if(devtree->class_code != -1) ADD2LOG(" class 0x%06x", devtree->class_code);
if(devtree->vendor_id != -1) ADD2LOG(" vend 0x%04x", devtree->vendor_id);
if(devtree->device_id != -1) ADD2LOG(" dev 0x%04x", devtree->device_id);
if(devtree->subvendor_id != -1) ADD2LOG(" svend 0x%04x", devtree->subvendor_id);
if(devtree->subdevice_id != -1) ADD2LOG(" sdev 0x%04x", devtree->subdevice_id);
if(devtree->revision_id != -1) ADD2LOG(" rev 0x%02x", devtree->revision_id);
if(devtree->interrupt != -1) ADD2LOG(" irq %d", devtree->interrupt);
ADD2LOG("\n");
}
if(devtree->edid) {
ADD2LOG(" EDID record:\n");
for(u = 0; u < 0x80; u += 0x10) {
ADD2LOG(" %02x ", u);
hexdump(&hd_data->log, 1, 0x10, devtree->edid + u);
ADD2LOG("\n");
}
}
if(devtree->next) ADD2LOG("\n");
}
ADD2LOG("----- /proc device tree end -----\n");
}
#endif /* defined(__PPC__) */

1
src/hwinfo/src/hd/prom.h Normal file
View File

@@ -0,0 +1 @@
void hd_scan_prom(hd_data_t *hd_data);

246
src/hwinfo/src/hd/s390.c Normal file
View File

@@ -0,0 +1,246 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "hd.h"
#include "hd_int.h"
#include "hddb.h"
#include "s390.h"
#if defined(__s390__) || defined(__s390x__)
#include <sysfs/libsysfs.h>
#include <sysfs/dlist.h>
#define BUSNAME "ccw"
#define BUSNAME_GROUP "ccwgroup"
#define BUSNAME_IUCV "iucv"
static void hd_scan_s390_ex(hd_data_t *hd_data, int disks_only)
{
hd_t* hd;
hd_res_t* res;
struct sysfs_bus *bus;
struct sysfs_bus *bus_group;
struct sysfs_device *curdev = NULL;
struct dlist *attributes = NULL;
struct sysfs_attribute *curattr = NULL;
struct dlist *devlist = NULL;
struct dlist *devlist_group = NULL;
int virtual_machine=0;
unsigned int devtype=0,devmod=0,cutype=0,cumod=0;
/* list of each channel's cutype, used for finding multichannel devices */
int cutypes[1<<16]={0};
int i;
hd_data->module=mod_s390;
remove_hd_entries(hd_data);
bus=sysfs_open_bus(BUSNAME);
bus_group=sysfs_open_bus(BUSNAME_GROUP);
if (!bus)
{
ADD2LOG("unable to open" BUSNAME "bus");
return;
}
devlist=sysfs_get_bus_devices(bus);
if(bus_group) devlist_group=sysfs_get_bus_devices(bus_group);
if(!devlist)
{
ADD2LOG("unable to get devices on bus " BUSNAME);
return;
}
/* build cutypes list */
dlist_for_each_data(devlist, curdev, struct sysfs_device)
{
int channel=strtol(rindex(curdev->bus_id,'.')+1,NULL,16);
attributes = sysfs_get_device_attributes(curdev);
dlist_for_each_data(attributes,curattr,struct sysfs_attribute)
{
if(strcmp("cutype",curattr->name)==0)
cutype=strtol(curattr->value,NULL,16);
}
cutypes[channel]=cutype;
}
/* check for each channel if it must be skipped and identify virtual reader/punch */
for(i=0;i<(1<<16);i++)
{
if(cutypes[i]==0x3088) /* It seems that QDIO devices only appear once */
cutypes[i+1]*=-1; /* negative cutype -> skip */
if(cutypes[i]==0x2540)
{
virtual_machine=1; /* we are running in VM */
cutypes[i]=-2; /* reader */
cutypes[i+1]=-3; /* punch */
}
}
/* identify grouped channels */
if(devlist_group) dlist_for_each_data(devlist_group, curdev, struct sysfs_device)
{
struct sysfs_directory* d;
struct dlist* dl;
struct sysfs_link* cl;
//printf("ccwg %s\n",curdev->path);
d=sysfs_open_directory(curdev->path);
dl=sysfs_get_dir_links(d);
dlist_for_each_data(dl,cl,struct sysfs_link) /* iterate over this channel group */
{
if(!rindex(cl->target,'.')) continue;
int channel=strtol(rindex(cl->target,'.')+1,NULL,16);
//printf("channel %x name %s target %s\n",channel,cl->name,cl->target);
if(strncmp("cdev",cl->name,4)==0)
{
if(cl->name[4]=='0') /* first channel in group gets an entry */
{
if(cutypes[channel]<0) cutypes[channel]*=-1; /* make sure its positive */
}
else /* other channels in group are skipped */
if(cutypes[channel]>0) cutypes[channel]*=-1; /* make sure its negative */
}
}
}
dlist_for_each_data(devlist, curdev, struct sysfs_device)
{
int readonly=0;
res=new_mem(sizeof *res);
attributes = sysfs_get_device_attributes(curdev);
dlist_for_each_data(attributes,curattr, struct sysfs_attribute)
{
if (strcmp("online",curattr->name)==0)
res->io.enabled=atoi(curattr->value);
else if (strcmp("cutype",curattr->name)==0)
{
cutype=strtol(curattr->value,NULL,16);
cumod=strtol(index(curattr->value,'/')+1,NULL,16);
} else if (strcmp("devtype",curattr->name)==0)
{
devtype=strtol(curattr->value,NULL,16);
devmod=strtol(index(curattr->value,'/')+1,NULL,16);
} else if (strcmp("readonly",curattr->name)==0)
{
readonly=atoi(curattr->value);
}
}
res->io.type=res_io;
res->io.access=readonly?acc_ro:acc_rw;
res->io.base=strtol(rindex(curdev->bus_id,'.')+1,NULL,16);
/* Skip additional channels for multi-channel devices */
if(cutypes[res->io.base] < -3)
continue;
if(disks_only && cutype!=0x3990 && cutype!=0x2105 && cutype!=0x3880 && cutype!=0x9343 && cutype!=0x6310 &&
(cutype != 0x1731 || devtype != 0x1732 || cumod != 3))
continue;
res->io.range=1;
switch (cutype)
{
/* three channels */
case 0x1731: /* QDIO (QETH, HSI, zFCP) */
res->io.range++;
/* two channels */
case 0x3088: /* CU3088 (CTC, LCS) */
res->io.range++;
}
hd=add_hd_entry(hd_data,__LINE__,0);
add_res_entry(&hd->res,res);
hd->vendor.id=MAKE_ID(TAG_SPECIAL,0x6001); /* IBM */
hd->device.id=MAKE_ID(TAG_SPECIAL,cutype);
hd->sub_device.id=MAKE_ID(TAG_SPECIAL,devtype);
hd->bus.id=bus_ccw;
hd->sysfs_device_link = new_str(hd_sysfs_id(curdev->path));
hd->sysfs_bus_id = new_str(strrchr(curdev->path,'/')+1);
if(cutypes[res->io.base]==-2) /* virtual reader */
{
hd->base_class.id=bc_scanner;
}
if(cutypes[res->io.base]==-3) /* virtual punch */
{
hd->base_class.id=bc_printer;
}
/* all other device data (names, classes etc.) comes from the s390 ID file */
hd->detail=free_hd_detail(hd->detail);
hd->detail=new_mem(sizeof *hd->detail);
hd->detail->ccw.type=hd_detail_ccw;
hd->detail->ccw.data=new_mem(sizeof(ccw_t));
hd->detail->ccw.data->cu_model=cumod;
hd->detail->ccw.data->dev_model=devmod;
hd->detail->ccw.data->lcss=(strtol(curdev->bus_id,0,16) << 8) + strtol(curdev->bus_id+2,0,16);
hddb_add_info(hd_data,hd);
}
if(virtual_machine)
{
/* add an unactivated IUCV device */
hd=add_hd_entry(hd_data,__LINE__,0);
hd->vendor.id=MAKE_ID(TAG_SPECIAL,0x6001); /* IBM */
hd->device.id=MAKE_ID(TAG_SPECIAL,0x0005); /* IUCV */
hd->bus.id=bus_iucv;
hd->base_class.id=bc_network;
hd->status.active=status_no;
hd->status.available=status_yes;
hddb_add_info(hd_data,hd);
/* add activated IUCV devices */
bus=sysfs_open_bus(BUSNAME_IUCV);
if(bus)
{
devlist=sysfs_get_bus_devices(bus);
if(devlist)
{
dlist_for_each_data(devlist, curdev, struct sysfs_device)
{
hd=add_hd_entry(hd_data,__LINE__,0);
hd->vendor.id=MAKE_ID(TAG_SPECIAL,0x6001); /* IBM */
hd->device.id=MAKE_ID(TAG_SPECIAL,0x0005); /* IUCV */
hd->bus.id=bus_iucv;
hd->base_class.id=bc_network;
hd->status.active=status_yes;
hd->status.available=status_yes;
attributes = sysfs_get_device_attributes(curdev);
dlist_for_each_data(attributes,curattr,struct sysfs_attribute)
{
if(strcmp("user",curattr->name)==0)
hd->rom_id=new_str(curattr->value);
}
hd->sysfs_device_link = new_str(hd_sysfs_id(curdev->path));
hd->sysfs_bus_id = new_str(strrchr(curdev->path,'/')+1);
hddb_add_info(hd_data,hd);
}
}
}
}
}
void hd_scan_s390(hd_data_t *hd_data)
{
if (!hd_probe_feature(hd_data, pr_s390)) return;
hd_scan_s390_ex(hd_data, 0);
}
void hd_scan_s390disks(hd_data_t *hd_data)
{
if (!hd_probe_feature(hd_data, pr_s390disks)) return;
hd_scan_s390_ex(hd_data, 1);
}
#endif

5
src/hwinfo/src/hd/s390.h Normal file
View File

@@ -0,0 +1,5 @@
/** register all S/390 devices */
void hd_scan_s390(hd_data_t *hd_data);
/** register only S/390 disks */
void hd_scan_s390disks(hd_data_t *hd_data);

Some files were not shown because too many files have changed in this diff Show More