Subject: Re: An unusual Scheme project
From: rpw3@rpw3.org (Rob Warnock)
Date: Sat, 01 Mar 2003 07:00:39 -0600
Newsgroups: comp.lang.scheme
Message-ID: <BxGdnVAeZ7JqM_2jXTWc-g@speakeasy.net>
William Bland <news@abstractnonsense.com> wrote:
+---------------
| Harri Haataja wrote:
| > I find the desire some (esp Linux) people have to push things to
| > kernel space very strange. I would think everything that is
| > possible to do in the much more safe and managed user space,
| > should be kept there.
| 
| I agree for most things, but I can't see a kernel exploration
| system / rapid driver development platform working particularly
| well in user space ;-)
+---------------

Uh... It works *extremely* well, actually! And it's *much* easier
to do debugging when the code-under-test is in user mode! Building
a bringup environment for new (and often initially broken!) hardware
was precisely what I used Scheme for when I first started using it
back at SGI circa 1992!! All I had to do was add a few primitives
in C (dynamically-loadable into SCM, later MzScheme) for poking at
the system & hardware:

	malloc & free 	; Note: *Not* from GC'd space
	mpin		; Pin a virtual address range of the process
			;  in physical memory, similar to unix v.7 "sys()".
	vir->phys	; Once you've pinned it, where is it? [Needed for DMA]
	mmap		; Map the hardware registers into process space.
	peek & poke	; In 8/16/32/64-bit flavors

That was enough to let me do almost complete debugging in user mode of
several generations of networking cards -- multi-port FDDI, Ethernet,
ATM, and HIPPI, to name a few -- including testing of both PIO & DMA
transfers. (That's why you need to "pin" pages, so other processes' data
won't get paged into that spot while you're DMA'ing into it!) The code
looked a bit like this (pardon dusty memories for any mistakes):

	(define bridge-path "/hw/module/1/slot/io3/pci/controller")
	(define big0-path "/hw/module/1/slot/io3/pci/0/usrpci/mem32")
	(define brj (mmap bridge-path 0 #x1000000 1))
	(define dev0cf (+ brj #x20000))
	(define dev0 'notyet)
	(define dev0m 'notyet)
	(let ((tmp (r32 dev0cf)))
	  (if (= tmp #x210a9)
	    (begin
	      (print "FOO present on device 0 - Enabling mem space")
	      (w32 (+ dev0cf 4) (logior PCCSR_MASTER_EN PCCSR_MEM_SPACE))
	      (print "Mapping a big window")
	      (set! dev0 (mmap big0-path (r32 (+ dev0cf #x10)) #x8000000 1))
	      (set! dev0m (+ dev0 #x7800000)))))

At that point, "dev0" contained the process-virtual address of the
device's on-board registers, and "dev0m" pointed to its shared memory
buffers. Peeking (r32) and poking (w32) at those addresses, one could
put the device through all of its paces (except interrupts! -- but every
bit that could cause an interrupt had a corresponding pollable flag bit,
so in practice that wasn't a serious limitation).

+---------------
| You may well be right but I can imagine things like rapidly
| prototyping a new file-system might be fun in Scheme?
+---------------

You can do *that* in user mode, too!  It wasn't in Scheme (would have
been easier had it been!), but when consulting for AMD in the late 80's,
I reimplemented the IBM CMS filesystem (at least well enough to
read/allocate/write CMD "mini-disk" user files with that "interesting"
B-tree filesystem they had) completely in user space under Amdahl's UTS-5.

You can do the same in modern Unixes/Linux, too. Just write a user-mode
NFS daemon (one easy way to hook a user process into the filesystem
dispatch) that munges raw partitions into whatever filesystem you like
(the way database vendors do for performance).

IMHO and IME, anything that *can* be done in user mode *should* be done
in user-mode, at least during development.


-Rob

-----
Rob Warnock, PP-ASEL-IA		<rpw3@rpw3.org>
627 26th Avenue			<URL:http://rpw3.org/>
San Mateo, CA 94403		(650)572-2607