[comp.unix.wizards] Unix kernel calling the kernel

michael@maui.cs.ucla.edu (10/26/88)

I need to know how a part of the unix kernel can call another part of the
kernel (in particular, open(), read(), write(), close).

Specifically, I am planning to write a device driver for a block device
that would read the data from a tty device (Actually a psuedu tty who's
other end is another device driver--yet another fun thing to worry
about).

The system is a system 5 release 2 (Unix Pc 3.51a)
The open() call can be done at device initial open, the close() at
device initial close, but the strategy routine will need to call read
and write multiple times (I need to transfer 512 bytes of data, but the
tty buffers have a limit of 255 chars. I was planning on 8 calls of 64
bytes each). Not to mention one more write to tell the other end what
it is that I want them to do.

Now, the obvious way of just calling "read()" will fail with a recursice
TRAP inside the kernel. But there is no "open", or "read" routine defined
in the kernel's name list.

Between process accounting and core file creation, I know that it can
be done, but I do not know how.

			Michael

ferencz@cwsys3..CWRU.Edu (Don Ferencz) (10/26/88)

In article <17200@shemp.CS.UCLA.EDU> michael@CS.UCLA.EDU () writes:
>I need to know how a part of the unix kernel can call another part of the
>kernel (in particular, open(), read(), write(), close).
> [...]
>The system is a system 5 release 2 (Unix Pc 3.51a)
> [...]
>TRAP inside the kernel. But there is no "open", or "read" routine defined
>in the kernel's name list.
>
>			Michael

I don't want to go into a full desciption of how device driver routines
work, but I have had some experience in their design, so I can give
a brief note on where to look.

You won't find routines named "read()" and "write()" in the kernel tables:
these (and all other) system calls cause a trap that puts the 
processor into "kernel mode" where it looks up the routine name in
the "sysent" table (not very important).  All "read()"s, "write()"s and
other I/O calls look up which device you are referring to, then
based on whether the device is a "block" (like disks) or "character" device,
(like serial ports) check the "bdevsw" or "cdevsw" tables,
respectively.  For the hard disk driver, the "bdevsw" table has
an entry for the "major" number of the hard disk, which should have
a field which then points to the actual routine called.  To make
things easy (???) for us, it is conventional to name the routine
xxxread() and xxxwrite, where "xxx" is the name of the driver (for a 
hard disk driver, it should be "hdread()" and "hdwrite()", so these are
the actual routines you are looking for.

As far as calling one routine from another, that's no problem (unless
you are using STREAMS, which is SYSV 3.0 or greater, so don't sweat
it).  Just make sure you give the correct arguments to "hdread()"
and the like. 

The best source of information on this stuff is "The UNIX Device
Drivers Guide" by AT&T.  I think you'll definitely need a copy to
do any serious device driver work.


===========================================================================
| Don Ferencz                       |  "And in the end/                   |
| ferencz@cwsys3.cwru.EDU           |   The love you take/                |
| Department of Systems Engineering |   Is equal to the love you make."   |
| Case Western Reserve University   |       -- The Beatles                |
===========================================================================

andrew@frip.gwd.tek.com (Andrew Klossner) (11/03/88)

[]

	"Specifically, I am planning to write a device driver for a
	block device that would read the data from a tty device
	(Actually a pseudo tty who's other end is another device driver
	...)"

I've done something like this, as part of a mechanism by which kernel
messages and /dev/console traffic are routed to an X window
if-and-only-if X is up.  You open the routine by calling ptsopen; you
write by calling ptswrite; and you close by calling ptsclose.  There
are several pitfalls:

1) Under some varieties of Unix, the device driver expects the entire
device number, not just the minor number.  You have no easy way of
finding out what the major number is.  I hacked our pty driver not to
care about the major number.

2) If you call ptsclose for a pseudo-terminal that's still open, the
close routine will shut down the pty and the "legitimate" processes
that have it open will have trouble.  On the other hand, if you don't
call ptsclose and nobody had it open, it won't get shut down.  You
either have to interact with the inode locking mechanism, or you need
alternate "open" and "close" entry points into the pty driver.

3) After call call to ptswrite, you need to unschedule yourself so that
the other end of the pseudo-terminal can digest what you've fed it.

  -=- Andrew Klossner   (uunet!tektronix!tekecs!frip!andrew)    [UUCP]
                        (andrew%frip.gwd.tek.com@relay.cs.net)  [ARPA]