Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 30 Jan 1997 09:13:54 -0600
From:      "Eric L. Hernes" <erich@lodgenet.com>
To:        "Brian J. McGovern" <mcgovern@spoon.beta.com>
Cc:        msmith@atrad.adelaide.edu.au, hackers@freebsd.org
Subject:   Re: The continuting email... 
Message-ID:  <199701301513.JAA29351@jake.lodgenet.com>
In-Reply-To: Your message of "Thu, 30 Jan 1997 00:05:43 EST." <199701300505.AAA09649@spoon.beta.com> 

next in thread | previous in thread | raw e-mail | index | archive | help
"Brian J. McGovern" writes:
>
>I'd be more than happy to hammer out documentation. I do it quite frequently.
>However, doing documentation requires a.) Coordination with the group as a

If you're serious about writing some of this down.  I'd let you
have the driver writer's guide as a starting point.  Its the out-of-date
doc we've all been refering to ;-)  When I first started learning
drivers, I wanted the same doc you're looking for.  I even scribbled
down a few notes.  The thing that I've found out about documenting
is that as you get further up the curve, different things are important.
I lose sight of what might be a big stumbling block for a beginner.  Then
as you get higher and higher, free time gets harder and harder to come
by (or maybe its just my attention defecit syndrome ;-)).  And you're
sitting there trying to make sense out of your notes and then you
finally say, screw it, I'm going to walk the dog, or go to the bar, or
go hunging, or ..., I'll just answer a few questions on -hackers ;-)

>
>>Driver initialisation is seperated into two parts, known as 'probe' and
>>'attach'.  The purpose of the 'probe' routine is to ascertain whether
>>the hardware is present, and optionally determine its configuration.
>
>>Probe/attach for ISA device drivers is triggered by the presence of a
>>non-static isa_driver structure in the driver; at least the first three
>>fields should be initialised, with the probe and attach routines and the
>>name of the driver :
>
>Ok. I know the what. Any particular reason it has to be non-static? I assume
>to cause it to blow up if there is another driver with the same name, but, 
>am I correct?

because that's the one piece of information used to bolt your driver
into the kernel.  well, that and the interrupt handler, if any.
have a look at ioconf.c in the kernel compile directory sometime.
(yet another obscure source reference ;-))

>
>Secondly, what are the fields after the first 3? 
>
>Also, I did a grep for "isa_driver" in /usr/include via a find (ie -
>grep "isa_driver" `find .` to no avail. Which header should I include?

The kernel is mostly a self-contained critter that can be placed
*anywhere* no /usr/include is usually necessary.  In fact
/usr/include/{sys,machine,net,netinet} are symlinks into the kernel
tree, if it exists.  Most if not all ISA stuff is in sys/i386/isa/***
including all device drivers, header files, and bus driver sources proper.
`struct isa_driver' is in sys/i386/isa/isa_device.h

>
>>struct isa_driver foodriver = { fooprobe, fooattach, "foo"};
>
>>The 'fooprobe' function is called during startup to determine whether
>>the device is present or not.  It should return zero if the probe
>>for the hardware failed, or the size of the I/O space occupied by
>>the device if the probe succeeded.
>
>Please define "size of the I/O space". To me, this can mean many
>things, probably all of which are wrong. Is it the number of ports a 
>device uses? Amount of memory (shared or otherwise)? And how about
>our simulated pseudo device, which won't control hardware, but might
>have a few K in buffers?

In the i386 architecture, there are really four different ways to
get data to/from a device: 1) I/O space, or I/O mapped IO, 2) shared
memory segment, or memory mapped IO, 3) DMA, 4) interrupts.

I/O mapped IO is accomplished via the inb/outb family of instructions.
These are conveniently wrapped up in machine/cpu_func.h so that in your
code you can just outb(someaddr, someval).  NOTE that if you're porting
some code from linux, they have the args reversed!  If our device has
the config line: `device ep0 at isa? port 0x300 net irq 10 vector epintr'
`port 0x300' is the address in the IO space.

Memory mapped IO is a region usually in the 640K-1M range that the
device shares with the OS. In the config line
`device ie0 at isa? port 0x360 net irq 7 iomem 0xd0000 vector ieintr'
`iomem 0xd0000' sets the memory mapped IO address.  You can set pointers
to this physical addr, and do bcopy's bzero's etc.  You will have
to make sure that you are accessing the memory via a `kernel virtual
address', or you'll panic.  The isa_device pointer handed to probe() and
attach are a KVA.  If you want to see the physical addr, use kvtop().

DMA (on the isa bus) is accomplished by isa_dma* family of functions.
There is no docs on this, so you'll have to grep in sys/i386/isa for
their use :(  Or use the source in sys/i386/isa/isa.c
The line: `device cx0 at isa? port 0x240 net irq 15 drq 7 vector cxintr'
shows that this device uses DMA channel 7.  There's a pretty good
section in the handbook on DMA.

Interrupts are just a signaling mechanism, similar to signals in user
processes.  But they add a lot of concurrency issues to a driver.
The line `device fea0 at isa? net irq ? vector feaintr' shows that
the driver can figure out the IRQ from the card, and the interrupt
handler is `feaintr', which must be non-static.

>
>Ok. Looks clear enough. I'm assuming we're still in attach here... I'm 
>also assuming that block devices would call bdevsw_add (wrong name i think,
>but I think I get the idea). How about STREAMS types or tty type devices that
>are linked off through a line protocol?

There are no STREAMS.  Network drivers are quite different from standard
character drivers, but they are also documented better in the 4.4BSD book.
Most of the multi-line serial drivers are derrived from sio.  There is
a slight bit of glue required to get the driver to work with line
disciplines, but thats covered in the 4.4 book too (I think)  Other than
that its just a character driver.  In fact for the first phase of development,
I'd be inclined to get it working as a standard char device, then when
that's working, go for the line discipline stuff.  But then I've never
written one either.

>
>Ok. Some of it makes sense. Is there a blank generic one that gives the
>appropriate order? For instance, I see nullstop and nullreset. There should
>also be a poll routine in there some where? Is it a NULL? a no? a -1?

Poll is SysV, BSD uses select for similar operations.  For a ttydriver,
I think you can safely set this to the generic `ttselect' and have
it work.

>>
>Ok. Is creating a devfs node mandatory? I know people would like to move to
>it, but when/is it required? What makes the decision if it is optional?

Not mandatory, you should respect the `DEVFS' pre-processor macro.
like:

#ifdef DEVFS
<do devfs stuff>
#endif

eric.

-- 
erich@lodgenet.com
http://rrnet.com/~erich erich@rrnet.com






Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199701301513.JAA29351>