2008-01-16

恢復 windows XP 的system loader

(linux)

fdisk /mbr

(xp)
xp光碟開機
使用者修復模式
fixmbr

2006-05-16

Installing dri drivers on FreeBSD

Installing dri drivers on FreeBSD


*BSDI am getting quite a few questions with regards to installing dri enabled graphics drivers on FreeBSD. In this article I'll discuss the general setup, and it shoudl enable you to get this to work for every card that is supported.

Supported hardware:

  • Older Matrox hardware (g200 - g550), everything before the P series
  • Older ATI hardware (8xxx and 9000 upto 9400, basicly everything with a rv2xx chipset)
  • Some S3 hardware

What is inmediately clear from this is that it almost exclusively concerns older hardware. WHat is also clear is the complete lack of NVIDIA in the list.

Why do you need dri?

Accelerated 3d graphics, ie: OpenGL support.

OpenGL support is usefull for more then a bit of gaming. Makign previews in renderign software is just one of the more serious uses for it.

What do you need?

Of course you need a supported video card. Beyond that, you will need the sources for the kernel and you need XFree86 v4.x or Xorg 6.7 or later.

Installation

After installing the kernel sources, do the following:

cd /usr/src/sys/modules/drm
make
make install
Now you have the direct rendering modules installed, and you can load the one appropriate for your video card. The best way to do this is by adding it to the boot loader configuration, to do so, you have to add a line to /boot/loader.conf similar to:
radeon_load="YES"
Replace radeon with the proper module name for your card (mga for Matrox, s3 for.. s3) Known issues

It is worth noting that you really should load the module at boot time or at least make absolutely sure that you have either agp enabled in your kernel, or load the agp module at boot.

The issue here is that the agp module can not be loaded after the kernel booted, and the dri modules depend on agp. So if you don't have agp support when your kernel boots, dri is NOT going to work ever.

Installing X

Once the module works, you will get a message during startup that will tell you that drm is enabled and has found soem graphics hardware.

Now it is time for configuring the X server. This should be pretty straightforward, just make sure you have the dri and glx modules loaded, and select a driver appropriate for your card, and things should be fine.

You can verify if your setup indeed uses direct rendering with the glxinfo command.

Not getting X to start?

If you do not get a working X at all but the dri modules are loaded by the kernel and give the expected output on boot, it might well eb that you have a problem with your AGP setup.

The first thing to do in such a case is goto your bios and DISABLE fast write and any other advanced AGP features. Try again and see if it works now. If it does, enable the features one by oen and try each time if the X server still starts and works.

Especially ATI Radeon cards on boards with a VIA chipset are extremely picky about AGP setup, and will fail in mysterious ways when you enable fast write, so unless you like such mysteries, you better just disable this.


DRI Troubleshooting

This is a process for troubleshooting the DRI. It only works if you do it in order. OS names prefix OS-specific parts.

This process assumes you have XFree86 4.3.0 or newer installed. If not, update to any version of X.Org, or XFree86 4.3.0 or newer, before starting.

Contents

  1. Kernel Setup
    1. AGP
    2. DRM
  2. X server setup
  3. Userspace setup

Kernel Setup

AGP

If you have a PCI card you may skip this section (DRM will load the AGP driver to resolve symbols, but otherwise doesn't need it). If you have a non-Intel PCIE chipset you may also skip this step.

Check that AGP has been set up properly. If you have a PCI or PCIE card you may skip this step. Otherwise, if dmesg | grep agp returns nothing, you need to fix it.

FreeBSD:

  • If dmesg | grep agp doesn't show anything about agp, make sure you have device agp in your kernel (it's default in -stable and -current). AGP does not work when loaded as a module after boot until FreeBSD 7.0-current.

  • If your AGP module is loaded according to kldload but it didn't show up, probes fine, then you may have device agp in the kernel and loaded from loader.conf. This doesn't work, so remove it from loader.conf.

  • If you aren't using RELENG_6 (note: not RELENG_6_0), you may need to update to get support for your AGP chipset.

  • If you have device agp in the kernel but not in loader.conf, and are using RELENG_6 or newer, and it still doesn't probe, please file a PR containing the output of scanpci and your dmesg.

Linux:

  • If there are no agpgart: lines, compile agpgart into your kernel or load it as a module.

  • If it complains about an unsupported chipset/bridge, make sure you included your chipset-specific AGP support when you configured the kernel. This chipset support is for your motherboard, not for your video card, so if you have a Radeon on an Intel motherboard, you need intel-agp.ko, not ati-agp.ko.

DRM

Check that the DRM (Direct Rendering Module, the kernel module) is loaded and has found your card. Do dmesg | grep drm. You should have several lines of info, with samples below:

FreeBSD:

drm0:  port 0x9000-0x90ff mem 0xed000000-0xed00ffff,0xe0000000-0xe7ffffff irq 10 at device 0.0 on pci1
info: [drm] AGP at 0xe8000000 64MB
info: [drm] Initialized radeon 1.9.0 20020828 on minor 0
info: [drm] Loading R200 Microcode

Linux:

[drm] AGP 0.99 on Intel i815 @ 0xe8000000 64MB
[drm] Initialized radeon 1.1.1 20010405 on minor 0

Note that 64MB is not the size of the card's memory; it's the size of the AGP aperture (how much system memory can be accessed by the card if X chooses to use that much).

FreeBSD:

  • If kldload (card being one of mga, r128, radeon, sis, tdfx) says Exec format error, check your dmesg for complaints about unresolved symbols. If the unresolved symbols are agp, look at the AGP instructions above.

  • If kldstat shows your card module is loaded but nothing shows up in dmesg | grep drm, you may not have a supported card, or it may not be getting probed due to the PCI ID being missing from the driver.

Linux:

  • If you get DRM version output but not your card-specific DRM version output, you may not have a supported card, or it may not be getting probed due to the PCI ID being missing from the driver.

If your card isn't getting probed, please make sure you are using current DRM CVS sources before submitting a report of missing support. Instructions for building the DRM are at: Building.

If you are using current DRM sources and your card should be supported by an existing driver but isn't, please submit a report to http://bugs.freedesktop.org/ with the output of scanpci

X server setup

At this point DRM should be set up correctly. Start the X server and grep "Direct rendering" /var/log/Xorg.0.log. If that grep returns "Direct rendering enabled", skip ahead to the next section.

If that grep returns nothing, make sure you have lines for Load "dri" and Load "glx" in the Modules section of xorg.conf. If your changes to xorg.conf have no effect, make sure the xorg.conf you are editing matches the one being used according to grep config\ file /var/log/Xorg.0.log

Next, make sure that X works with the DRM correctly. Look at the bottom of the X log where it has lines with [dri], [drm], [agp], etc. If there are any (EE) errors in there, look at those.

If you get a message like this:

(EE) [dri] RADEONDRIScreenInit failed because of a version mismatch
(EE) [dri] libdri version is 4.2.0 but version 5.0.0 is needed.
(EE) [dri] Disabling DRI.
then your libdri module is too old. If you installed from a snapshot, be sure to update the common module. If the version numbers are the other way around (version is 5.0 but version 4.2 is needed) then you updated your server without updating your 2D driver as well.

If it complains about the kernel module version, you have to update your kernel modules. For FreeBSD, this means either modules from -current or from -stable as described in the install section. For Linux, the kernel DRM is updated semi-regularly, and [WWW]Alan Hourihane's website also has kernel modules.

Linux:

  • If you get this error message:

    [agp] AGP not available
    despite the fact that the agpgart module loaded and initialized without problems, ensure that agpgart loads before the driver module for your chipset (like the radeon module). If agpgart loads later, the driver module will not see the AGP bus. As well, make sure the kernel module for your AGP bridge loads before the driver module for your chipset. For example, if your AGP bridge is an AMD Irongate (this can be determined via lspci -v and looking for the line containing AGP), make sure that amd_k7_agp is loaded before the driver module (say radeon).
  • If you thought you had updated your kernel module and the updated version shows up after you modprobe the appropriate .o, make sure your kernel doesn't have the DRM compiled in. If you dmesg | grep drm, it will show that multiple versions were loaded. Recompile your kernel without the DRM, and install the updated module again.

  • If it says:

    [drm] drmSetBusid failed (7, PCI:1:0:0), Permission denied
    people have said that it's because the modules were built with a different gcc version than the kernel. Make sure they are in sync. Also, dmesg output should show something about version magic mismatches if this is the case.
  • If at this point, dmesg says:

    [drm:radeon_cp_init] *ERROR* radeon_cp_init called without lock held
    then you missed the part above about having the correct AGP modules loaded. 2.6 users need to make sure both the agpgart core module and the appropriate chipset-specific module are loaded. Run lspci | grep "AGP bridge" to find out what sort of AGP chipset you have. Intel needs intel-agp, VIA needs via-agp, etc.

If you find a line saying:

(EE) RADEON(0): [dri] RADEONInitVisualConfigs failed (depth 8 not supported). Disabling DRI.
or something along those lines, this is because none of the DRI drivers support rendering in 8-bit mode. If you have a Voodoo3, it only works in 16-bit mode and will say something similar if you try 32-bit. Change your depth appropriately by adding:
   DefaultDepth 16

or

   DefaultDepth 24
DefaultFbBpp 32

as appropriate to your xorg.conf's Screen section.

If there are no [dri] lines and it says Direct Rendering disabled, you may be trying to use too high a resolution. grep Static\ buffer /var/log/Xorg.0.log will find a line like:

(WW) ATI(0): DRI static buffer allocation failed -- need at least 4608 kB video memory
If so, reduce your resolution or color depth. The video ram necessary for a given resolution/depth is width*height*(depth/8)*3 kilobytes. (The 3 is for front, back, and depth buffers).

If you are using Intel i8xx hardware and it says:

(WW) I810(0): xf86AllocateGARTMemory: allocation of 1024 pages failed
(Cannot allocate memory)

You need to have X.Org allocate more system memory to the integrated graphics. In the Device section of xorg.conf, set VideoRam to something higher, for example:.

   VideoRam 32768

If you see messages about:

Symbol __glXActiveScreens from module /usr/X11R6/lib/modules/extensions/libdri.a is unresolved!

make sure you have Load "glx" in your xorg.conf's modules section. If you do have Load "glx", make sure you don't have any parts of the nvidia binary driver installed, particularly libglx.so*. Remove those, and reinstall X.Org if you continue to have problems.

Userspace setup

Next, look at a GL program. Set the environment variable LIBGL_DEBUG to verbose, i.e. setenv LIBGL_DEBUG verbose for csh-based shells or export LIBGL_DEBUG=verbose for bash-based shells. Run glxinfo, which should be included with X.Org. At the top it should show libGL trying to load the driver-specific hardware rendering library, like:

libGL: OpenDriver: trying /usr/X11R6/lib/modules/dri/radeon_dri.so.
If it isn't doing that, you have replaced your X.Org-provided libGL with some other libGL, or it's finding an old libGL from somewhere. Run ldd /usr/X11R6/bin/glxinfo and see which libGL it's finding. Make sure it's the one in /usr/X11R6/lib/libGL, or a link in /usr/lib to the one in /usr/X11R6/lib. You shouldn't have any libMesaGL* on your system.

If the driver complains about unresolved symbols:

libGL error: dlopen /usr/X11R6/lib/modules/dri/radeon_dri.so failed
(/usr/X11R6/lib/modules/dri/radeon_dri.so: undefined symbol: _glapi_noop_enable_warnings)
then your libGL is out of sync with your DRI drivers. Because APIs change, you typically need a libGL from the latest X.Org release to run DRI drivers, and sometimes you need a libGL from X.Org CVS for the latest drivers. Reinstall both your drivers and your libGL from sources from the same date.

If you get:

libGL error: failed to open DRM: Operation not permitted
libGL error: reverting to (slow) indirect rendering
then you are trying to run as a user that doesn't have permission to use the DRI (root is the default allowed user). To let all users access the DRI, add the following section to your xorg.conf:
Section "DRI"
Mode 0666
EndSection

If you get (the driver name may vary):

libGL error: dlopen /usr/X11R6/lib/modules/dri/r200_dri.so failed (libexpat.so.1 : cannot open shared object file: No such file or directory)
libGL error: unable to find driver: r200_dri.so
then make sure that you have libexpat.so.1 installed. Binary snapshots now come with a statically linked libexpat, so this should no longer be a problem.

If you get (the driver name may vary):

libGL error: dlopen /usr/X11R6/lib/modules/dri/r200_dri.so failed (r200_dri.so : cannot open shared object file: No such file or directory)
then make sure you have compiled the appropriate dri module for your card. It it could be either in a separate file (r200_dri.so in this case), or bundled in libGL.so. Edit xc/config/cf/host.def and make sure you list at least your driver (if not all available) in a line:\ \
#define BuildXF86DRI YES
/* 2D accel drivers are: ati mga glint s3virge sis savage nv tga rendition tdfx vga i810 sunffb sunleo suncg6 suncg3 suncg14 suntcx */
#define XF86CardDrivers ati
/* the next line DriDrivers defines dri modules. Valid choices: gamma i810 i915 mach64 mga r128 radeon r200 tdfx savage sis ffb
ati is not a valid DriDriver name. For new Radeon cards use r200 instead. */
#define DriDrivers radeon r200

If you have a 3dfx card and it's complaining about libglide3, or there are glide errors, you need to install the correct glide for your card as provided by your distribution.

If you are using a radeon and it complains about the module versions and maybe fails on an assertion, you need to update your DRM as in the instructions above.

If you've made it this far, glxinfo should be printing direct rendering: Yes and direct rendering for native GL programs should be working. Make sure that you are running at reasonable settings for your card, and maybe adjust your expectations of speed.

If you are experiencing trouble using GL with any program, maybe setting more [WWW]environment variables may help you.

FreeBSD:

  • Linux compatibility has its own set of issues. To debug Linux DRI compatibility (i.e. quake3/UT), use /compat/linux/usr/X11R6/bin/glxinfo with LIBGL_DEBUG=verbose set. You should be using -current as of April 25, 2003, or -stable as of May 2, 2003. Your linux_dri version should exactly match the X you have installed. If not you'll probably get segfaults. If your X.Org segfaults, make sure you don't have the linux_glx port installed. If you get coredumps on your system with SSE support (Pentium 3 and up, Athlon XP and up), you may need to set the environment variable MESA_FORCE_SSE to 1 due to what appears to be a bug with our linux compat's signal handling.

FreeBSD DRI

DRI (Direct Rendering Infrastructure) is an opensource project aimed at more fully utilizing video hardware capabilities under X11. It offers an alternative to using the nVidia drivers and a GeForce card for applications requiring OpenGL.

Note that performance on the DRI compatible cards I had available for testing was disappointing compared to the GeForce card with nVidia driver. Both DRI tests were run on a Pentium 866MHz system. I have not had a chance to test other video chipsets with DRI. It is probable that more modern video cards will show significantly better performance under DRI. I'd recommend 7 or 8 displays per second as a minimum for usability.

Card + Driver SUMA Speed Test (F12)
Matrox G400 + DRI 1.6 Displays/sec
ATI Rage 128 Pro Ultra TF + DRI 1.9 Displays/sec
GeForce + nVidia driver 10 - 20 Displays/sec

Enabling DRI on FreeBSD is relatively simple, although I have not found any official or organized documentation on it.

The steps below are for FreeBSD 5.4, but should be the same or at least similar on any recent FreeBSD. There are a number of resources on the WEB to help with troubleshooting. If you run into any problems, I suggest entering "FreeBSD direct rendering" on Google web and Google groups.

  1. Make sure the nVidia driver is NOT installed. It will interfere with the normal glx libraries needed to use dri.
  2. Install a 3D video card supported by the DRI project.
  3. Install the dri package: pkg_add -r dri This adds the DRI client modules to your X server in /usr/X11R6/lib/modules/dri. This is a necessary step I had a hard time finding out about. Without this package installed, the system logs will all erroneously indicate that DRI is working, but glxinfo will tell you it's not.
  4. Add driver_load="YES" to /boot/loader.conf, where driver is the appropriate dri driver from /boot/kernel. For example, for a Matrox card, use mga_load="YES". See /usr/X11R6/lib/modules/dri for a list of dri drivers.
  5. Make sure "dri" and "glx" are both being loaded in your xorg.conf. Also add a DRI section to allow non-root users to access the DRM device.

    Section "Module"
    Load "dri"
    Load "glx"
    ...
    EndSection

    Section "DRI"
    Mode 0666
    EndSection

  6. Restart your X server.
  7. Quick test: Run glxinfo:

    name of display: localhost:11.0
    display: localhost:11 screen: 0
    direct rendering: Yes
    ...
  8. If it says "direct rendering: No", check your logs to make sure the direct rendering module is loaded. It should look something like the text below:

    FreeBSD clone bacon ~ 206: dmesg | grep -i drm

    drm0: mem 0xfe000000-0xfe7fffff,0xfe9fc000-0xfe9fffff,0xf2000000-0xf3ffffff irq 11 at device 0.0 on pci1
    info: [drm] AGP at 0xf8000000 64MB
    info: [drm] Initialized mga 3.1.0 20021029 on minor 0

    FreeBSD clone bacon ~ 206: grep -i drm /var/log/Xorg.0.log

    (II) Loading sub module "drm"
    (II) LoadModule: "drm"
    (II) Loading /usr/X11R6/lib/modules/freebsd/libdrm.a
    (II) Module drm: vendor="X.Org Foundation"
    (II) MGA(0): [drm] bpp: 32 depth: 24
    (II) MGA(0): [drm] Sarea 2200+664: 2864
    drmOpenDevice: node name is /dev/dri/card0
    drmOpenDevice: open result is 6, (OK)
    drmOpenDevice: node name is /dev/dri/card0
    drmOpenDevice: open result is 6, (OK)
    drmOpenByBusid: Searching for BusID pci:0000:01:00.0
    drmOpenDevice: node name is /dev/dri/card0
    drmOpenDevice: open result is 6, (OK)
    drmOpenByBusid: drmOpenMinor returns 6
    drmOpenByBusid: drmGetBusid reports pci:0000:01:00.0
    (II) MGA(0): [drm] DRM interface version 1.2
    (II) MGA(0): [drm] created "mga" driver at busid "pci:0000:01:00.0"
    (II) MGA(0): [drm] added 8192 byte SAREA at 0xc2743000
    (II) MGA(0): [drm] mapped SAREA 0xc2743000 to 0x28371000
    (II) MGA(0): [drm] framebuffer handle = 0xf2000000
    (II) MGA(0): [drm] added 1 reserved context for kernel
    (II) MGA(0): [drm] Added 128 65536 byte DMA buffers
    (II) MGA(0): [drm] Registers handle = 0xfe9fc000
    (II) MGA(0): [drm] Status handle = 0xc2955000
    (II) MGA(0): [drm] installed DRM signal handler
    (II) MGA(0): [drm] Mapped 128 DMA buffers
    (II) MGA(0): [drm] dma control initialized, using IRQ 11
    (II) MGA(0): [drm] removed 1 reserved context for kernel
    (II) MGA(0): [drm] unmapping 8192 bytes of SAREA 0xc2743000 at 0x28371000
    (II) MGA(0): [drm] bpp: 32 depth: 24
    (II) MGA(0): [drm] Sarea 2200+664: 2864
    drmOpenDevice: node name is /dev/dri/card0
    drmOpenDevice: open result is 6, (OK)
    drmOpenDevice: node name is /dev/dri/card0
    drmOpenDevice: open result is 6, (OK)
    drmOpenByBusid: Searching for BusID pci:0000:01:00.0
    drmOpenDevice: node name is /dev/dri/card0
    drmOpenDevice: open result is 6, (OK)
    drmOpenByBusid: drmOpenMinor returns 6
    drmOpenByBusid: drmGetBusid reports pci:0000:01:00.0
    (II) MGA(0): [drm] DRM interface version 1.2
    (II) MGA(0): [drm] created "mga" driver at busid "pci:0000:01:00.0"
    (II) MGA(0): [drm] added 8192 byte SAREA at 0xc2651000
    (II) MGA(0): [drm] mapped SAREA 0xc2651000 to 0x28371000
    (II) MGA(0): [drm] framebuffer handle = 0xf2000000
    (II) MGA(0): [drm] added 1 reserved context for kernel
    (II) MGA(0): [drm] Added 128 65536 byte DMA buffers
    (II) MGA(0): [drm] Registers handle = 0xfe9fc000
    (II) MGA(0): [drm] Status handle = 0xc294f000
    (II) MGA(0): [drm] installed DRM signal handler
    (II) MGA(0): [drm] Mapped 128 DMA buffers
    (II) MGA(0): [drm] dma control initialized, using IRQ 11
    (II) MGA(0): [drm] removed 1 reserved context for kernel
    (II) MGA(0): [drm] unmapping 8192 bytes of SAREA 0xc2651000 at 0x28371000
    (II) MGA(0): [drm] bpp: 32 depth: 24
    (II) MGA(0): [drm] Sarea 2200+664: 2864
    drmOpenDevice: node name is /dev/dri/card0
    drmOpenDevice: open result is 6, (OK)
    drmOpenDevice: node name is /dev/dri/card0
    drmOpenDevice: open result is 6, (OK)
    drmOpenByBusid: Searching for BusID pci:0000:01:00.0
    drmOpenDevice: node name is /dev/dri/card0
    drmOpenDevice: open result is 6, (OK)
    drmOpenByBusid: drmOpenMinor returns 6
    drmOpenByBusid: drmGetBusid reports pci:0000:01:00.0
    (II) MGA(0): [drm] DRM interface version 1.2
    (II) MGA(0): [drm] created "mga" driver at busid "pci:0000:01:00.0"
    (II) MGA(0): [drm] added 8192 byte SAREA at 0xc2651000
    (II) MGA(0): [drm] mapped SAREA 0xc2651000 to 0x2836d000
    (II) MGA(0): [drm] framebuffer handle = 0xf2000000
    (II) MGA(0): [drm] added 1 reserved context for kernel
    (II) MGA(0): [drm] Added 128 65536 byte DMA buffers
    (II) MGA(0): [drm] Registers handle = 0xfe9fc000
    (II) MGA(0): [drm] Status handle = 0xc2929000
    (II) MGA(0): [drm] installed DRM signal handler
    (II) MGA(0): [drm] Mapped 128 DMA buffers
    (II) MGA(0): [drm] dma control initialized, using IRQ 11

  9. One problem I ran into with the Matrox card was low memory. If this happens, you'll see a message like DRI static buffer allocation failed in your Xorg.0.log, and you'll need to reduce the resolution or color depth of your display.
  10. If you still have problems, check out this troubleshooting guide.

2006-03-07

注音輸入法在輸入列沒有出現 "注音" 的文字

Q : 使用注音輸入法在輸入列沒有出現 "注音" 的文字, 其他輸入法則可以正常顯示 這只是顯示問題,在輸入文字都可以正常打出中文字。

A : 在 gcin-setup->注音詞音設定->精簡視窗

把它關掉。

2006-03-06

gcin 與輸入法檔案

其實其他的輸入法就是 .cin 檔案而已,用 gcin 裡面附的 gcin2tab 轉成 gcin 使用的 .gtab 格式,然後修改 gtab.list 檔案加入新的輸入法。

因為這些 .cin 是從其他人設計的輸入法拿來的,不算 gcin 作者維護。

可是比較龜毛的是,這些檔案一定要放在系統目錄,放在個人目錄下沒效。

gcin 新增輸入法的狀況大概是這樣。

目前 gcin 內附輸入法有:
代碼:
內碼 0 -
倉頡 1 cj.gtab
倉五 2 cj5.gtab
#輕鬆 2 ez7.gtab
注音 3 -
帶調粵拼 4 jyutping.gtab
拼音 5 pinyin.gtab
詞音 6 -
大易 7 dayi3.gtab
行列 8 ar30.gtab
#嘸蝦米 9 liu5new.gtab
#嘸蝦米 9 liu55.gtab
#嘸蝦米 9 liu57a.gtab
嘸蝦米 9 noseeing.gtab
簡易 - simplex.gtab
日本式 = nippon.gtab
greek ` greek.gtab

額外的輸入法則是只要有合適的 .cin 檔,都可以轉,請參考:
gcin 已支援的輸入法表格下載,中、日、韓、越、俄文、客語、台語…

2006-02-22

浅谈"watchdog timeout"出现的原因

淺談"watchdog timeout"出現的原因

[閱讀 329 次]

xie_minix

最近有比較多的人談到網卡的」watchdog timeout「問題,究竟是什麼原因造成的,大多數人都把網卡的性能不佳做為問題的根源所在。我認為網卡的性能只是一方面的因素,他還涉及到緩衝的大 小、單位時間內的包的數量、及網卡驅動程序等一系列因素。以下將從源代碼的角度來對他進行分析。

首先,我們看看到底是哪個函數發出了「watchdog timeout」字符串,只要你查一下源代碼不難看出,在各網卡的驅動程序裡的XX_watchdog(XX是各網卡的名稱,如:8139是rl, AMD7990是pcn,Inter是fxp等等)函數發出的。函數比較簡單:
static void rl_watchdog(ifp)
struct ifnet  *ifp;

/*申明ifp是一個ifnet結構,結構存放了該網卡的輸入輸
出的函數指針和一些重要參數,當然也包括rl_watchdog函數的
指針*/

{
struct rl_softc  *sc;
sc = ifp->if_softc;
/*ifnet是softc結構的一個子集,softc包含了更多的該網卡的參數*/

printf("rl%d: watchdog timeout\n", sc->rl_unit);
/*打印出是哪塊網卡出現問題。
sc->rl_unit代表該種網卡的第幾快。我們知道在一個機器裡同樣
的網卡可能有幾塊,當然此參數是由網卡驅動程序的初始化程序
填充*/

ifp->if_oerrors++;
/*累計輸出出現的錯誤包數量(o代表輸出)*/

rl_txeof(sc);
/*這裡是每個驅動程序不同的,此處為8139的,不過我覺得用rl_stop(sc)更好*/

rl_rxeof(sc);
/*這裡也是每個驅動程序不同。我覺得來一個rl_reset(sc)也不錯。*/

rl_init(sc);/*這裡大家都一樣,重新初始芯片。*/

return;
}

好了,到這我們知道是XX_watchdog函數發出了watchdog timeout信息。那麼是誰來調用該函數呢? 我們接著來看另一個函數:if_slowtimo函數,該函數在if.c中。if.c是interface(接口的簡稱), 即系統在啟動過程中初始化時必須調用其中的一些函數。ifinit函數是其中被調用的一個,這個函數很簡單:
void
ifinit()
{
static struct timeout if_slowtim;

timeout_set(&if_slowtim, if_slowtimo, &if_slowtim);
/*簡單的說就是設置一定時器*/

if_slowtimo(&if_slowtim);
/*哈哈,等不急了,先調用了再說*/

}
這樣一來,if_slowtimo就成了一個一定時間內就要執行的一個函數了,此時候,大家也知道了if_slowtimo 的大概功能,無非是定時查看各網卡的發送數據的情況,如果沒發送完成,就給該卡加一個計數器,到計數器達到一定的值時還沒發送出去就調用該卡的 XX_watchdog函數。下面我們來看看if_slowtimo函數。
void

if_slowtimo(arg)

void *arg;

{

struct timeout *to = (struct timeout *)arg;

struct ifnet *ifp;

int s = splimp();
/*在做以下操作的時候必須關中斷*/

TAILQ_FOREACH(ifp, &ifnet, if_list)
{/*搜索每一個接口設備,TAILQ_FOREACH實際上是for(...)*/

 if (ifp->if_timer == 0 || --ifp->if_timer)

  continue;
/*如果是if_timer為0或if_timer減1以後還為真,實際上是對每塊網卡
的計數器if_timer減1後判斷他是否還大於0,小於0就調用watchdog
函數。*/

 if (ifp->if_watchdog) /*不過調用之前看看該卡有沒有watchdog函數*/

  (*ifp->if_watchdog)(ifp);

}

splx(s);

timeout_add(to, hz /
IFNET_SLOWHZ);
/*每次計時器完成後都會清除,你不得不又加上去。hz是計算
機的主頻,就是說調度的間隔時間是和主頻成正比的關係。*/

}

到這裡一切都很明白了,我們只要在驅動程序的輸出包時給定一個值,而輸出函數是一個直到輸出成功才跳出的循環,不成功他就一直重試來輸出此包,而我們上面的程序就會時間一到就給你的值減1,如果減到小於0了,就watchdog timeout。我們還是來看一看程序吧:
static void rl_start(ifp)

struct ifnet  *ifp;

{

struct rl_softc  *sc;

struct mbuf  *m_head = NULL;

sc = ifp->if_softc;

while(RL_CUR_TXMBUF(sc) == NULL) {/* 1:當輸出緩衝區為空時才進行新的輸出*/

 IF_DEQUEUE(&ifp->if_snd, m_head);/*把將要輸出的數據加入到輸出隊列中。*/

 if (m_head == NULL)/* 2:申請內存失敗*/

  break;

 if (rl_encap(sc, m_head))
{/*8139卡的弱智表現在此,多加一個頭部,還要長字節對齊,影響

     到數據必須重新搬遷。花時間啊!*/

  IF_PREPEND(&ifp->if_snd, m_head);

  ifp->if_flags |= IFF_OACTIVE;

  break;

 }

 if (ifp->if_bpf)/* 3:如果包過濾存在就進行過濾*/

  bpf_mtap(ifp, RL_CUR_TXMBUF(sc));

 CSR_WRITE_4(sc, RL_CUR_TXADDR(sc),/* 4:以下為硬件輸出的IO指令*/

     vtophys(mtod(RL_CUR_TXMBUF(sc), caddr_t)));

 CSR_WRITE_4(sc, RL_CUR_TXSTAT(sc),

     RL_TXTHRESH(sc->rl_txthresh) |

     RL_CUR_TXMBUF(sc)->m_pkthdr.len);

 RL_INC(sc->rl_cdata.cur_tx);

}

if (RL_CUR_TXMBUF(sc) !=
NULL)/*如果傳送緩衝不為空,說明數據放到緩衝中已經準備傳了*/

 ifp->if_flags |= IFF_OACTIVE;/*加上正在傳標誌*/

ifp->if_timer = 5;/*設定計數器為5*/

return;

}


static void rl_intr(arg)

{

...  這中間我就不寫了

if ((status & RL_ISR_TX_OK) || (status & RL_ISR_TX_ERR))
 /*如果中斷後狀態寄存器的標識 是成功或出錯,就調用下面的程序。*/

 rl_txeof(sc);

...

}

再看rl_txeof:

static void rl_txeof(sc)

{

...

ifp->if_timer =
0;
/*哈哈,在這清0了,也就是說,只要你不是反覆在那傳,
不管傳輸錯誤和傳輸正確 都不會出現"watchdog timeout"*/

...

}

綜上所述:引起watchdog timeout的主要原因為:1、緩衝區不夠大,前面的沒發完後面的又跟的來了。2、內核的內存分配出現問題,此情況比較少發生。3、卡的質量(在IO時的吞吐量)。如何解決些問題:
首先我們必須查出導致出現該問題的原因,即是這問題中的哪個引起的,我們來修改if.h中定義一全局變量:
u_int8_t myerror; /*意思是出錯的原因代碼,按我列的來吧,1是緩衝區不夠...*/

在函數static void rl_start(ifp)中加入:

static void rl_start(ifp)

struct ifnet *ifp;

{

struct rl_softc *sc;

struct mbuf *m_head = NULL;

sc = ifp->if_softc;

u_int8_t tmperror;

if (RL_CUR_TXMBUF(sc) != NULL) {/*新加,如果是緩衝區不夠問題*/

myerror=1;

}

while(RL_CUR_TXMBUF(sc) == NULL) {

IF_DEQUEUE(&ifp->if_snd, m_head);

if (m_head == NULL)

{

myerror=2; /*內存分配出錯*/

break;

}

if (rl_encap(sc, m_head)) {

IF_PREPEND(&ifp->if_snd, m_head);

ifp->if_flags |= IFF_OACTIVE;

break;

}

if (ifp->if_bpf)

bpf_mtap(ifp, RL_CUR_TXMBUF(sc));

tmperror=myerror;/*在進行寫IO口前先保存前面出錯的原因*/

CSR_WRITE_4(sc, RL_CUR_TXADDR(sc),

vtophys(mtod(RL_CUR_TXMBUF(sc), caddr_t)));

CSR_WRITE_4(sc, RL_CUR_TXSTAT(sc),

RL_TXTHRESH(sc->rl_txthresh) |

RL_CUR_TXMBUF(sc)->m_pkthdr.len);

myerror=tmperror;/*上面兩句沒問題的話再還原前面的出錯原因*/

RL_INC(sc->rl_cdata.cur_tx);

}

if (RL_CUR_TXMBUF(sc) != NULL)

ifp->if_flags |= IFF_OACTIVE;

ifp->if_timer = 5;

return;

}

最後再改一下rl_watchdog中的顯示部分
printf("rl%d: watchdog timeout:error number is %x\n", sc->rl_unit,myerror);
當然這只是我個人的見解,可能有許多不足或沒考慮到的地方,也希望大家能提出更好、更容易的方法。