So, diese Frage zu beantworten ist leider nicht ganz einfach, denn um es erschöpfend zu tun müsste man sehr tief in FreeBSDs Interna einsteigen. Da ich dazu weder Zeit noch Lust habe, nur die Kurzfassung. Ich kann hier immer nur wieder auf "The Design and Implementaion of the FreeBSD Operating System" verweisen, was zwar nur Version 5.2 abdeckt, im Großen und Ganzen aber immer noch die beste referenz zu FreeBSDs Interna und UNIX allgemein ist.
Um diese Ausgaben zu verstehen, musst du wissen wie FreeBSD intern Geräte handhabt. Grundsätzlich wird jedes physikalische Gerät intern durch eine Instanz der device_t Struct repräsentiert. Der Treiber (Ich nenne es mal Treiber, obwohl die Unixer eigentlich lieber die Bezeichnung "Modul" sehen) abstrahiert dieses Gerät zu etwas internem, meist einem oder mehreren dev_t. dev_t werden anschließend von devfs in /dev als Device-Node bereitgestellt. Das Problem, was sich nun ergibt ist, dass einzelne Treiber Abhängigkeiten untereinander haben. Zum Beispiel kann eine USB-Maus von ums(4) nur dann abgesprochen, wenn der zugrundeliegende USB-Bus (meist ehci(4)) bereits vorhanden ist. Außerdem wäre dumm, wenn jeder Treiber seine eigene Suppe zum Initialisieren kochen würde.
Daher bekam FreeBSD mit Version 3.0 ein System namens NEWBUS. NEWBUS ist mal simpel gesagt die Treiberschnittstelle, also ein Framework welches Funktionen bereit stellt Treiber zu initialisiere und zu ordnen. Man muss nicht zwingend NEWBUS nutzen, inzwischen machen es aber bis auf einige zunehmend aussterbe Altlasten alle Treiber. Daher beachten wir andere Fälle erst einmal nicht. Der Name sagt schon, was NEWBUS ist:
- New da es damals neu war und ältere Verfahren ablöste.
- Bus, da es ein Bus ist. Jeder auf ihm sitzende bekommt alles mit.
Wenn der Kernel startet, kann man den Prozess grob in zwei Teile trennen. Zuerst wird der Kernel selbst (src/sys/$platform, src/sys/kern/ und src/sys/vm) initialisiert:
Code:
Copyright (c) 1992-2011 The FreeBSD Project.
Copyright (c) 1979, 1980, 1983, 1986, 1988, 1989, 1991, 1992, 1993, 1994
The Regents of the University of California. All rights reserved.
FreeBSD is a registered trademark of The FreeBSD Foundation.
FreeBSD 8.2-RELEASE-p4 #0: Fri Oct 28 11:00:47 CEST 2011
root@happy.home.yamagi.org:/usr/obj/usr/src/sys/HAPPY amd64
Timecounter "i8254" frequency 1193182 Hz quality 0
CPU: Intel(R) Core(TM) i7-2600K CPU @ 3.40GHz (3411.15-MHz K8-class CPU)
Origin = "GenuineIntel" Id = 0x206a7 Family = 6 Model = 2a Stepping = 7
Features=0xbfebfbff<FPU,VME,DE,PSE,TSC,MSR,PAE,MCE,CX8,APIC,SEP,MTRR,PGE,MCA,CMOV,PAT,PSE36,CLFLUSH,DTS,ACPI,MMX,FXSR,SSE,SSE2,SS,HTT,TM,PBE>
Features2=0x179ae3bf<SSE3,PCLMULQDQ,DTES64,MON,DS_CPL,VMX,EST,TM2,SSSE3,CX16,xTPR,PDCM,PCID,SSE4.1,SSE4.2,POPCNT,<b24>,AESNI,XSAVE,<b28>>
AMD Features=0x28100800<SYSCALL,NX,RDTSCP,LM>
AMD Features2=0x1<LAHF>
TSC: P-state invariant
real memory = 17179869184 (16384 MB)
avail memory = 16499822592 (15735 MB)
ACPI APIC Table: <ALASKA A M I>
FreeBSD/SMP: Multiprocessor System Detected: 8 CPUs
FreeBSD/SMP: 1 package(s) x 4 core(s) x 2 SMT threads
cpu0 (BSP): APIC ID: 0
cpu1 (AP): APIC ID: 1
cpu2 (AP): APIC ID: 2
cpu3 (AP): APIC ID: 3
cpu4 (AP): APIC ID: 4
cpu5 (AP): APIC ID: 5
cpu6 (AP): APIC ID: 6
cpu7 (AP): APIC ID: 7
Anschließend wird per simplem Suchalgorithmus (tatsächlich ein angepasster Bubblesort) eine Ordnung in die vorhandenen Treiber gebracht. Aus diesen wird ein Baum erstellt und der Baum per Tiefensuche abgelaufen. Zu jedem Knoten und Blatt gehört eine Initialisierungsfunktion, die den Treiber initialisiert. Zu Beginn kennt NEWBUS nur ein Gerät und hat damit nur eine device_t: nexus0. Dies ist NEWBUS selbst. Als erstes werden nun natürlich die Bussysteme wie PCI initialisiert, was jede Menge device_t erzeugt. Dann die einzelnen Geräte und so weiter...
Eine Initialisierungsreihenfolge wäre zum Beispiel: Nexus -> PCI -> USB -> Maus.
Wenn jetzt ein neues Gerät auftaucht - sei es durch Hotplug oder durch das Laden eines Treibers - wird NEWBUS den kompletten Baum neu ordnen. Anschließend wird die Initialisierungsfunktion des des Treiber neuen Gerätes aufgerufen, sowie die darunterliegenden Knoten.
Ein Beispiel: Du hast vergessen ehci.ko zu laden, deine Maus ist aber angeschlossen. Nun wird ehci.ko eingefügt, der Baum neu geordnet. Zuerst initialisiert USB selbst, dann ums(4).
Die sich ergebenden NEWBUS-Bäume kann man sich ausgeben lassen. Im laufenden System ist das eventuell sinnvoller, als die dmesg zu parsen:
Code:
yamagi@happy:pts/6 ~: devinfo -r
nexus0
apic0
cryptosoft0
aesni0
ram0
I/O memory addresses:
0x0-0x9d7ff
0x100000-0xdedf3fff
0xdf5c9000-0xdf5cafff
0xdf67d000-0xdf7fffff
0x100000000-0x41f7fffff
acpi0
Interrupt request lines:
9
I/O ports:
0x10-0x1f
0x22-0x3f
0x44-0x5f
0x63
0x65
0x67-0x6f
0x72-0x7f
0x80
0x84-0x86
0x88
0x8c-0x8e
0x90-0x9f
0xa2-0xbf
0xe0-0xef
0x290-0x29f
0x400-0x453
0x454-0x457
0x458-0x47f
0x4d0-0x4d1
0x500-0x57f
I/O memory addresses:
0xe0000000-0xe3ffffff
0xfec00000-0xfecfffff
0xfed08000-0xfed08fff
0xfed10000-0xfed19fff
0xfed1c000-0xfed1ffff
0xfed20000-0xfed3ffff
0xfed90000-0xfed93fff
0xfee00000-0xfee0ffff
0xff000000-0xffffffff
cpu0
ACPI I/O ports:
0x414
0x415
coretemp0
est0
acpi_perf0
cpufreq0
cpu1
ACPI I/O ports:
0x414
0x415
coretemp1
est1
acpi_perf1
cpufreq1
cpu2
ACPI I/O ports:
0x414
0x415
coretemp2
est2
acpi_perf2
cpufreq2
cpu3
ACPI I/O ports:
0x414
0x415
coretemp3
est3
acpi_perf3
cpufreq3
cpu4
ACPI I/O ports:
0x414
0x415
coretemp4
est4
acpi_perf4
cpufreq4
cpu5
ACPI I/O ports:
0x414
0x415
coretemp5
est5
acpi_perf5
cpufreq5
cpu6
ACPI I/O ports:
0x414
0x415
coretemp6
est6
acpi_perf6
cpufreq6
cpu7
ACPI I/O ports:
0x414
0x415
coretemp7
est7
acpi_perf7
cpufreq7
pcib0
pci0
I/O ports:
0xf020-0xf03f
0xf040-0xf05f
0xf060-0xf063
0xf070-0xf077
0xf080-0xf083
0xf090-0xf097
I/O memory addresses:
0xfa624000-0xfa6240ff
0xfa629000-0xfa62900f
hostb0
pcib1
pci1
I/O ports:
0xe000-0xe07f
vgapci0
Interrupt request lines:
16
I/O memory addresses:
0xe8000000-0xefffffff
0xf0000000-0xf3ffffff
0xf8000000-0xf9ffffff
vgapm0
scpm0
nvidia0
hdac0
Interrupt request lines:
256
I/O memory addresses:
0xfa080000-0xfa083fff
pcm1
pcm2
pcm3
pcm4
em0
Interrupt request lines:
257
I/O memory addresses:
0xfa600000-0xfa61ffff
0xfa628000-0xfa628fff
ehci0
Interrupt request lines:
23
I/O memory addresses:
0xfa627000-0xfa6273ff
usbus0
uhub0
uhub4
hdac1
Interrupt request lines:
258
I/O memory addresses:
0xfa620000-0xfa623fff
pcm5
pcm6
pcm7
pcm8
pcib2
pci2
pcib3
pci3
xhci0
Interrupt request lines:
17
I/O memory addresses:
0xfa500000-0xfa507fff
usbus1
uhub1
pcib4
pci4
pcib5
pci5
I/O memory addresses:
0xfa410000-0xfa4101ff
atapci0
Interrupt request lines:
19
I/O ports:
0xd000-0xd00f
0xd010-0xd013
0xd020-0xd027
0xd030-0xd033
0xd040-0xd047
ata2
ata3
pcib6
pci6
xhci1
Interrupt request lines:
16
I/O memory addresses:
0xfa300000-0xfa307fff
usbus2
uhub2
pcib7
pci7
pcib8
pci8
I/O ports:
0xc000-0xc07f
ral0
Interrupt request lines:
18
I/O memory addresses:
0xfa200000-0xfa207fff
pcm0
Interrupt request lines:
19
I/O ports:
0xc080-0xc0ff
0xc100-0xc11f
fwohci0
Interrupt request lines:
17
I/O memory addresses:
0xfa208000-0xfa2087ff
firewire0
pcib9
pci9
I/O ports:
0xb000-0xb00f
0xb010-0xb013
0xb020-0xb027
0xb030-0xb033
0xb040-0xb047
ahci0
Interrupt request lines:
19
I/O memory addresses:
0xfa110000-0xfa1101ff
ahcich0
I/O memory addresses:
4195418368-4195418495
ahcich1
I/O memory addresses:
4195418496-4195418623
ehci1
Interrupt request lines:
23
I/O memory addresses:
0xfa626000-0xfa6263ff
usbus3
uhub3
uhub5
ukbd0
ums0
ubt0
isab0
ACPI I/O memory addresses:
0xfed1f410-0xfed1f413
isa0
sc0
vga0
I/O ports:
0x3c0-0x3df
I/O memory addresses:
0xa0000-0xbffff
ichwd0
ACPI I/O ports:
0x430-0x437
0x460-0x47f
atkbdc0
I/O ports:
0x60
0x64
atkbd0
Interrupt request lines:
1
ahci1
Interrupt request lines:
259
I/O memory addresses:
0xfa625000-0xfa6257ff
ahcich2
I/O memory addresses:
0xfa625100-0xfa62517f
ahcich3
I/O memory addresses:
0xfa625180-0xfa6251ff
ahcich4
I/O memory addresses:
0xfa625200-0xfa62527f
ahcich5
I/O memory addresses:
0xfa625300-0xfa62537f
ahcich6
I/O memory addresses:
0xfa625380-0xfa6253ff
ichsmb0
Interrupt request lines:
18
I/O ports:
0xf000-0xf01f
smbus0
acpi_sysresource0
acpi_ec0
I/O ports:
0x62
0x66
acpi_sysresource1
atdma0
attimer0
atrtc0
Interrupt request lines:
8
I/O ports:
0x70-0x71
acpi_sysresource2
fpupnp0
acpi_sysresource3
acpi_sysresource4
acpi_hpet0
I/O memory addresses:
0xfed00000-0xfed003ff
acpi_button0
pci_link0
pci_link1
pci_link2
pci_link3
pci_link4
pci_link5
pci_link6
pci_link7
acpi_sysresource5
acpi_sysresource6
acpi_timer0
ACPI I/O ports:
0x408-0x40b
In die dmesg kann grundsätzlich jeder schreiben, der im Kernel ist. Dabei gibt es zwei Loglevel:
- Normal sehen wir immer
- Verbose sehen wir nur, wenn der Kernel mit -v gestartet wird oder später das zugehörige sysctl gesetzt.
Hier interessieren nun erst einmal nur die NEWBUS-Ausgaben, die du oben hat. Der menschenlesbare Kram wird durch den Treiber selbst oder durch eine systemweite Datenbank ertsellt, meist durch Zuordnung zu den einzelnen Teilen der Device-ID. In 8.2 ist diese Datenbank zum Beispiel nicht wirklich aktuell, so existiert ATI noch als eigenständiges Unternehmen, weshalb er AMD-Chipsätze als ATI erkennt. Nun zum Thema:
- at: Das Gerät liegt auf einem Bus, hat aber eine eigene device_t.
- on: Das Gerät ist an ein andere Gerät gekoppelt und daher keine eigene device_t. Der Cardbus Bus ist das gleiche Gerät wie der Cardbus Controller. Ein anderes Beispiel wäre fdc(4) (Floppy-Disk-Controller) und fd(4) (Floppy-Laufwerk).
- at Device on: Die Kombination aus beiden. Der Bus-Treiber wie z.b. dein USB-Controller teilt sich das device_t mit jemand anderem. Die an diesem Bus angeschlossenen Geräte sind aber selbstständig, haben also eigene device_t.