[comp.sys.att] Loadable "block" device drivers on the UNIX pc DON'T WORK!

lenny@icus.islp.ny.us (Lenny Tropiano) (07/10/89)

Well I've been dabbling a little in device drivers lately, and my current
quest is to see if I could write a block device driver.   Using my copy of
the blocks _Writing_a_UNIX_Device_Driver_ by Janet I. Egan and
Thomas J. Teixeira, and their block driver example, I decided a good place
to start would be their *working* driver.   Although the book is specific to
MASSCOMP's implementation of UNIX, RTU, the device-driver kernel routines
were almost all identical to the UNIX pc's kernel routines.  With that book,
and my trusty photocopy of the "UNIX PC Version 3.0 Device Driver Development
Guide, Issue 0" I was on my way ...

First I started by typing in the 12 pages of code (to implement sort of a
mini-ram disk), minus the comments for now ...   Then I did the dreaded 
"cc -c" on the file.   It had a few errors, undefined this, undefined that,
typos, etc...  I played around with the header files in /usr/include/sys,
and got the appropriate changes (not much), and off I went to compile land.
This time it compiled up!   Ok, now I had to go hunting for Mike Ditto's 
vidram stuff, needed the simple INSTALL scripts he had.  Found 'em!

Modified the INSTALL scripts to install the block/character(for raw access)
device and typed "./INSTALL".  Off it went, installing the device into
the /etc/master file with the commands ...

/etc/masterupd -a block char init release open close ioctl read \
	write strategy ram
MAJ=`/etc/masterupd -b ram`
/etc/mknod /dev/ram b $MAJ 0
MAJ=`/etc/masterupd -c ram`
/etc/mknod /dev/rram c $MAJ 0

Then ... it did the /etc/lddrv/lddrv command to allocate and bind 
the driver.

cp ram.o /etc/lddrv
/etc/lddrv/lddrv -av ram
allocated: 0x4000 bytes starting at 0x5c000 for device ram, B:10 C:9 id:4
BIND failed: invalid argument

...
Hmm, I thought.  What did I do wrong? I wrote to Alex Crain 
(alex@umbc3.umbc.edu), who gave me some advice on where to look ...  
Basically the drvbind() kernel routine failed to bind the driver because 
of something... (he outlined 4 or so reasons why possibly).   Nope, the 
driver looked OK.   

Then I spoke with Gil Kloepfer (gil@limbic.UUCP) one evening, and he was
saying, "Can we do loadable block devices?  Do they work?"   All the devices
we've used are character oriented.  He suggested making a dummy driver with
all function stubs.

ram.c:
raminit() { }
ramrelease() { }
ramopen() { }
ramclose() { }
ramioctl() { }
ramstrategy() { }
ramread() { }
ramwrite() { }

This compiled (of course) and then I tried the /etc/lddrv/lddrv -av ram
command again... Sure enough it failed with the SAME ERROR!   Hmm, I thought,
the only block driver I know of is the disk driver, and that isn't loadable.
(It's built into the kernel).

Block Devices
major	device	handler	flags
 0	disk	gd	ioctl write read close open pwr strategy fix char block required
...

Hmmm, I thought to myself, I know I've seen somewhere you can do loadable
block drivers (even though the UNIX PC Device Driver Development Guide is
very vague when it comes to that...  In the file /etc/master, it has this:

...
*
* Loadable drivers
* nlbdrv	number of slots for loadable block drivers
* nlcdrv	number of slots for loadable char drivers
*
nlbdrv	NLBDRV	4
nlcdrv	NLCDRV	10

Yes, 4 slots for loadable block drivers.   Oh well, I'll forward this
posting onto the person doing the work for the *next and last* FIXDISK
for the UNIX PC.   He's fixed everything so far, I'm sure he'll love to
tackle this when he gets back from his trip :-)

So to make a long story even longer, Mike Peterson who was trying the
same thing and getting the same results ... now you know why.  Those who
tried to write SCSI device drivers (IDT) I wonder how they did it?  Or
if they did it at all, maybe that's why the SCSI board was abandoned ...

Eventually when my driver is loaded I'll be able to do this ...

# mkfs /dev/rram 200:10
# mount /dev/ram /ramdisk
# df -t /ramdisk
/ramdisk  (/dev/ram  ):      192 blocks      10 i-nodes
                 total:      200 blocks      10 i-nodes

Enough said ...  

-Lenny
-- 
Lenny Tropiano             ICUS Software Systems         [w] +1 (516) 589-7930
lenny@icus.islp.ny.us      Telex; 154232428 ICUS         [h] +1 (516) 968-8576
{ames,talcott,decuac,hombre,pacbell,sbcs}!icus!lenny     attmail!icus!lenny
        ICUS Software Systems -- PO Box 1; Islip Terrace, NY  11752

lenny@icus.islp.ny.us (Lenny Tropiano) (07/11/89)

In article <736@icus.islp.ny.us> lenny@icus.islp.ny.us (Lenny Tropiano) writes:
|>
...
|>cp ram.o /etc/lddrv
|>/etc/lddrv/lddrv -av ram
|>allocated: 0x4000 bytes starting at 0x5c000 for device ram, B:10 C:9 id:4
|>BIND failed: invalid argument
|>
|>...

Problem has been solved.  A very kind person from AT&T gave me a call
today at my office, and told me that he had similar results when he tried
block devices on the UNIX pc.  What he said was that the drvbind()
kernel routine requires the presence of *strategy() and *print() routine,
even if they don't do a darn thing...  In my case they would be called 
ramstrategy() and ramprint() respectively.

Sure enough I tried this and the driver loaded and bound itself to
the kernel space.  Now it is time to remove the bugs from the driver ;-)

BTW: According to the _UNIX PC Device Driver Development Guide_, 
print() routines (and I quote) ...

*  Print

   This entry point is for the error reporting routine of the driver.
   It is most often left unused, and is not used at all in the present
   UNIX PC kernel.   It may be here for historic reasons.


Obviously if this isn't used at all ... I still consider it a bug that
drvbind() requires it.   Oh well, if it can't be fixed at the present,
this will do.

ramprint()
{
	panic("Ut oh!  I'm in ramprint(), how did I manage this?");
}

-Lenny
-- 
Lenny Tropiano             ICUS Software Systems         [w] +1 (516) 589-7930
lenny@icus.islp.ny.us      Telex; 154232428 ICUS         [h] +1 (516) 968-8576
{ames,talcott,decuac,hombre,pacbell,sbcs}!icus!lenny     attmail!icus!lenny
        ICUS Software Systems -- PO Box 1; Islip Terrace, NY  11752