Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 30 Jan 1997 14:22:44 +1030 (CST)
From:      Michael Smith <msmith@atrad.adelaide.edu.au>
To:        mcgovern@spoon.beta.com (Brian J. McGovern)
Cc:        msmith@atrad.adelaide.edu.au, hackers@freebsd.org
Subject:   Re: Cases (was: Constructive Criticism)
Message-ID:  <199701300352.OAA26563@genesis.atrad.adelaide.edu.au>
In-Reply-To: <199701300301.WAA09208@spoon.beta.com> from "Brian J. McGovern" at "Jan 29, 97 10:01:40 pm"

next in thread | previous in thread | raw e-mail | index | archive | help
Brian J. McGovern stands accused of saying:
> >
> >This is called the "learning curve".  There are two ways to climb it, for
> >climb it you must if you want to do anything.
> >
> >1) Spend lots of time trying, asking questions, exercising your intelligence
> >   and patience.
> >2) Give lots of money to someone else to have them force you through 1).
>
> I disagree with your two cases. As with any development decision, if
> I can't justify the cost of undertaking the certain project, I won't
> even begin it.

Do you read Dilbert?   If it weren't for your other comments, I would have
to say that you were trained management.  You need to lift your eyes a
little and look at the longer-term benefits of a given exercise.

> In the case of #1, its a time/learning curve that is
> out of reach. By the time I figure it out for release x.y.z, its
> usually changed.

You're joking, right?  The driver integration model has changed _once_
in something like ten years, and that change is simple, straightforward,
and if you asked could be explained in less than a screenfull of words.

> Ok, so one bad example ;p But, still, I've noted a good chunk of the
> technical docs in the handbook always seems to be a release out of
> date. Again, perhaps its something that can be undertaken.

Writing documentation is lots of work.  Tina and her ilk are a rare
resource.

> >If you can't work out how device drivers are integrated, I seriously
> >doubt that you're up to writing one in the first place. 8(  
> >
> 
> Ah, again, a circle effect. You'll never get good till you've chewed on a
> handful of them. 

Correct.

> And you'll never start on your first till you think you
> can do it.

*This* is your failing point, and it is annoyingly common.  Given "you can
never know until you try", your attitude means that you will _never_learn_
because without an ironclad guarantee of success, you'll never make the
effort.  An attitude like that is a guarantee of failure.

> A lack of documentation makes it infinately more difficult. 

I would assert that the mailing lists are a form of interactive
documentation that transcends anything that can be statically
committed to any media.

> But, like my original
> message said, if I _am_ able to learn something useful, and return an equal 
> amount, or more time on development than what you took to teach me, its a 
> win all around.

Your offerings would be gratefully accepted, believe you me 8)

> Unfortunately, my time to tinker with such things is limited. I've
> banged out some test code in the past (simple device reads, writes,
> etc), but don't have a weekend to figure out how to stick it in the
> kernel. And until I know I have a weekend to make a concerted
> effort, I won't bother anyone with the newbie question. Why ask the
> question if the answer would be useless?

How can you make an assessment like that when you claim ignorance?
Perhaps integrating your driver is a 5-minute task?  Will you let your
timidity hold you back?

> When the time comes, I'll ask. However, I'd also like to keep the
> number of questions I have to ask to a bare minimum. I'd rather have
> it be "I'm doing XYZPDQ, and it blows up in such and such a way. Can
> any one see any obvious problem", than "What do I do now?".

I think "I have some device driver routines, how do I glue them together
so that the kernel can use them" is a pretty straightforward question.
I could (and would happily) answer that in a fashion that you should be
able to do something with directly.

> For me to grow beyond copying an example in the book, I really need
> to understand _why_ I'm doing what i'm doing.

Why not ask them then?  The authors of the code you're fretting about 
(or at the very least people that understand it) are all around, and most
are easily approachable.

> Reading someone else's chunk of code doesn't tell you WHY they
> implemented something a certain way... Good commenting would, but if
> all the code in the world had sufficient commenting, we wouldn't be
> having this discussion :)

Reading the code in its larger context will often make obvious why something
was implemented in a particular fashion.  Often "expediency" is the only
succinct answer 8)

> Tomorrow, whilest I'm at work, I will write some code for a pseudo-device
> driver I wish to call foo. I will write routines for fooinit, fooread, 
> and foowrite. According to the documentation I've read, I should be able to 
> leave the open and close routines set to (I guess NULL ?) nothing. fooinit
> will also exist, but will just contain a printf to announce the presence of
> the pseudo-driver. The driver will be a character driver, with major number
> of 20. Minor number will represent buffer numbers, each buffer will be 1K
> in length. Writes to a buffer will set the string. Reads will return it (if
> the full length is specified). Optionally, I'll use the offset attributes
> to allow multiple reads and writes. Lastly, all of these routines will
> be in a file called foodev.c.

Ok, sounds like a plan.

> Now, based on my reading, and what I've seen in some of the drivers
> I _have_ looked at, I believe that I'll have to set a cdevsw structure up,
> and it looks like a struct isa_driver. I also see probe() and attach()
> routines that I have not seen documentation on before in the books I have
> read. I see devfs support thrown in... Looks kinky. Probably will need help
> there eventually... 

Ok.

> Anyhow, want to lecture me on what some of these things are, whats required,
> whats optional, and how my stuff will fit in the cosmic scheme of things?

Sure; I'll keep it cc'd to -hackers so that others can snipe at my ignorance,
and if you save all of these messages, you should have an excellent reference
on which to base your documentation.

I'll restrict myself to ISA drivers, as these are where I'm most familiar.
PCI drivers are generally similar, but have an easier time in some
regards.

I'll use your 'foo' driver as an example.

 ====

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 :

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.

static int
fooprobe(struct isa_device *dev)

It is legitimate to alter the contents of the fields in the isa_device
structure, if new values are determined by probing for the hardware.
Note that the id_irq field is a bitmask, not a numeric value.  The
probe routine should not emit any text unless it comes up against
something particularly alarming.

The probe routine is called once per instance of the driver in the
configuration file.

Attach is called, again once per instance of the driver in the config,
when the device has been successfully probed and does not conflict.

static int
fooattach(struct isa_device *dev)

The attach routine should build any local data structures required for
management of the device.  It is traditional for the attach routine to
emit a line like :

foo0: Snarklewacker 200, rotating Floib, no BoBoBoBoB.

The startup code will have already emitted a line like :

foo0 at 0x10-20 irq 1 iomem 0x12345 on isa

Once internal state for the driver has been established, you add an entry
to the device switch for the driver.  In the case of a character device, 
the following fragment is normally used :

    dev = makedev(CDEV_MAJOR,0);
    cdevsw_add(&dev,&foo_cdevsw,NULL);

Where CDEV_MAJOR is the major device number assigned to the driver
(normally #defined somewhere obvious).

A typical cdevsw initialisation might look like :

static d_open_t         fooopen;
static d_close_t        fooclose;
static d_read_t         fooread;
static d_write_t        foowrite;
static d_ioctl_t        fooioctl;
static d_select_t       fooselect;

#define CDEV_MAJOR      20
static struct cdevsw foo_cdevsw =
{
    fooopen,          fooclose,       fooread,        foowrite,
    fooioctl,         nullstop,       nullreset,      nodevtotty,
    fooselect,        nommap,         NULL,           driver_name,
    NULL, -1
};

Note that some of the placeholders are "no*" and some are "null*" - I
think that this is laziness on someone's part 8(

To create a devfs device node :

	sc->devfs_token = devfs_add_devsw(&foo_cdevsw, unit,
					DEV_CHR, UID_ROOT, GID_WHEEL,
					0660, "foo%d", unit);

This returns a token which is saved (here) in the devfs_token field in
the device's softc structure (the per-device state structure).  The
cdevsw structure defines the driver's entrypoints, unit is the unit
number associated with the device node (you can encode major/minor
data here if you wish), DEV_CHR indicates a character device node, the
UID_ROOT, GID_WHEEL and 0660 entries set the ownership/permissions on
the new device node, and the remaining arguments are printf-style,
with a format string and parameters for the format string which yield
the name of the device node.

You can call this several times to create multiple nodes for a single
instance of the driver.


 ====

That should get you probing and attached; keep us in touch!

> 	-Brian

-- 
]] Mike Smith, Software Engineer        msmith@gsoft.com.au             [[
]] Genesis Software                     genesis@gsoft.com.au            [[
]] High-speed data acquisition and      (GSM mobile)     0411-222-496   [[
]] realtime instrument control.         (ph)          +61-8-8267-3493   [[
]] Unix hardware collector.             "Where are your PEZ?" The Tick  [[



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