Subject: Re: Kernel source tree specifications
To: Ian Zagorskih <ianzag@megasignal.com>
From: Bill Studenmund <wrstuden@netbsd.org>
List: tech-kern
Date: 06/18/2003 11:47:07
On Wed, 18 Jun 2003, Ian Zagorskih wrote:

> Hi all,
>
> I would likt to ask is there available any clean and complete
> documentation or better specification related to the structure of
> kernel source tree ?

There isn't.

> Let me explain. I read article about "How to write your own pseudo device
> driver" from http://www.netbsd.org/Documentation/kernel/pseudo/#newdevice
>
> Nice and usefull article at least for the beginner as I am. It says that
> machine independant device driver code should be place at /sys/dev and
> machine dependant should be at /sys/arch/<arch>/<arch>.
>
> Ok, good statement. But this article says nothing about content of /src/dev.
> There are more then 40 sub-dirrectories in NetBSD 1.6.1 related to ISA, PCI,
> USB and so so on. What about this structure ? Is it explicitly defined by any
> document or "it happened so historically" ? What about other kernel source
> code tree structure ? How can i add my own "bus" into the kernel ? Where
> should i place my code ?

Ok. I'll add some notes, and I hope the FAQ keepers will integrate it in.
:-)

There are two general styles of drivers in /dev. One is where we are
driving a particular chip (especially one that is in different designs),
and the other is where we aren't.

For the ones where we are driving a particular chip, the driver is split
into a main part plus different front-ends. The different front-ends
handle attaching to different busses. The front ends usually are in the
directory of their bus, and the main part is in ic/. There are exceptions
though. :-)

As an example, I'll look at the lpt driver. cd sys/dev; ls */lpt* gives:

ic/lpt.c            ic/lptvar.h         mvme/lpt_pcctwo.c   pci/lpt_puc.c
ic/lpt_upc.c        isa/lpt_isa.c       mvme/lptvar.h
ic/lptreg.h         mvme/lpt_mvme.c     ofisa/lpt_ofisa.c

ic/lpt.c is the main part of the driver. ic/lptreg.h and ic/lptvar.h are
register definitions and driver-private variables, respectively. All the
other .c files are attachments for different busses. For instance,
isa/lpt_isa.c is the isa-bus attachment. pci/lpt_puc.c is the pci one.
ofisa/lpt_ofisa.c is for OpenFirmare based machines that have isa busses.
mvme/ is for Motorola VME busses (not sure why there are 2), and
ic/lpt_upc.c is for attaching to the upc bus (something that was on ARM
2/3 machines; not sure why it's in ic/).

The advantage of this structure is that it makes re-using code easy. When
your chip gets ported to a new bus, you just have to add in a new
attachment routine, and away you go.

A lot of this is hidden by the config glue, which is why it isn't as clear
as it might have been (if you'd been subjected to all the details).

Here's how the config lines (for i386) for the printer look:

lpt*    at pnpbios? index ?
lpt*	at puc? port ?
lpt0    at isa? port 0x378 irq 7
lpt1    at isa? port 0x278
lpt2    at isa? port 0x3bc

The config lines (in files.isa, files.i386, files.pnpbios (in the i386
arch area)) are:

device  lpt
file    dev/ic/lpt.c                    lpt                     needs-flag

attach  lpt at isa with lpt_isa
file    dev/isa/lpt_isa.c               lpt_isa

attach  lpt at puc with lpt_puc
file    dev/pci/lpt_puc.c       lpt_puc

attach  lpt at pnpbios with lpt_pnpbios
file    arch/i386/pnpbios/lpt_pnpbios.c         lpt_pnpbios

This example's a little bad in that the lpt device really shouldn't be in
files.isa, but it is for historical reasons.

So each of those kernel config lines above (lpt* at .. lpt? at ..) gets
mapped to a call to the appropriate attach routines (lpt_isa_probe &
lpt_isa_attach for lpt? at isa?, lpt_puc_{probe,attach} for lpt* at puc).

Drivers that don't fit that model just has a file. Things like ccd, vnd
just have a file. sd and cd have files in the scsipi code.

> Even while it's quite specific custom hardware and i doubt this code will be
> ever released outside of our company, i would like to play with rules of
> operating system rather inventing my own wheel.

Cool!

> At this moment i have several different PC104 addapters which implement at
> higher level some custom bus dependant message passing mechanism. CANBUS,
> BITBUS and DSP boards if to be exact. This message passing schemes do not fit
> in block nor character device scheme. For field busses like CANBUS or BITBUS
> IMO datagram socket scheme would be good.

Then you want to add a network stack. That does sound like the best thing
to do. Look at how network drivers work, and you'll come up with a new
network stack that just handles your data frames. Note: I knownothing of
these busses, so I'm just assuming thats the best thing to do. :-)

> While i have done all underlying hardware dependant board raw interface, i do
> not know at this moment how to implement kernel <-> userland interface. Can
> you suggest me a good example of alike "non-standard" interface ? ATM i'm
> trying to implement client synchronous message send->reply call through ioctl
> but it dosn't look so well for me. Even ugly :)

The datagram socket classes are probably what you want.

Take care,

Bill