mirror of
https://github.com/vincentmli/bpfire.git
synced 2026-04-23 17:32:57 +02:00
Zwischencommit Installer...
git-svn-id: http://svn.ipfire.org/svn/ipfire/trunk@333 ea5c0bd1-69bd-2848-81d8-4f18e57aeed8
This commit is contained in:
@@ -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; \
|
||||
|
||||
@@ -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 !!!!
|
||||
|
||||
39
lfs/initrd
39
lfs/initrd
@@ -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)/
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
8
lfs/newt
8
lfs/newt
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
24
lfs/scsi.img
24
lfs/scsi.img
@@ -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 !!!!
|
||||
|
||||
15
lfs/slang
15
lfs/slang
@@ -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)
|
||||
|
||||
@@ -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
14
make.sh
@@ -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
341
src/hwinfo/COPYING
Normal 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
1956
src/hwinfo/ChangeLog
Normal file
File diff suppressed because it is too large
Load Diff
95
src/hwinfo/Makefile
Normal file
95
src/hwinfo/Makefile
Normal 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
|
||||
|
||||
66
src/hwinfo/Makefile.common
Normal file
66
src/hwinfo/Makefile.common
Normal 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
149
src/hwinfo/README
Normal 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
1
src/hwinfo/VERSION
Normal file
@@ -0,0 +1 @@
|
||||
10.16
|
||||
26
src/hwinfo/doc/example1.c
Normal file
26
src/hwinfo/doc/example1.c
Normal 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
26
src/hwinfo/doc/example2.c
Normal 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;
|
||||
}
|
||||
|
||||
1
src/hwinfo/doc/footer.html
Normal file
1
src/hwinfo/doc/footer.html
Normal file
@@ -0,0 +1 @@
|
||||
</body></html>
|
||||
92
src/hwinfo/doc/hwinfo.8
Normal file
92
src/hwinfo/doc/hwinfo.8
Normal 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
109
src/hwinfo/doc/libhd.doc
Normal 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
898
src/hwinfo/doc/libhd.doxy
Normal 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
50
src/hwinfo/gen-hwcfg-disk.sh
Executable 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
77
src/hwinfo/getsysinfo
Executable 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
15
src/hwinfo/hwbootscan
Normal 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
101
src/hwinfo/hwbootscan.rc
Normal 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
2103
src/hwinfo/hwinfo.c
Normal file
File diff suppressed because it is too large
Load Diff
625
src/hwinfo/hwscan.c
Normal file
625
src/hwinfo/hwscan.c
Normal 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
257
src/hwinfo/hwscand.c
Normal 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
126
src/hwinfo/hwscanqueue.c
Normal 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
17
src/hwinfo/init_message.h
Normal 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
113
src/hwinfo/scripts/mci
Executable 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
38
src/hwinfo/src/Makefile
Normal 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
|
||||
14
src/hwinfo/src/hd/Makefile
Normal file
14
src/hwinfo/src/hd/Makefile
Normal 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
78
src/hwinfo/src/hd/adb.c
Normal 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
1
src/hwinfo/src/hd/adb.h
Normal file
@@ -0,0 +1 @@
|
||||
void hd_scan_adb(hd_data_t *hd_data);
|
||||
1014
src/hwinfo/src/hd/bios.c
Normal file
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
8
src/hwinfo/src/hd/bios.h
Normal 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
1578
src/hwinfo/src/hd/block.c
Normal file
File diff suppressed because it is too large
Load Diff
2
src/hwinfo/src/hd/block.h
Normal file
2
src/hwinfo/src/hd/block.h
Normal 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
455
src/hwinfo/src/hd/braille.c
Normal 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__) */
|
||||
|
||||
1
src/hwinfo/src/hd/braille.h
Normal file
1
src/hwinfo/src/hd/braille.h
Normal file
@@ -0,0 +1 @@
|
||||
void hd_scan_braille(hd_data_t *hd_data);
|
||||
777
src/hwinfo/src/hd/cpu.c
Normal file
777
src/hwinfo/src/hd/cpu.c
Normal 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
1
src/hwinfo/src/hd/cpu.h
Normal file
@@ -0,0 +1 @@
|
||||
void hd_scan_cpu(hd_data_t *hd_data);
|
||||
242
src/hwinfo/src/hd/edd.c
Normal file
242
src/hwinfo/src/hd/edd.c
Normal 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
1
src/hwinfo/src/hd/edd.h
Normal file
@@ -0,0 +1 @@
|
||||
void hd_scan_sysfs_edd(hd_data_t *hd_data);
|
||||
136
src/hwinfo/src/hd/fb.c
Normal file
136
src/hwinfo/src/hd/fb.c
Normal 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
1
src/hwinfo/src/hd/fb.h
Normal file
@@ -0,0 +1 @@
|
||||
void hd_scan_fb(hd_data_t *hd_data);
|
||||
162
src/hwinfo/src/hd/floppy.c
Normal file
162
src/hwinfo/src/hd/floppy.c
Normal 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");
|
||||
}
|
||||
1
src/hwinfo/src/hd/floppy.h
Normal file
1
src/hwinfo/src/hd/floppy.h
Normal file
@@ -0,0 +1 @@
|
||||
void hd_scan_floppy(hd_data_t *hd_data);
|
||||
5684
src/hwinfo/src/hd/hd.c
Normal file
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
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
236
src/hwinfo/src/hd/hd_int.h
Normal 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
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
7
src/hwinfo/src/hd/hddb.h
Normal 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);
|
||||
55
src/hwinfo/src/hd/hddb_int.h
Normal file
55
src/hwinfo/src/hd/hddb_int.h
Normal 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
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
0
src/hwinfo/src/hd/hdp.h
Normal file
169
src/hwinfo/src/hd/ibm-notebooks.h
Normal file
169
src/hwinfo/src/hd/ibm-notebooks.h
Normal 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
267
src/hwinfo/src/hd/input.c
Normal 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;
|
||||
}
|
||||
|
||||
|
||||
1
src/hwinfo/src/hd/input.h
Normal file
1
src/hwinfo/src/hd/input.h
Normal file
@@ -0,0 +1 @@
|
||||
void hd_scan_input(hd_data_t *hd_data);
|
||||
1147
src/hwinfo/src/hd/int.c
Normal file
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
1
src/hwinfo/src/hd/int.h
Normal file
@@ -0,0 +1 @@
|
||||
void hd_scan_int(hd_data_t *hd_data);
|
||||
114
src/hwinfo/src/hd/isa.c
Normal file
114
src/hwinfo/src/hd/isa.c
Normal 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
12
src/hwinfo/src/hd/isa.h
Normal 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
438
src/hwinfo/src/hd/isapnp.c
Normal 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__) */
|
||||
|
||||
57
src/hwinfo/src/hd/isapnp.h
Normal file
57
src/hwinfo/src/hd/isapnp.h
Normal 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
311
src/hwinfo/src/hd/isdn.c
Normal 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
4
src/hwinfo/src/hd/isdn.h
Normal 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
308
src/hwinfo/src/hd/kbd.c
Normal 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
1
src/hwinfo/src/hd/kbd.h
Normal file
@@ -0,0 +1 @@
|
||||
void hd_scan_kbd(hd_data_t *hd_data);
|
||||
153
src/hwinfo/src/hd/klog.c
Normal file
153
src/hwinfo/src/hd/klog.c
Normal 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
2
src/hwinfo/src/hd/klog.h
Normal 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
1549
src/hwinfo/src/hd/manual.c
Normal file
File diff suppressed because it is too large
Load Diff
2
src/hwinfo/src/hd/manual.h
Normal file
2
src/hwinfo/src/hd/manual.h
Normal 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
206
src/hwinfo/src/hd/memory.c
Normal 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;
|
||||
}
|
||||
|
||||
|
||||
1
src/hwinfo/src/hd/memory.h
Normal file
1
src/hwinfo/src/hd/memory.h
Normal file
@@ -0,0 +1 @@
|
||||
void hd_scan_memory(hd_data_t *hd_data);
|
||||
742
src/hwinfo/src/hd/misc.c
Normal file
742
src/hwinfo/src/hd/misc.c
Normal 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
2
src/hwinfo/src/hd/misc.h
Normal 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
1083
src/hwinfo/src/hd/modem.c
Normal file
File diff suppressed because it is too large
Load Diff
1
src/hwinfo/src/hd/modem.h
Normal file
1
src/hwinfo/src/hd/modem.h
Normal file
@@ -0,0 +1 @@
|
||||
void hd_scan_modem(hd_data_t *hd_data);
|
||||
600
src/hwinfo/src/hd/monitor.c
Normal file
600
src/hwinfo/src/hd/monitor.c
Normal 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;
|
||||
}
|
||||
}
|
||||
|
||||
1
src/hwinfo/src/hd/monitor.h
Normal file
1
src/hwinfo/src/hd/monitor.h
Normal file
@@ -0,0 +1 @@
|
||||
void hd_scan_monitor(hd_data_t *hd_data);
|
||||
785
src/hwinfo/src/hd/mouse.c
Normal file
785
src/hwinfo/src/hd/mouse.c
Normal 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) */
|
||||
1
src/hwinfo/src/hd/mouse.h
Normal file
1
src/hwinfo/src/hd/mouse.h
Normal file
@@ -0,0 +1 @@
|
||||
void hd_scan_mouse(hd_data_t *hd_data);
|
||||
546
src/hwinfo/src/hd/net.c
Normal file
546
src/hwinfo/src/hd/net.c
Normal 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
1
src/hwinfo/src/hd/net.h
Normal file
@@ -0,0 +1 @@
|
||||
void hd_scan_net(hd_data_t *hd_data);
|
||||
295
src/hwinfo/src/hd/parallel.c
Normal file
295
src/hwinfo/src/hd/parallel.c
Normal 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 */
|
||||
|
||||
1
src/hwinfo/src/hd/parallel.h
Normal file
1
src/hwinfo/src/hd/parallel.h
Normal file
@@ -0,0 +1 @@
|
||||
void hd_scan_parallel(hd_data_t *hd_data);
|
||||
604
src/hwinfo/src/hd/pci.c
Normal file
604
src/hwinfo/src/hd/pci.c
Normal 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
1
src/hwinfo/src/hd/pci.h
Normal file
@@ -0,0 +1 @@
|
||||
void hd_scan_sysfs_pci(hd_data_t *hd_data);
|
||||
272
src/hwinfo/src/hd/pcmcia.c
Normal file
272
src/hwinfo/src/hd/pcmcia.c
Normal 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);
|
||||
}
|
||||
|
||||
1
src/hwinfo/src/hd/pcmcia.h
Normal file
1
src/hwinfo/src/hd/pcmcia.h
Normal file
@@ -0,0 +1 @@
|
||||
void hd_scan_pcmcia(hd_data_t *hd_data);
|
||||
611
src/hwinfo/src/hd/pppoe.c
Normal file
611
src/hwinfo/src/hd/pppoe.c
Normal 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]
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
1
src/hwinfo/src/hd/pppoe.h
Normal file
1
src/hwinfo/src/hd/pppoe.h
Normal file
@@ -0,0 +1 @@
|
||||
void hd_scan_pppoe(hd_data_t *hd_data);
|
||||
694
src/hwinfo/src/hd/prom.c
Normal file
694
src/hwinfo/src/hd/prom.c
Normal 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
1
src/hwinfo/src/hd/prom.h
Normal file
@@ -0,0 +1 @@
|
||||
void hd_scan_prom(hd_data_t *hd_data);
|
||||
246
src/hwinfo/src/hd/s390.c
Normal file
246
src/hwinfo/src/hd/s390.c
Normal 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
5
src/hwinfo/src/hd/s390.h
Normal 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
Reference in New Issue
Block a user