================================================================ COMPILING DRIVERS, for Linux Newbies This text provides a very minimal introduction to compiling drivers, particularly WinModem drivers under Linux. Must points are covered in much more detail in the Linux HOWTO documentation set. WinModem drivers commonly include: 1) a readible Open Source component, which can be readily debugged by experts in code. This component provides "wrappers" to common kernel functions for the binary and a Closed Source component of the modem code. 2) A Closed Source component compiled into BINARY form in which the original source code is not available to the public to protect its proprietary information. The binary format precludes incorporation of the modem drivers in many Linux distributions (Debian, Mandrake, Red hat, etc.) for legal reasons, practical reasons, and/or reasons of principle. Thus the modem user must commonly COMPILE his own drivers, and properly install these drivers into their Linux System. Fully pre-compiled modem binaries are generally not provided. The administrative cost is too high, for maintaining drivers for all the different customized variations to the linux kernel distributions use. Pre-compiled binaries are usually only found for the most common and generic distributions on the market. Since almost all the newer PCs are now equipped with WinModems, most everyone will have to compile theirown linux modem drivers. Exceptions are the more expensive modems with Controller chipsets, characteristic of the earliest modems. They are supported by Open Source serial code included in Linux distributions (Distros hereafter). Winmodems are less expensive because of greatly reduced hardware costs (ie: no Digital Signal Processing, DSP, and/or no controller chips). Some of the functions of the older Controller based chipsets are replaced by a combination of software code and/or other System hardware. Modems without a controller are referred to as "controllerless modems" and modems without a DSP and controller are referred to as "soft modems". With faster central processor units (CPU), some processing tasks are performed by the CPU for the HCF (host controller free) modems. For the soft modems serving under ac97_codec audio singnal processing rules the digital audio card does some of the signal processing. COMPILING is the process of converting human readable source code into compact binary code that the Operating System (OS) can process quickly. For winmodems, code components from the modem chipset provider are combined with KERNEL-HEADERS, thus generating one or more complementary drivers. They are commonly compiled as Modules and installed as ModuleNames.o into sub-folders of: /lib/modules/kernel-version/ Therefrom they can be dynamically inserted into the boot kernel of the Operating System (OS) when needed, sometimes with auxiliary instructions from /etc/modules.conf They can be removed from the kernel when no longer serving, thus economizing on System resources. The KERNEL-HEADERs have FileNames.h can can be read with a text browser. Some are installed to /usr/include/ For systems with RPM package managers, they are provided by a package kernel-headers-SomeVersion.rpm They specify: 1) code bits to be incorporated by various of your installed programs, and 2) the dependencies within the set of FileNames.h However the whole set of /usr/include/FileNames.h Are in general TOO FEW to support compiling. Exceptions to note are the kernel-header-version.deb packages of Debian style Distros, which are designed to support compiling. A KERNEL-SOURCE package must more generally be installed, and processed to produce needed kernel headers. The kernel-source is some 20-30 MB now even in compressed form. The kernel-source package provided by your Linux Distro SHOULD preferentially be used. It will usually have some differences from that initially released at http://www.kernel.org . Typically the installation process will set a symbolic link: /usr/src/linux --> PATH_to/kernel-source-version/ Check with: ls -l /usr/src/linux Move into it with: cd /usr/src/linux Look at the first few lines of the Makefile with: more Makefile They will look like: -------------------- VERSION = 2 PATCHLEVEL = 4 SUBLEVEL = 21 EXTRAVERSION = -Some.Extraversion.Designation -------------------- wherein -Some.Extraversion.Designation was that last used by your Linux Distro for a specialization of the more general kernel-release 2.4.21 . For Mandrake Linux their will generally be an include an "mdk", such as: EXTRAVERSION = -3.1mdk These four makefile lines specify that: 1) the compiled kernel will have a version name like: vmlinuz-2.4.21-3.1mkd 2) the complementary kernel modules will have an encoded version label: 2.4.21-3.1mkd 3) the modules will be installed by: make modules-install to sub-folders of /lib/modules/2.4.21-3.1mkd/ Some kernel-headers from a prior usage may be resident from the Last.Usage of the kernel-source/. Check with: ls include/linux/ which may display abundant FileNames.h The version of these headers will be in the UTS line displayed (for example) by cat include/linux/version.h #define UTS_RELEASE "2.4.21-3.1mdk" Next, list completely the contents of your current folder /usr/src/linux with: ls -a Where the " -a " additionally reveals ".dot-prefixed-confguration-files" such as .config .hdepend .depends which may be left over from the prior usage of the kernel-source. IMPORTANT: the kernel-source as installed generally WILL NOT represent your current kernel version as displayed with: uname -r even if the kernel-version is the same. For example, in the RedHat Distro kernel-source/ there is a set of kernel-configuration files within /usr/src/linux/configs/ Each is specialized for a different CPU (i586, i686, K6, etc), Yet each will be represented by the VERY SAME version.h and "uname -r" . !!!! Thus a PROPER CONFIGURATION MUST BE DONE by You, before any usage of kernel-source !!!! Configuration of the kernel-source is where almost all the Mistakes occur!!! Here is a way to do it correctly (but read through EXCEPTIONAL CASES below). 1)Within /usr/src/linux, browse the README file for general guidance. It will relate the usage: # make mrproper cleans up leftovers from any previous usage .dot-files and the include/linux/ folder. Additionally you may need to do an edit within Makefile, but ONLY that 4th line. If the general source release version is say 2.4.21 and # uname -r Displays 2.4.21-8.1enterprise This EXTRAVERSION mis-match must be corrected. Otherwise, compiled drivers would not be installed to the matching: /lib/modules/kernel_version/ 2) If necessary to edit, FIRST make a backup: cp Makefile Makefile.backup then edit ONLY the 4th line of Makefile to EXTRAVERSION = -8.1enterprise NEVER change anything else within the Makefile. 3) Copy the config file of the current kernel to # /usr/src/linux/.config and DO SPECIFY that " . " But where is it? For many Distros, it will be the file like /boot/config-2.4.21-Current.Kernel.Extraversion matching the output of: # uname -r Or it may be the target of a symbolic link: /boot/config --> So # cp /boot/config-2.4.21-Current.Kernel.Extraversion /usr/src/linux/.config For SuSE linux it is: # cp /boot/vmlinuz.config /usr/src/linux/.config PLEASE do not omit that "." in .config as it is crucially necessary. View .config with a text browser. It is simply a listing of the code components used in the kernel and its modules. 4) The .config file will be read during # make oldconfig which feeds its specifications through a process specifying the SAME inter-dependencies previously used in compiling your kernel, and generating fresh .dot-config files . They can be displayed with: # ls -al 5) Though it may be redundant after "make mrproper", it will do no harm to: make clean 5a) If your Linux Distribution is SuSE, there will exist files: /boot/vmlinuz.autoconf.h /boot/vmlinuz.version.h They MUST be copied as: cp /boot/vmlinuz.autoconf.h /usr/src/linux/include/linux/autoconf.h cp /boot/vmlinuz.version.h /usr/src/linux/include/linux/version.h 6) Now rebuild kernel headers with: make dep 7) Check with: ls include/linux/ and cat include/linux/version.h to verify the version. EXCEPTIONAL CASES For Distros with a Debian style package management system, a kernel-header-Version.deb package matched with your kernel-version is available. If may suffice to set a symbolic link: ln -s /usr/src/kernel-header-Version /usr/src/linux and then compile the modem drivers. If a custom kernel is to be compiled, the kernel-package.deb software will GREATLY simplify the task. Here is a typical command line: make-kpkg --revision 2:test.1 --append_to_version -MySpecial --arch_in_name --initrd kernel_headers kernel_image wherein "--append_to_version -MySpecial" replaces the need for an edit of the Makefile 4th line: EXTRAVERSION = For the 2.4.nn kernels, a symbolic link is set during initial module installations: /lib/modules/kernel-version/build --> /usr/src/linux The driver resources from Intel (and others?) have a Makefile using this build link. So if your compile fails, check with: ls -l /lib/modules/kernel-version/build Then establish the build link if necessary with: ln -s PATH-To/kernel-source or headers folder/ /lib/modules/kernel-version/build Do NOT forget the "-s" for symbolic, or you will Duplicate folder contents As already mentioned above, for the SuSE distribution, there may be files: version.h autoconfig.h located in the /boot/ folder. Before beginning a compile, they should be copied to /usr/src/linux/include/linux/ Someone reported that a critical header file: modversions.h is written to /usr/src/linux/include/linux ONLY if the kernel-source package has been installed with the YAST package manager. COMPILING the MODEM DRIVERS can now finally be done. Unpack the compiler kit for your modem drivers, cd into its folder, read any README files, make clean FINALLY, your modem drivers will compiled by a command like make ModuleName or perhaps make all During this process, some of the kernel-header code with be joined with the supplied modem specific code, and ModemDrivers.o will be produced. Follow and further instructions in the modem code resource to install the drivers, often with: make install ## end COMPILING DRIVERS =================================================== FOLLOW UP STEPS. 1) Check for a symbolic link: ls -l /dev/modem which should display something like /dev/modem --> /dev/WinModemPort Some Distros may set a default /dev/modem --> /dev/ttyS0 (or 1,2,3) which are for Controller Chip modems only. If represent,as Root: # rm -f /dev/modem # ln -s /dev/WinModemPort /dev/modem If may prove necessary to disable a default BOOT UP setup for Controller Chip modems, to prevent resetting of the unwanted default link. 2) Loading drivers Depending upon your installation, the modem drivers may/may_not be autoloaded. Login as Root in a console with: # su - root # lsmod If the modem drivers are not already loaded onto the kernel, insert them with command # modprobe ModuleDriver 3) Testing drivers. For a first test of the drivers, it is Very Usefull to have installed the package: wvdial Do read "man wvdial" and sometime browse the documentation that is written to /usr/share/doc/wvdial/ The first step in setting up wvdial is to run its configuration program as Root. Below is the output from a System with a Lucent/Agere modem wvdialconf will either follow a symbolic link /dev/modem --> /dev/ModemPort or check through ports with name style: /dev/ttyS* Below ttySLT0 is the modem port name, replacing /dev/ttyLTO when the Device Files System (devfs) is in use. %% begun lines below are my added comments. # wvdialconf /etc/wvdial.conf Scanning your serial ports for a modem. ttySLT0<*1>: ATQ0 V1 E1 -- OK ttySLT0<*1>: ATQ0 V1 E1 Z -- OK ttySLT0<*1>: ATQ0 V1 E1 S0=0 -- OK ttySLT0<*1>: ATQ0 V1 E1 S0=0 &C1 -- OK ttySLT0<*1>: ATQ0 V1 E1 S0=0 &C1 &D2 -- OK ttySLT0<*1>: ATQ0 V1 E1 S0=0 &C1 &D2 +FCLASS=0 -- OK %% in the AT* tests above Only the lt_modem.o driver is being interrogated ttySLT0<*1>: Modem Identifier: ATI -- LT V.92 Data+Fax Modem Version 8.26a %% The ATI test queries the modem firmware, concurrently prompting loading of the lt_serial.o driver ttySLT0<*1>: Speed 4800: AT -- OK ttySLT0<*1>: Speed 9600: AT -- OK ttySLT0<*1>: Speed 19200: AT -- OK ttySLT0<*1>: Speed 38400: AT -- OK ttySLT0<*1>: Speed 57600: AT -- OK ttySLT0<*1>: Speed 115200: AT -- OK ttySLT0<*1>: Max speed is 115200; that should be safe. ttySLT0<*1>: ATQ0 V1 E1 S0=0 &C1 &D2 +FCLASS=0 -- OK Found a modem on /dev/ttySLT0. : Can't read config file /etc/wvdial.conf : No such file or directory Modem configuration written to /etc/wvdial.conf ttySLT0: Speed 115200; init "ATQ0 V1 E1 S0=0 &C1 &D2 +FCLASS=0" %%% This wvdialconf action if successful generates the files: /etc/ppp/peers/wvdial /etc/ppp/peers/wvdial-pipe and for further editing, /etc/wvdial.conf [Dialer Defaults] Modem = /dev/ttySLT0 Baud = 115200 Init1 = ATZ Init2 = ATQ0 V1 E1 S0=0 &C1 &D2 +FCLASS=0 ISDN = 0 Modem Type = Analog Modem ; Phone = ; Username = ; Password = Note that if your IP is the MicroSoft Network, then use syntax: Username = MSN/ Edit these lines and remove the ";" to activate them. Many Users prefer to use the dialout utility KPPP. This is fine. But each User MUST run the configuration process separately. In principle, different Users on the same Linux System could have different Internet providers and/or use different modems. 4) Preparation for your first dialout. Concurrent ethernet capability will compete for the Domain Name Service (DNS) needed for browser naviagation. So as root: # /sbin/ifconfig eth0 down before starting a dialout! With a Mandrake installation, it will be necessary to: # /etc/init.d/network stop 5) Internet clients such as Netscape, Mozilla, Explorer etc. should be CLOSED during your first dial out trials. Should a URL on the Internet be specifed as the default URL/connect, then the Client may compete with ppp for connectivity functions. After PPP functionality has been verified, the effects of opened or launched browsers can be checked If you have installed the DIALD (dial on demand) package, stop it for initial tests: # /etc/init.d/diald stop Otherwise diald function will be initiated with modem usage, and could compilate issues. Test diald only after ppp by itself is fine. If your internet provider assigns DNS dynamically then add to /etc/ppp/options: usepeerdns To analyze a dialout attempt, it is useful to display kernel messages with: # tail -f /var/log/messages & or to achieve some prefix trimming: # tail -f /var/log/messages | cut -d: -f4- & The & puts the commanded process in the "background" allowing recovery of the command prompt. Some dialer packages (kppp etc) may automate the above steps. 6) A dail out with wvdial will then display like: # wvdial & --> WvDial: Internet dialer version 1.53 --> Initializing modem. --> Sending: ATZ ATZ OK --> Sending: ATQ0 V1 E1 M1 S0=0 &C1 &D2 +FCLASS=0 ATQ0 V1 E1 M1 S0=0 &C1 &D2 +FCLASS=0 OK --> Modem initialized. --> Sending: ATDT3019178111 --> Waiting for carrier. ATDT3019178111 CONNECT 53333 V42bis --> Carrier detected. Waiting for prompt. ** APX1.LNH.MD.RCN.NET Terminal Server ** Login: --> Looks like a login prompt. --> Sending: marvstod marvstod Password: --> Looks like a password prompt. --> Sending: (password) Entering PPP Session. IP address is 66.44.1.6 MTU is 1006. --> Looks like a welcome message. --> Starting pppd at Sat Jul 26 13:59:03 2003 --> pid of pppd: 2404 : pppd 2.4.1 started by root, uid 0 : Using interface ppp0 : Connect: ppp0 <--> /dev/tts/LT0 : kernel does not support PPP filtering Jul 26 13:59:08 stodolsklap kernel: PPP BSD Compression module registered Jul 26 13:59:08 stodolsklap kernel: PPP Deflate Compression module registered : local IP address 66.44.1.6 : remote IP address 208.59.89.132 : primary DNS address 207.172.3.8 7) Note that for some Linux distributions (Mandrake for one), maintain modules in compressed module.gz format, if modem service was not specified during the Linux installation. A subsequent installation of any dialer package: wvdial - PPP dialer with built-in intelligence. kppp - PPP dialer for KDE dtmfdial - A DTMF Tone Dialer gkdial - Gtk-based PPP dial-up configuration tool. gkdial-gnome - GNOME-based PPP dial-up configuration tool. masqdialer - daemon for remote control of masqueraded dialup links will stimulate unpacking of ppp related modules during bootup. The cogent ppp related modules loaded during such a CONNECT are displayed within the output from: # lsmod ppp_deflate 3512 1 (autoclean) zlib_inflate 18980 0 (autoclean) [ppp_deflate] zlib_deflate 18648 0 (autoclean) [ppp_deflate] bsd_comp 4440 0 (autoclean) ppp_async 7744 1 (autoclean) ppp_generic 16380 3 (autoclean) [ppp_deflate bsd_comp ppp_async] slhc 5264 1 (autoclean) [ppp_generic For ealier 2.4.nn kernels, loading of these modules may be need the following lines within /etc/module.conf : ### automate ppp modules loading ### alias /dev/ppp ppp_generic alias char-major-108 ppp_generic alias tty-ldisc-3 ppp_async alias tty-ldisc-14 ppp_synctty alias ppp-compress-21 bsd_comp alias ppp-compress-24 ppp_deflate alias ppp-compress-26 ppp_deflate ### end ppp block #### For more recent kernels with their modutils, these lines are no longer needed. 8) For potential causes of a NO DIALTONE failure, read the Post-install.html at http://linmodems.technion.ac.il/ Not setting the Country Code may be and additional problem. COUNTRY CODE Issues ==================== The modem which you purchase locally or abroad may not be preset with the proper Country Code setting. An incorrect setting can hinder acquisition of dial tone. Inclusion of an X3 (dial without wainting) in the modem Init string of under wvdial, including in /etc/wvdial.conf a line Stupid Modem = yes Dialtone recognition depends on the setting of country and/or local phone line equipment. To properly get dialtone for your country phone experiment use AT+GCI=xx where xx=00..FF hex number Theoretically there could be 256 different countries but not all are valid. Tables in manuals are way off date, you have to write a small script to try all combinations for yourself if you can't guess by chance. After country select you can check textual name of the country it represents. For example: at+gci=00 OK ati9 Japan If you can't find exact contry, choose the nearest one available. Nearby countries tend to have similar equipment and compatible dialtones. These comments from: Emard ================= 9) After a successful CONNECT, the Domain Name Service (DNS) needed for Browser navigation can be checked with: # ping corel.com PING corel.com (206.47.20.85): 56 data bytes 64 bytes from 206.47.20.85: icmp_seq=0 ttl=52 time=209.1 ms 64 bytes from 206.47.20.85: icmp_seq=1 ttl=52 time=189.9 ms 64 bytes from 206.47.20.85: icmp_seq=2 ttl=52 time=180.0 ms 64 bytes from 206.47.20.85: icmp_seq=3 ttl=52 time=179.9 ms # Ctrl-C aborts ping --- corel.com ping statistics --- 4 packets transmitted, 4 packets received, 0% packet loss round-trip min/avg/max = 179.9/189.7/209.1 ms # ping 206.47.20.85 PING 206.47.20.85 (206.47.20.85): 56 data bytes 64 bytes from 206.47.20.85: icmp_seq=0 ttl=52 time=179.8 ms 64 bytes from 206.47.20.85: icmp_seq=1 ttl=52 time=190.0 ms 64 bytes from 206.47.20.85: icmp_seq=2 ttl=52 time=170.0 ms # Ctrl-C aborts ping Should there be a success with: # ping 206.47.20.85 BUT a failure with the named address: ping corel.com Then DNS has not been acquired. Note that failure to stop ethernet service # /sbin/ifconfig eth0 down before starting a dialout, will commonly block DNS under ppp. To terminate the wvdial session, bring the action to the foreground (fg): # fg wvdial Ctrl-C to terminate: wvdial Caught signal #2! Attempting to exit gracefully... : secondary DNS address 207.172.3.9 : Terminating on signal 15. : Connection terminated. : Connect time 7.8 minutes. --> Disconnecting at Sat Jul 26 14:06:53 2003 10) The Debian distribution provides a utility: # pppconfig for setting up a chatscript for ppp initiation. Most dialers do use chatscripts and will produce similar records. Below is the record of a dial out initiated by: # pon : pppd 2.4.1 started by marv, uid 1000 : abort on (BUSY) : abort on (NO CARRIER) : abort on (VOICE) : abort on (NO DIALTONE) : abort on (NO DIAL TONE) : abort on (NO ANSWER) : abort on (DELAYED) : send (ATZ^M) : expect (OK) : ATZ^M^M : OK : -- got it : send (ATQ0V1E1M0S0=0W2&C1&D2+FCLASS=0^M) : expect (OK) : ^M : ATQ0V1E1M0S0=0W2&C1&D2+FCLASS=0^M^M : OK : -- got it : send (ATDT3019178111^M) : expect (CONNECT) : ^M : ATDT3019178111^M^M : CONNECT : -- got it : send (\d) : Serial connection established. : Using interface ppp0 : Connect: ppp0 <--> /dev/modem : kernel does not support PPP filtering Jul 26 14:08:39 stodolsklap kernel: PPP BSD Compression module registered Jul 26 14:08:39 stodolsklap kernel: PPP Deflate Compression module registered : local IP address 66.44.1.195 : remote IP address 208.59.89.132 : primary DNS address 207.172.3.8 11) GENERAL ITEMS If attemped insertion of a modem driver evokes a complaint like: unresolved symbol do_SAK_R9a0bcb74 then the kernel-headers using in compiling the modem drivers do not match those of your current kernel whose KernelVersion is displayed by: uname -r and whose kernel config file is often located at /boot/config-KernelVersion The section above "COMPILING DRIVERS, for Newbies" relates how to make corrections. There are definitely IPs whose login protocols are Linux hostile. If you cannot achieve a login, try another Internet Provider (IP). or ask for someone on discuss@linmodems.org to test your IP. For general upto date advice: http://linmodems.technion.ac.il/ http://linmodems.technion.ac.il/resources.html for a general PCI_ID database http://www.yourvote.com/pci/ The Vendor listing is http://www.yourvote.com/pci/vendors.txt with some Device IDs too. the original Linux winmodems URL is: http://linmodems.org with a mailing list on Winmodems: discuss@linmodems.org whose archives can be searched at: http://linmodems.technion.ac.il/wgindex.html There is an extensive modem database at: USB modem information: http://www.linux-usb.org/USB-guide/x332.html http://start.at/modem/ If your IP is MSN, the Microsoft Network, then for UserName in dialup scripts under Linux, instead use: MSN/UserName ---------- end FOLLOW UP STEPS ---------------