diff -Nru /sys/man/9/0intro /sys/man/9/0intro
--- /sys/man/9/0intro Thu Jan 1 00:00:00 1970
+++ /sys/man/9/0intro Sat Jan 5 00:00:00 2013
@@ -0,0 +1,53 @@
+.TH INTRO 9
+.SH NAME
+intro \- introduction to kernel functions
+.SH DESCRIPTION
+This section of the manual
+describes the functions publicly available to the authors of
+kernel code, particularly device drivers (real and virtual).
+This section will eventually be much expanded, but this makes a start.
+.PP
+The
+.SM SYNOPSIS
+subsections do not show the header files needed for
+the standard kernel declarations.
+The primary combinations summarised below:
+.IP
+.RS
+.ta \w'\fL#include 'u
+.nf
+.B
+#include "u.h"
+.B
+#include "../port/lib.h"
+.B
+#include "mem.h"
+.B
+#include "dat.h"
+.B
+#include "fns.h"
+.B
+#include "../port/error.h"
+.PP
+.I "furthermore, added in IP code:"
+.br
+.B
+#include "../ip/ip.h"
+.PP
+.I "furthermore, in hardware device drivers:"
+.br
+.B
+#include "io.h"
+.br
+.B
+#include "ureg.h"
+.PP
+.I "furthermore, in network interfaces or ether drivers:"
+.B
+#include "../port/netif.h"
+.fi
+.RE
+.PP
+There might also be specific include files needed by
+drivers on particular platforms or to use specialised kernel interfaces.
+The easiest method is to check the source of likely-looking drivers nearby.
diff -Nru /sys/man/9/NOTICE /sys/man/9/NOTICE
--- /sys/man/9/NOTICE Thu Jan 1 00:00:00 1970
+++ /sys/man/9/NOTICE Sat Jan 5 00:00:00 2013
@@ -0,0 +1,2 @@
+Copyright © 1996-2005 Lucent Technologies Inc.
+Portions Copyright © 1999-2005 Vita Nuova Limited
diff -Nru /sys/man/9/allocb /sys/man/9/allocb
--- /sys/man/9/allocb Thu Jan 1 00:00:00 1970
+++ /sys/man/9/allocb Sat Jan 5 00:00:00 2013
@@ -0,0 +1,312 @@
+.TH ALLOCB 9
+.SH NAME
+allocb, iallocb, freeb, freeblist, BLEN, blocklen, concatblock, copyblock, trimblock, packblock, padblock, pullblock, pullupblock, adjustblock, checkb \- data block management
+.SH SYNOPSIS
+.ta \w'\fLBlock* 'u
+.B
+Block* allocb(int size)
+.PP
+.B
+Block* iallocb(int size)
+.PP
+.B
+void freeb(Block *b)
+.PP
+.B
+void freeblist(Block *b)
+.PP
+.B
+long BLEN(Block *b)
+.PP
+.B
+int blocklen(Block *b)
+.PP
+.B
+Block* concatblock(Block *b)
+.PP
+.B
+Block* copyblock(Block *b, int n)
+.PP
+.B
+Block* trimblock(Block *b, int offset, int n)
+.PP
+.B
+Block* packblock(Block *b)
+.PP
+.B
+Block* padblock(Block *b, int n)
+.PP
+.B
+int pullblock(Block **bph, int n)
+.PP
+.B
+Block* pullupblock(Block *b, int n)
+.PP
+.B
+Block* adjustblock(Block *b, int n)
+.PP
+.B
+void checkb(Block *b, char *msg)
+.SH DESCRIPTION
+A
+.B Block
+provides a receptacle for data:
+.IP
+.EX
+.DT
+typedef
+struct Block
+{
+ Block* next;
+ Block* list;
+ uchar* rp; /* first unconsumed byte */
+ uchar* wp; /* first empty byte */
+ uchar* lim; /* 1 past the end of the buffer */
+ uchar* base; /* start of the buffer */
+ void (*free)(Block*);
+ ulong flag;
+} Block;
+.EE
+.PP
+Each
+.B Block
+has an associated buffer, located at
+.BR base ,
+and accessed via
+.B wp
+when filling the buffer, or
+.B rp
+when fetching data from it.
+Each pointer should be incremented to reflect the amount of data written or read.
+A
+.B Block
+is empty when
+.B rp
+reaches
+.BR wp .
+The pointer
+.B lim
+bounds the allocated space.
+Some operations described below accept lists of
+.BR Block s,
+which are
+chained via their
+.B next
+pointers, with a null pointer ending the list.
+.B Blocks
+are usually intended for a
+.B Queue
+(see
+.IR qio (9)),
+but can be used independently.
+.PP
+A
+.B Block
+and its buffer are normally allocated by one call to
+.IR malloc (9)
+and aligned on an 8 byte (\fLBY2V\fP) boundary.
+Some devices with particular allocation constraints
+(eg, requiring certain addresses for DMA) might allocate their own
+.B Block
+and buffer;
+.B free
+must then point to a function that can deallocate the specially allocated
+.BR Block .
+.PP
+Many
+.B Block
+operations cannot be used in interrupt handlers
+because they either
+.IR sleep (9)
+or raise an
+.IR error (9).
+Of operations that allocate blocks, only
+.IR iallocb
+is usable.
+.PP
+.I Allocb
+allocates a
+.B Block
+of at least
+.IR size
+bytes.
+The block
+is initially empty:
+.B rp
+and
+.B wp
+point to the start of the data.
+If it cannot allocate memory,
+.I allocb
+raises an
+.IR error (9);
+it cannot be used by an interrupt handler.
+.PP
+.IR Iallocb
+is similar to
+.IR allocb
+but is intended for use by interrupt handlers,
+and returns a null pointer if no memory is available.
+It also limits its allocation to a quota allocated at system initialisation to interrupt-time buffering.
+.PP
+.I Freeb
+frees a single
+.B Block
+(and its buffer).
+.PP
+.I Freeblist
+frees the whole
+list of blocks headed by
+.IR b .
+.PP
+.I BLEN
+returns the number of unread bytes in a single block
+.IR b ;
+it is implemented as a macro.
+.PP
+.I Blocklen
+returns the number of bytes of unread data in the whole list of blocks headed by
+.IR b .
+.PP
+.I Concatblock
+returns
+.I b
+if it is not a list, and otherwise
+returns a single
+.B Block
+containing all the data in the list of blocks
+.IR b ,
+which it frees.
+.PP
+.I Copyblock
+by contrast returns a single
+.B Block
+containing a copy of the first
+.I n
+bytes of data in the block list
+.IR b ,
+padding with zeroes if the list contained less than
+.I n
+bytes.
+The list
+.I b
+is unchanged.
+.PP
+.I Padblock
+can pad a single
+.B Block
+at either end, to reserve space for protocol headers or trailers.
+If
+.IR n ≥ 0 ,
+it inserts
+.I n
+bytes at the start of the block,
+setting the read pointer
+.B rp
+to point to the new space.
+If
+.IR n < 0 ,
+it adds
+.I n
+bytes at the end of the block,
+leaving the write pointer
+.B wp
+pointing at the new space.
+In both cases, it allocates a new
+.B Block
+if necessary, freeing the old, and
+it always returns a pointer to the resulting
+.BR Block .
+.PP
+.I Trimblock
+trims the list
+.I b
+to contain no more than
+.I n
+bytes starting at
+.I offset
+bytes into the data of the original list.
+It returns a new list, freeing unneeded parts of the old.
+If no data remains, it returns a null pointer.
+.PP
+.I Packblock
+examines each
+.B Block
+in the list
+.IR b ,
+reallocating any block in the list that has four times more available space than actual data.
+It returns a pointer to the revised list.
+.PP
+.I Pullblock
+discards up to
+.I n
+bytes from the start of the list headed by
+.BI * bph \f1.\f0
+Unneeded blocks are freed.
+.I Pullblock
+sets
+.BI * bph
+to point to the new list head
+and returns the number of bytes discarded (which might be less than
+.IR n ).
+It is used by transport protocols to discard ack'd data at
+the head of a retransmission queue.
+.PP
+.I Pullupblock
+rearranges the data in the list of blocks
+.I b
+to ensure that there are at least
+.I n
+bytes of contiguous data in the first block,
+and returns a pointer to the new list head.
+It frees any blocks that it empties.
+It returns a null pointer if there is not enough data in the list.
+.PP
+.I Adjustblock
+ensures that the block
+.I b
+has at least
+.I n
+bytes of data, reallocating or padding with zero if necessary.
+It returns a pointer to the new
+.BR Block .
+(If
+.I n
+is negative, it frees the block and returns a null pointer.)
+.PP
+.I Checkb
+does some consistency checking of
+the state of
+.IR b ;
+a
+.IR panic (9)
+results if things look grim.
+It is intended for internal use by the queue I/O routines (see
+.IR qio (9))
+but could be used elsewhere.
+.PP
+The only functions that can be called at interrupt level are
+.IR iallocb ,
+.IR freeb ,
+.IR freeblist ,
+.IR BLEN ,
+.IR blocklen ,
+.IR trimblock
+and
+.IR pullupblock .
+The others allocate memory and can potentially block.
+.SH SOURCE
+.B /sys/src/9/port/allocb.c
+.SH DIAGNOSTICS
+Many functions directly or indirectly can raise an
+.IR error (9),
+and callers must therefore provide for proper error recovery
+as described therein to prevent memory leaks and other bugs.
+Except for
+.IR iallocb ,
+any functions that allocate new blocks or lists
+are unsuitable for use by interrupt handlers.
+.IR Iallocb
+returns a null pointer when it runs out of memory.
+.SH SEE ALSO
+.IR qio (9)
diff -Nru /sys/man/9/conf /sys/man/9/conf
--- /sys/man/9/conf Thu Jan 1 00:00:00 1970
+++ /sys/man/9/conf Sat Jan 5 00:00:00 2013
@@ -0,0 +1,340 @@
+.TH CONF 9
+.SH NAME
+conf \- native and hosted kernel configuration file
+.SH DESCRIPTION
+Plan 9 kernels are built for a given target
+.I platform
+using platform-specific code in directory
+.BI /sys/src/9/ platform
+and portable code in
+.BR /sys/src/9/port ,
+.B /sys/src/9/ip
+and elsewhere.
+Existing
+.I platforms
+include
+.B alphapc
+for the DEC Alpha,
+.B iPAQ
+for the Compaq iPAQ,
+.B pc
+for the Intel x86,
+and
+.B ppc
+for the IBM/Motorola PowerPC.
+Each
+.I platform
+can have several different kernels with different configurations.
+A given configuration is built in the platform's directory using the
+.IR mk (1)
+command:
+.IP
+.EX
+mk 'CONF=\fIconf\fP'
+.EE
+.PP
+where
+.I conf
+is a text file that specifies drivers, protocols and other parameters for that
+particular kernel:
+a parts list.
+The result of a successful
+.I mk
+is
+an executable or bootable file with a name determined by the
+.IR platform 's
+.BR mkfile ,
+typically
+.BI 9 conf.
+.PP
+A kernel configuration file has several sections of the form
+.IP
+.EX
+.I "label"
+.IR " item" " [ " "subitem ..." " ]"
+\& ...
+.EE
+.PP
+Each section begins with a
+.I label
+at the start of a line, which names a configuration
+category, followed by
+a list of each
+.I item
+to select from that category,
+one line per item, with white space (ie, blank or tab) at the start of the line.
+An
+.I item
+line can optionally list one or more
+.I subitems
+that must be included in the kernel to support it.
+A line that starts with a
+.L #
+is a comment.
+Empty lines are ignored.
+.PP
+.I Labels
+are chosen from the following set, listed in the order
+in which they conventionally appear in a configuration file:
+.TF etherxx
+.TP
+.B dev
+Device drivers
+.TP
+.B ip
+IP protocols (native kernels only) taken from
+.B ../ip
+.TP
+.B link
+Hardware-specific parts of device drivers.
+.TP
+.B misc
+Architecture-specific files; specific VGA and SCSI interfaces
+.TP
+.B lib
+Libraries to link with the kernel
+.TP
+.B port
+C code and declarations to include as-is in the generated configuration file
+.TP
+.B boot
+Configuration for
+.IR boot (8)
+.TP
+.B bootdir
+List of files and directories to put in the
+.B boot
+directory of
+.IR root (3).
+.PD
+.PP
+When an
+.I item
+is listed
+under a given
+.I label
+it causes a corresponding component to be included in the kernel.
+The details depend on the
+.IR label ,
+as discussed below.
+Each
+.I subitem
+represents a kernel subcomponent required by the corresponding
+.IR item .
+Both items and subitems can be either portable (platform-independent)
+or platform-specific.
+The source file for a given item or subitem
+is sought in the platform-directory
+(for platform-specific code), and
+in directories
+.BR ../port
+and
+.BR ../ip ,
+under control of the platform's
+.BR mkfile
+and
+.B ../port/portmkfile
+(which is included by
+.BR mkfile ).
+Resulting object files are left in the
+.I platform
+directory.
+.PP
+Outside the
+.B dev
+section,
+each item and subitem
+.I x
+causes the kernel image to include the code compiled from
+.IB x .c ,
+(or
+.IB x .s
+for assembly-language support),
+or
+.IB portdir / x .c ,
+where
+.I portdir
+is one of the portable directories mentioned above.
+In the
+.B dev
+section, an item
+.I x
+corresponds instead to the driver source file
+.BI dev x .c
+in the current (platform-specific)
+directory or a portable driver
+.IB portdir /dev x .c .
+Subitems are handled as in any other section.
+Typically they are auxiliary files that are needed by the associated driver.
+.PP
+For instance, in a native kernel
+the portable driver for the
+.B draw
+device uses platform-specific code from
+.BR screen.c .
+That can be represented as follows:
+.IP
+.EX
+dev
+ draw screen
+.EE
+.PP
+Each item
+.I x
+in the
+.B ip
+section
+corresponds to a protocol implementation compiled from
+.BI ../ip/ x .c .
+Any subitems
+are dealt with in the same way as in the
+.B dev
+section.
+.PP
+The
+.B link
+section provides a way for hardware-specific
+parts of drivers to link at runtime to the hardware-invariant part of a device
+drivers.
+For each item
+.IR x ,
+the kernel will call the function
+.IB x link
+during its initialisation.
+Typically that function makes itself known to the device driver by
+calling a function provided by that driver,
+passing the address of a interface-specific data structure or linkage table.
+For example,
+.B ethersmc
+is an interface-specific component:
+.IP
+.EX
+link
+ \fR...\fP
+ ethersmc
+.EE
+.PP
+and its source file
+.B ethersmc.c
+provides a function
+.B ethersmclink
+that
+calls
+.B addethercard
+in the interface-invariant part of the driver,
+.BR devether.c :
+.IP
+.EX
+void
+ethersmclink(void)
+{
+ addethercard("smc91cXX", reset);
+}
+.EE
+.PP
+The
+.B boot
+section configures
+.IR boot (8),
+the first user program run by the kernel.
+Each line in the section names a possible boot method (see
+.IR boot (8)
+for the current list).
+The first will be the default.
+Also by default,
+.B /boot
+will run
+.B /bin/termrc
+from
+.IR cpurc (8),
+with
+.B bootdisk
+set to
+.BR #S/sdC0/ .
+To change the defaults, the line (or lines) containing a
+.B boot
+label can be given some options:
+.RS
+.TP
+.B "boot cpu"
+.br
+The kernel is a cpu server: run
+.B /bin/cpurc
+not
+.B /bin/termrc
+(see
+.IR cpurc (8)).
+.TP
+.BI "boot cpu boot " disk
+Use
+.I disk
+as the default
+.BR bootdisk .
+.RE
+.PP
+The
+.B lib
+section lists the libraries to include when linking the kernel,
+in an order that satisfies any dependencies amongst them.
+Each item
+.I x
+corresponds to
+.BI /$objtype/lib x .a ,
+a target-specific library
+produced by compiling the C source code in
+.BI /sys/src/lib item,
+where
+.B objtype
+is set in the platform's
+.B mkfile
+to the target system's object type
+(eg,
+.BR 386 ,
+.BR power ,
+etc).
+.PP
+An item in the
+.B bootdir
+section
+has one of the forms:
+.IP
+.EX
+.I name
+.I "source name"
+.EE
+.PP
+where
+.I name
+and
+.I source
+are path names (often absolute path names).
+The kernel's initial root file system (see
+.IR root (3))
+will contain a file or directory with the given
+.IR name .
+The contents will come from the file
+.I name
+(which must exist) unless an explicit
+.I source
+file is given.
+.PP
+The
+.B port
+section usually contains initialisations for kernel-specific values.
+The most common one is
+.IP
+.EX
+ int cpuserver = \fIn\fP;
+.EE
+.PP
+where
+.I n
+is non-zero for cpu servers and file servers, and zero otherwise.
+.SH FILES
+.B /sys/src/9/port/mkdevc
+.br
+.B /sys/src/9/port/mkdevlist
+.br
+.B /sys/src/9/port/mkroot
+.SH SEE ALSO
+.IR mk (1)
diff -Nru /sys/man/9/delay /sys/man/9/delay
--- /sys/man/9/delay Thu Jan 1 00:00:00 1970
+++ /sys/man/9/delay Sat Jan 5 00:00:00 2013
@@ -0,0 +1,41 @@
+.TH DELAY 9
+.SH NAME
+delay, microdelay, addclock0link \- small delays, clock interrupts
+.SH SYNOPSIS
+.ta \w'\fLvoid 'u
+.B
+void delay(int n)
+.PP
+.B
+void microdelay(int n)
+.PP
+.B
+void addclock0link(void(*clockf)(void))
+.SH DESCRIPTION
+.I Delay
+busy waits for
+.I n
+milliseconds, forced to be at least one millisecond.
+.PP
+.I Microdelay
+is similar, but busy waits for
+.I n
+microseconds.
+.PP
+For delays on the order of clock ticks,
+.I tsleep
+(see
+.IR sleep (9))
+provides a better alternative to the busy waiting of these routines.
+.PP
+.I Addclock0link
+adds
+.I clockf
+to a list of functions to be executed at each clock interrupt on
+the first processor.
+.SH SOURCE
+.B /sys/src/9/port/portclock.c
+.br
+.B /sys/src/9/*/clock.c
+.SH SEE ALSO
+.IR sleep (9)
diff -Nru /sys/man/9/devattach /sys/man/9/devattach
--- /sys/man/9/devattach Thu Jan 1 00:00:00 1970
+++ /sys/man/9/devattach Sat Jan 5 00:00:00 2013
@@ -0,0 +1,699 @@
+.TH DEVATTACH 9
+.SH NAME
+devattach, devclone, devdir, devgen, devwalk, devdirread, devstat, devopen, devbread, devbwrite, devcreate, devremove, devwstat, devreset, devinit, devshutdown, openmode \- common device driver support
+.SH SYNOPSIS
+.nf
+.ta \w'\fLBlock* 'u +10n
+.B
+typedef int
+.B
+Devgen(Chan *c, char *name, Dirtab *tab, int ntab, int i, Dir *dp)
+.PP
+.B
+Chan* devattach(int tc, char *spec)
+.PP
+.B
+Chan* devclone(Chan *c)
+.PP
+.B
+void devdir(Chan *c, Qid qid, char *n, long length,
+.B
+ char *user, long perm, Dir *dp)
+.PP
+.B
+int devgen(Chan *c, char *name, Dirtab *tab, int ntab,
+.B
+ int i, Dir *dp)
+.PP
+.B
+Walkqid* devwalk(Chan *c, Chan *nc, char **name, int nname,
+.B
+ Dirtab *tab, int ntab, Devgen *gen)
+.PP
+.B
+void devstat(Chan *c, uchar *db, int n, Dirtab *tab,
+.B
+ int ntab, Devgen *gen)
+.PP
+.B
+long devdirread(Chan *c, char *d, long n, Dirtab *tab,
+.B
+ int ntab, Devgen *gen)
+.PP
+.B
+Chan* devopen(Chan *c, int omode, Dirtab *tab,
+.B
+ int ntab, Devgen *gen)
+.PP
+.B
+Block* devbread(Chan *c, long n, ulong offset)
+.PP
+.B
+long devbwrite(Chan *c, Block *bp, ulong offset)
+.PP
+.B
+void devcreate(Chan*, char*, int, ulong)
+.PP
+.B
+void devremove(Chan*)
+.PP
+.B
+void devwstat(Chan*, uchar*, int)
+.PP
+.B
+void devreset(void)
+.PP
+.B
+void devinit(void)
+.PP
+.B
+void devshutdown(void)
+.PP
+.B
+int openmode(ulong mode)
+.SH DESCRIPTION
+Device drivers call these functions to carry out essential tasks and default actions.
+They do most of the name space management
+for a driver that serves a simple name space
+(eg, data and control files),
+leaving the driver to concentrate on the device-specific details
+of the I/O requests.
+More complex drivers also make good use of them at the leaves
+of their name space, and to help manage the
+.B Chan
+structures correctly.
+.PP
+A device has an associated
+.IR type ,
+represented as a Unicode character (`rune') that identifies the device
+inside and outside the kernel.
+It appears as the value of the
+.B type
+field in the
+.B Dir
+resulting from a
+.IR stat (2)
+of any file provided by the device.
+A device is named outside the kernel using
+a path name starting with
+.B #
+followed by the device character
+(eg,
+.B c
+in
+.B #c
+for the console).
+Any subsequent characters before
+the next '/' or end of string is the `device specifier',
+interpreted solely by the device itself.
+.PP
+.I Devattach
+returns a new channel representing
+the root of the file tree
+corresponding to device type
+.IR tc ,
+with device specifier
+.IR spec .
+It is normally called by a driver's
+.I attach
+function (see
+.IR dev (9)).
+The
+.B qid
+for the new channel is
+.BR "(Qid){0,0,QTDIR}" ,
+suitable for a root directory for many devices, but
+a device driver is free to change it (provided the
+.B QTDIR
+bit remains in the
+.BR Qid.type ).
+.PP
+.I Devclone
+returns a new channel that is a copy of
+.IR c .
+An attempt to clone an open channel causes a
+.IR panic (9).
+.PP
+The
+.L Dir
+structure is shown below:
+.IP
+.EX
+typedef
+struct Dir
+{
+ /* system-modified data */
+ ushort type; /* server type */
+ uint dev; /* server subtype */
+ /* file data */
+ Qid qid; /* unique id from server */
+ ulong mode; /* permissions */
+ ulong atime; /* last read time */
+ ulong mtime; /* last write time */
+ vlong length; /* file length */
+ char *name; /* last element of path */
+ char *uid; /* owner name */
+ char *gid; /* group name */
+ char *muid; /* last modifier name */
+} Dir;
+.EE
+.PP
+This
+.B Dir
+structure corresponds directly to the Limbo
+.B Dir
+adt described in
+.IR stat (2).
+.PP
+Given a channel and assorted other information,
+.I devdir
+initialises a Dir structure at
+.IR dp .
+.I Devdir
+supplies the following data itself:
+.RS
+.TF length
+.TP
+.B atime
+last access time (set to current time)
+.TP
+.B mtime
+last modification time (set to kernel creation date)
+.TP
+.B gid
+group name (set to
+.IR eve (9))
+.TP
+.B length
+length in bytes (set to zero, which
+is normal for most devices)
+.RE
+.PD
+.PP
+Note that
+.I devdir
+assigns the values of
+.I name
+and
+.I user
+directly to fields of
+.BI * dp,
+and consequently those values must remain valid until the last use of
+.BI * dp.
+(Sometimes that requires the use of an auxiliary buffer, such as
+.BR up->genbuf .)
+If channel
+.I c
+corresponds to a file descriptor on which Styx is served,
+.I devdir
+sets both the flag bit
+.B QTMOUNT
+in
+.IB dp ->qid.type
+and the flag bit
+.B DMMOUNT
+in
+.IB dp ->mode
+(see
+.I export
+in
+.IR dial (2)
+and
+.I mount
+in
+.IR bind (2)).
+.PP
+A simple name space can be represented in a driver by an array of
+.B Dirtab
+structures.
+The array is typically static when the names and permissions
+are static, but can be dynamically allocated and initialised if required.
+The structure of
+.B Dirtab
+is shown below:
+.IP
+.EX
+typedef
+struct Dirtab
+{
+ char name[KNAMELEN];
+ Qid qid;
+ vlong length;
+ long perm;
+} Dirtab;
+.EE
+.PP
+The name
+.RB ` . '
+.I must
+appear as the first entry in a
+.B Dirtab
+if the default
+.I devgen
+function is used.
+On the other hand, the name
+.RB ` .. '
+must never appear in a
+.B Dirtab
+table.
+Drivers that support a directory hierarchy must walk up the hierarchy towards
+the root when their
+.I walk
+function receives
+.RB ` .. '
+as a file name component.
+The name
+.RB ` . '
+is never seen by a driver.
+.PP
+The
+.IR devdirread ,
+.IR devopen ,
+.IR devstat ,
+and
+.IR devwalk
+functions all take a
+.I gen
+function argument,
+of type
+.BR Devgen ,
+which they invoke to retrieve the items in
+a
+.B Chan
+that represents a directory.
+.I Gen
+takes a channel
+.I c
+(a directory),
+a file
+.I name
+(which is nil except during
+.IR devwalk ),
+an array of
+.B Dirtab
+structures
+.I tab
+of length
+.IR ntab ,
+and a table index
+.IR i .
+The functions calling
+.I gen
+expect it to place the
+.IR i 'th
+entry in the directory into
+.IR \f5*\fPdp .
+It should return 1
+if the call was successful,
+-1 if
+.I i
+is beyond the index of the last directory entry,
+or 0 if there is no entry at
+.IR i ,
+but there are entries beyond it.
+When
+.I i
+has the special value
+.B DEVDOTDOT
+then
+.I gen
+should set
+.IR \f5*\fPdp
+to reflect the parent of
+.IR c ;
+if
+.I c
+is a one-level device directory, then `..' is equivalent to `.'.
+Custom implementations of
+.I gen
+often ignore
+.IR devtab ,
+and instead return their own dynamically generated
+set of directory entries from some other source.
+Exceptionally, during
+.I devwalk
+a non-nil
+.I name
+is provided: it is the name being looked up, and a device-specific
+.I gen
+can short-circuit the search by returning -1 if the name does not exist,
+or filling in
+.IR \f5*\fPdp
+and returning 1 if it does exist.
+.PP
+The function
+.I devgen
+is compatible with
+.BR Devgen ;
+it returns the
+.IR i 'th
+entry in
+.IR devtab ,
+and can be used to provide a simple, static
+set of directory entries.
+.PP
+.I Devwalk
+walks channel
+.I c
+to the file in the device named by the path encoded in
+.IR name ,
+which is an array of strings of length
+.IR nname .
+It provides the interface to
+.IR walk (5)
+within the kernel, and that specification must be well understood to appreciate
+all the nuances of its interface.
+Fortunately, in nearly all device drivers, a device's
+.I walk
+function typically passes its parameters on to
+.I devwalk
+(adding the device's own
+.B Dirtab
+array as the the value of
+.IR tab ),
+and simply returning the result of
+.IR devwalk .
+.PP
+.I Devwalk
+walks
+.I c
+using the given set of names, and if the walk is successful, the
+channel
+.I nc
+will refer to the result of the walk
+(specifically,
+.IB nc ->qid
+is set to the Qid for the file).
+If
+.I nc
+is nil,
+.I devwalk
+will allocate a new channel itself, that is initially a clone of
+.IR c .
+As in
+.IR walk (5),
+.I devwalk
+can return a partial result,
+represented by
+a dynamically allocated value of the following structure:
+.IP
+.EX
+struct Walkqid
+{
+ Chan *clone;
+ int nqid;
+ Qid qid[1]; /* actually nname in length */
+};
+.EE
+.PP
+The value must be freed after use.
+For each element of
+.I name ,
+.I devwalk
+passes
+the
+.I tab
+parameter to
+.I gen
+together with the currently-sought element of
+.IR name .
+If the first element is not found,
+.I devwalk
+returns nil; otherwise, it returns a
+.B Walkqid
+value in which
+.B nqid
+elements of the array
+.B qid
+are set to the qids (see
+.IR intro (5))
+of each valid element of
+.IR name .
+If all
+.I nname
+elements were successfully traversed, then
+.B nqid
+will have the value
+.IR nname ,
+and
+.B clone
+will refer to the result of the walk,
+which is either
+.I nc
+if given, or
+the new channel allocated by
+.IR devwalk .
+Otherwise, at least one element succeeded and
+.B nqid
+is less than
+.I nname
+and
+.B clone
+is nil.
+On an error or incomplete walk,
+the error string is set to the error that stopped the walk (eg,
+.B Enonexist
+or
+.BR Enotdir ).
+.PP
+.I Devstat
+fills the array of bytes
+.I db
+with data in the format produced by
+.IR stat (5)
+that describes the file
+referenced by channel
+.IR c ,
+which must have a corresponding entry
+returned by
+.IR gen
+(ie, an entry with matching
+.BR Qid.path ).
+If
+.I c
+is a communications channel connecting a Styx server to a current mount point,
+the
+.B DMMOUNT
+bit is set in the resulting
+.BR Dir.mode ,
+and
+.B QTMOUNT
+is set in
+.BR Dir.qid.type .
+As in
+.IR stat (5),
+the length of the data written to
+.I db
+varies; if more than
+.I n
+bytes are needed,
+.I devstat
+raises the
+.IR error (9)
+.BR Ebadarg .
+Otherwise, it returns the number of bytes in
+.I db
+actually used.
+.PP
+If an entry with the desired qid is not found in the table, but
+.I c
+corresponds to a directory
+(ie,
+.B QTDIR
+is set in
+.IR c\f5->qid.type\fP ),
+it is taken to be a
+.I stat
+of a notional directory containing the files listed in
+.IR tab .
+.I Dirstat
+then builds the corresponding Dir structure:
+its
+.B Dir.name
+is taken from
+.IR c\f5->path->elem\fP ;
+the length is
+.BI DIRLEN*nelem(tab) ;
+and
+.B Dir.perm
+is 0555 (read-execute for all).
+.PP
+.I Devdirread
+calls
+.I gen
+to obtain successive
+.B Dir
+structures representing entries in the open directory
+.IR c .
+These are converted to standard format (see
+.I convD2M
+in
+.IR fcall (2))
+and placed in the buffer
+.IR b .
+It returns the number of bytes in the result.
+At most
+.I n
+bytes will be returned, in multiples of
+.BR DIRLEN .
+Because the kernel maintains the current offset in
+.IR c ,
+successive calls to
+.I devdirread
+return successive directory components.
+.PP
+.I Devopen
+is called to check and complete a request to open channel
+.I c
+for I/O according to
+.IR omode
+(the open mode of
+.IR open (2)).
+It calls
+.I gen
+to obtain successive directory entries
+which it searches
+for a Qid matching that of
+.IR c ,
+and ensures that the current user has permission to open
+.I c
+with the given mode,
+.IR omode ,
+and that the mode itself is valid
+(see
+.I openmode
+below).
+Permission is checked against the permission in the
+matching entry.
+If no matching Qid is found, it is assumed
+that the notional parent directory of the files represented in
+.I tab
+is to be opened.
+Such a directory is deemed to have mode
+0555, allowing access by any user.
+A directory can only be opened for reading
+.RB ( OREAD ).
+.I Devopen
+returns the channel
+.I c
+on success.
+Last, it sets the bit
+.B COPEN
+in
+.B Chan.flag
+to mark
+.I c
+as open.
+This convention can always be relied upon by the driver's
+.I close
+function to tell if an open succeeded.
+On the otherhand,
+if the open request was unsuccessful,
+.I devopen
+raises an appropriate
+.IR error (9)
+and does not return.
+.PP
+.I Devbread
+returns a
+.B Block
+(see
+.IR allocb (9))
+containing up to
+.I n
+bytes read,
+using
+.BI "devtab[" c "->type]->read" ,
+from
+.I c
+starting at the given
+.IR offset .
+The read pointer in the returned
+.B Block
+points to the start of the data;
+the write pointer points to the next available byte.
+.PP
+.I Devbwrite
+writes the data in
+.B Block
+.I bp
+to the file
+.I c
+at the given
+.IR offset ,
+using the write function
+.BI "devtab[" c "->type]->write" .
+It then frees the block list
+.I bp
+before
+returning the number of bytes written.
+.PP
+Most built-in devices do not allow
+.IR create ,
+.IR remove
+or
+.I wstat
+on their files.
+.IR Devcreate ,
+.I devremove
+and
+.I devwstat
+are stubs that raise an
+.IR error (9),
+.BR Eperm .
+They can be named directly in a device driver's device
+switch (the
+.B Dev
+structure in
+.BR /sys/src/9/port/portdat.h :
+see
+.IR dev (9)).
+.PP
+.IR Devreset ,
+.I devinit
+and
+.I devshutdown
+are also stubs;
+they do nothing.
+A device driver puts them in its
+.B Dev
+structure when it need take no action on device reset, initialisation, or shut down.
+.PP
+.I Openmode
+is used by a driver that does not use
+.IR devopen ,
+to check the open mode it receives in its open
+routine.
+.I Openmode
+returns mode
+.IR o ,
+the mode parameter to
+.IR open (2)
+or
+.IR sys-create ,
+shorn of
+.BR OTRUNC
+and similar options,
+and reduced to one of
+.BR OREAD ,
+.BR OWRITE
+or
+.BR ORDWR .
+In particular,
+.B OEXEC
+becomes
+.B OREAD
+within the kernel.
+.I Openmode
+raises an
+.IR error (9)
+.B Ebadarg
+instead of returning, if
+.I o
+is an invalid mode (eg, reserved bits set).
+.SH SOURCE
+.B /sys/src/9/port/dev.c
+.SH SEE ALSO
+.IR allocb (9),
+.IR eve (9),
+.IR qio (9)
diff -Nru /sys/man/9/dmainit /sys/man/9/dmainit
--- /sys/man/9/dmainit Thu Jan 1 00:00:00 1970
+++ /sys/man/9/dmainit Sat Jan 5 00:00:00 2013
@@ -0,0 +1,86 @@
+.TH DMAINIT 9
+.SH NAME
+dmainit, dmasetup, dmadone, dmaend, dmacount \- platform-specific DMA support
+.SH SYNOPSIS
+.ta \w'\fLushort 'u
+.B
+void dmainit(int chan)
+.PP
+.B
+long dmasetup(int chan, void *va, long len, int isread)
+.PP
+.B
+int dmadone(int chan)
+.PP
+.B
+void dmaend(int chan)
+.PP
+.B
+int dmacount(int chan)
+.PP
+.SH DESCRIPTION
+These functions manage DMA on a bus that uses ISA-style DMA controllers.
+They were originally devised for the x86 platform, but the same interface, and similar code,
+is used by other platforms that use similar controllers.
+They compensate as best they can for the limitations of older DMA implementations
+(eg, alignment, boundary and length restrictions).
+There are 8 DMA channels:
+0 to 3 are byte-oriented; 4 to 7 are word-oriented (16-bit words).
+.PP
+.I Dmainit
+must be called early in a driver's initialisation to prepare
+.I chan
+for use.
+Amongst other things, it allocates a page-sized buffer to help circumvent hardware
+restrictions on DMA addressing.
+.PP
+.I Dmasetup
+prepares DMA channel
+.IR chan
+for a transfer between a device configured to use it
+and the virtual address
+.IR va .
+(The transfer is started by issuing a command to the device.)
+If
+.I va
+lies outside the kernel address space,
+the transfer crosses a 64k boundary,
+or exceeds the 16 Mbyte limit imposed by some DMA controllers,
+the transfer will be split into page-sized transfers using the buffer previously allocated by
+.IR dmainit .
+If
+.I isread
+is true (non-zero), data is to be transferred from
+.I chan
+to
+.IR va ;
+if false, data is transferred from
+.I va
+to
+.IR chan .
+In all cases,
+.I dmasetup
+returns the number of bytes to be transferred.
+That value (rather than
+.IR len )
+must be given to the device in the read or write request that starts the transfer.
+.PP
+.I Dmadone
+returns true (non-zero) if
+.I chan
+is idle.
+.PP
+.I Dmaend
+must be called at the end of every DMA operation.
+It disables
+.IR chan ,
+preventing further access to the previously associated memory and,
+if a low-memory buffer was required for input, transfers its contents
+to the appropriate part of the target buffer.
+.PP
+.I Dmacount
+returns the number of bytes that were last transferred by channel
+.IR chan .
+The count is always even for word-oriented DMA channels.
+.SH SOURCE
+.B /sys/src/9/pc/dma.c
diff -Nru /sys/man/9/error /sys/man/9/error
--- /sys/man/9/error Thu Jan 1 00:00:00 1970
+++ /sys/man/9/error Sat Jan 5 00:00:00 2013
@@ -0,0 +1,168 @@
+.TH ERROR 9
+.SH NAME
+error, nexterror, poperror, waserror \- error handling functions
+.SH SYNOPSIS
+.ta \w'\fLchar* 'u
+.B
+void error(char*)
+.PP
+.B
+void nexterror(void)
+.PP
+.B
+void poperror(void)
+.PP
+.B
+int waserror(void)
+.SH DESCRIPTION
+The kernel handles error conditions using non-local gotos,
+similar to
+.IR setjmp (2),
+but using a stack of error labels to implement nested exception handling.
+This simplifies many of the internal interfaces by eliminating the need
+for returning and checking error codes at every level of the call stack,
+at the cost of requiring kernel routines to adhere to a strict discipline.
+.PP
+Each process has in its defining kernel
+.B Proc
+structure a stack of labels,
+.B NERR
+(currently 64) elements deep.
+A kernel function that must perform a clean up or recovery action on an error
+makes a stylised call to
+.IR waserror ,
+.IR nexterror
+and
+.IR poperror :
+.IP
+.EX
+.DT
+if(waserror()){
+ /* recovery action */
+ nexterror();
+}
+/* normal action */
+poperror();
+.EE
+.PP
+When called in the normal course of events,
+.I waserror
+registers an error handling block by pushing its label onto the stack,
+and returns zero.
+The return value of
+.I waserror
+should be tested as shown above.
+If non-zero (true), the calling function should perform the needed
+error recovery, ended by a call to
+.I nexterror
+to transfer control to the next location on the error stack.
+Typical recovery actions include deallocating memory, unlocking resources, and
+resetting state variables.
+.PP
+Within the recovery block,
+after handling an error condition, there must normally
+be a call to
+.I nexterror
+to transfer control to any error recovery lower down in the stack.
+The main exception is in the outermost function in a process,
+which must not call
+.I nexterror
+(there being nothing further on the stack), but calls
+.I pexit
+(see
+.IR kproc (9))
+instead,
+to terminate the process.
+.PP
+When the need to recover a particular resource has passed,
+a function that has called
+.I waserror
+must
+remove the corresponding label from the stack by calling
+.IR poperror .
+This
+must
+be done before returning from the function; otherwise, a subsequent call to
+.I error
+will return to an obsolete activation record, with unpredictable but unpleasant consequences.
+.PP
+.I Error
+copies the given error message, which is limited to
+.B ERRMAX
+bytes, into the
+.B Proc.error
+of the current process,
+enables interrupts by calling
+.I spllo
+.RI ( native
+only),
+and finally calls
+.I nexterror
+to start invoking the recovery procedures currently stacked by
+.IR waserror .
+The file
+.B /sys/src/9/port/error.h
+offer a wide selection of predefined error messages, suitable for almost any occasion.
+The message set by the most recent call to
+.I error
+can be obtained within the kernel by examining
+.B up->error
+and in an application, by using the
+.L %r
+directive of
+.IR print (2).
+.PP
+A complex function can have nested error handlers.
+A
+.I waserror
+block will follow the acquisition of a resource, releasing it
+on error before calling
+.I nexterror,
+and a
+.I poperror
+will precede its release in the normal case.
+For example:
+.IP
+.EX
+.DT
+void
+outer(Thing *t)
+{
+ qlock(t);
+ if(waserror()){ /* A */
+ qunlock(t);
+ nexterror();
+ }
+ m = mallocz(READSTR, 0);
+ if(m == nil)
+ error(Enomem);
+ if(waserror()){ /* B */
+ free(m);
+ nexterror(); /* invokes A */
+ }
+ inner(t);
+ poperror(); /* pops B */
+ free(m);
+ poperror(); /* pops A */
+ qunlock(t);
+}
+.sp 1v
+void
+inner(Thing *t)
+{
+ if(t->bad)
+ error(Egreg); /* error() call returns to B */
+ t->valid++;
+}
+.EE
+.SH SOURCE
+.B /sys/src/9/port/proc.c
+.SH CAVEATS
+The description above has many instances of
+.IR should ,
+.IR will ,
+.I must
+and
+.IR "must not" .
+.SH SEE ALSO
+.IR panic (9)
diff -Nru /sys/man/9/eve /sys/man/9/eve
--- /sys/man/9/eve Thu Jan 1 00:00:00 1970
+++ /sys/man/9/eve Sat Jan 5 00:00:00 2013
@@ -0,0 +1,46 @@
+.TH EVE 9
+.SH NAME
+eve, iseve \- privileged user
+.SH SYNOPSIS
+.ta \w'\fLchar* 'u
+.B
+char eve[NAMELEN] = "bootes";
+.PP
+.B
+int iseve(void)
+.SH DESCRIPTION
+.I Eve
+is a null-terminated string containing the name of the owner of
+the Plan 9 system (sometimes called the `host owner',
+see
+.IR cons (3)).
+The identity is set on a terminal to the name of the user who logs in.
+It is set on a CPU server to the
+.I authid
+obtained either from NVRAM or by a console prompt.
+The initial process created by system initialisation is given the
+.I eve
+identity.
+.PP
+.I Iseve
+returns true if the current user is
+.IR eve .
+Several drivers use
+.I iseve
+to check the caller's identity
+before granting permission to perform certain actions.
+For example, the console driver allows only the user
+.I eve
+to write a new identity into the
+.B /dev/user
+file.
+The privileges are strictly local and do not extend into the network
+(in particular, to file servers—even ones running on the local machine).
+.SH SOURCE
+.B /sys/src/9/port/auth.c
+.SH SEE ALSO
+.IR auth (2),
+.IR cap (3),
+.IR cons (3),
+.IR authsrv (6),
+.IR auth (8)
diff -Nru /sys/man/9/inb /sys/man/9/inb
--- /sys/man/9/inb Thu Jan 1 00:00:00 1970
+++ /sys/man/9/inb Sat Jan 5 00:00:00 2013
@@ -0,0 +1,83 @@
+.TH INB 9
+.SH NAME
+inb, ins, inl, outb, outs, outl, insb, inss, insl, outsb, outss, outsl \- programmed I/O
+.SH SYNOPSIS
+.ta \w'\fLushort 'u
+.B
+int inb(int port)
+.PP
+.B
+ushort ins(int port)
+.PP
+.B
+ulong inl(int port)
+.PP
+.B
+void outb(int port, int value)
+.PP
+.B
+void outs(int port, ushort value)
+.PP
+.B
+void outl(int port, ulong value)
+.PP
+.B
+void insb(int port, void *address, int count)
+.PP
+.B
+void inss(int port, void *address, int count)
+.PP
+.B
+void insl(int port, void *address, int count)
+.PP
+.B
+void outsb(int port, void *address, int count)
+.PP
+.B
+void outss(int port, void *address, int count)
+.PP
+.B
+void outsl(int port, void *address, int count)
+.SH DESCRIPTION
+The
+.I x86
+implementation provides functions to allow kernel code
+written in C to access the I/O address space.
+On several other architectures such as the PowerPC and Strongarm,
+the platform-dependent code provides similar functions to access
+devices with an I/O space interface, even when that is memory mapped, to encourage portability of device drivers.
+.PP
+.IR Inb ,
+.I ins
+and
+.I inl
+apply the corresponding hardware instruction to fetch the next byte, short or long
+from the I/O
+.IR port .
+.IR Outb ,
+.I outs
+and
+.I outl
+output a
+.I value
+to the I/O
+.IR port .
+.PP
+The remaining functions transfer
+.I count
+bytes, shorts, or longs using programmed I/O between a memory
+.I address
+and
+.IR port .
+Functions
+.BI ins x
+copy values into memory; functions
+.BI outs x
+copy values from memory.
+The
+.I count
+is in elements, not bytes.
+.SH SOURCE
+.B /sys/src/9/pc/l.s
+.SH SEE ALSO
+.IR dma (9)
diff -Nru /sys/man/9/intrenable /sys/man/9/intrenable
--- /sys/man/9/intrenable Thu Jan 1 00:00:00 1970
+++ /sys/man/9/intrenable Sat Jan 5 00:00:00 2013
@@ -0,0 +1,106 @@
+.TH INTRENABLE 9
+.SH NAME
+intrenable, intrdisable \- enable (disable) an interrupt handler
+.SH SYNOPSIS
+.ta \w'\fLvoid* 'u
+.B
+void intrenable(int v, void (*f)(Ureg*, void*), void* a, int tbdf, char *name)
+.PP
+.B
+void intrdisable(int v, void (*f)(Ureg*, void*), void* a, int tbdf, char *name)
+.SH DESCRIPTION
+.I Intrenable
+registers
+.I f
+to be called by the kernel's interrupt controller driver each time
+an interrupt denoted by
+.I v
+occurs, and unmasks the corresponding interrupt in the interrupt controller.
+The encoding of
+.I v
+is platform-dependent; it is often an interrupt vector number, but
+can be more complex.
+.I Tbdf
+is a platform-dependent value that might further qualify
+.IR v .
+It might for instance
+denote the type of bus, bus instance, device number and function
+(following the PCI device indexing scheme), hence its name,
+but can have platform-dependent meaning.
+.I Name
+is a string that should uniquely identify the corresponding device (eg, \f5"uart0"\fP);
+again it is usually platform-dependent.
+.I Intrenable
+supports sharing of interrupt levels when the hardware does.
+.PP
+Almost invariably
+.I f
+is a function defined in a device driver to carry out the device-specific work associated with a given interrupt.
+The pointer
+.I a
+is passed to
+.IR f ;
+typically it points to the driver's data for a given device or controller.
+It also passes
+.I f
+a
+.B Ureg*
+value that
+contains the registers saved by the interrupt handler (the
+contents are platform specific;
+see the platform's include file
+.BR "ureg.h" ).
+.PP
+.I F
+is invoked by underlying code in the kernel that is invoked directly from the hardware vectors.
+It is therefore not running in any process (see
+.IR kproc (9);
+indeed, on many platforms
+the current process pointer
+.RB ( up )
+will be nil.
+There are many restrictions on kernel functions running outside a process, but a fundamental one is that
+they must not
+.IR sleep (9),
+although they often call
+.B wakeup
+to signal the occurrence of an event associated with the interrupt.
+.IR Qio (9)
+and other manual pages note which functions are safe for
+.I f
+to call.
+.PP
+The interrupt controller driver does whatever is
+required to acknowledge or dismiss the interrupt signal in the interrupt controller,
+before calling
+.IR f ,
+for edge-triggered interrupts,
+and after calling
+.I f
+for level-triggered ones.
+.I F
+is responsible for deal with the cause of the interrupt in the device, including any
+acknowledgement required in the device, before it returns.
+.PP
+.I Intrdisable
+removes any registration previously made by
+.I intrenable
+with matching parameters, and if no other
+interrupt is active on
+.IR v ,
+it masks the interrupt in the controller.
+Device drivers that are not dynamically configured tend to call
+.I intrenable
+during reset or initialisation (see
+.IR dev (9)),
+but can call it at any appropriate time, and
+instead of calling
+.I intrdisable
+they can simply enable or disable interrupts in the device as required.
+.SH SOURCE
+.B /sys/src/9/*/trap.c
+.SH SEE ALSO
+.IR malloc (9),
+.IR qio (9),
+.IR sleep (9),
+.IR splhi (9)
diff -Nru /sys/man/9/kbdputc /sys/man/9/kbdputc
--- /sys/man/9/kbdputc Thu Jan 1 00:00:00 1970
+++ /sys/man/9/kbdputc Sat Jan 5 00:00:00 2013
@@ -0,0 +1,52 @@
+.TH KBDPUTC 9
+.SH NAME
+kbdputc, kbdq \- keyboard interface to \fIcons\fP(3)
+.SH SYNOPSIS
+.ta \w'\f5extern\ \ \f1'u
+.B
+.B
+void kbdputc(Queue *q, int c)
+.PP
+.B
+extern Queue *kbdq;
+.SH DESCRIPTION
+This is the internal interface between
+.IR cons (3)
+and the platform-dependent keyboard driver.
+Before calling any of these functions,
+the global variable
+.B kbdq
+must be initialised;
+.IR cons (3)
+does not initialise it.
+This is usually done during system initialisation by the keyboard driver's
+.I kbdinit
+or
+.I kbdenable
+function ,
+as follows:
+.IP
+.EX
+kbdq = qopen(4*1024, 0, 0, 0);
+qnoblock(kbdq, 1);
+.EE
+.PP
+.I Kbdputc
+puts a Unicode character
+.I c
+(ie, a `rune')
+on the given
+.IR q ,
+as a sequence of bytes in UTF-8 encoding
+(see
+.IR utf (6)).
+It is up to the platform's keyboard driver to map a physical keyboard character,
+or a combination of them (for instance, following
+.IR keyboard (6))
+to a given Unicode character.
+.SH SOURCE
+.B /sys/src/9/*/kbd*.c
+.SH SEE ALSO
+.IR cons (3),
+.IR utf (6),
+.IR qio (9)
diff -Nru /sys/man/9/kproc /sys/man/9/kproc
--- /sys/man/9/kproc Thu Jan 1 00:00:00 1970
+++ /sys/man/9/kproc Sat Jan 5 00:00:00 2013
@@ -0,0 +1,131 @@
+.TH KPROC 9
+.SH NAME
+kproc, pexit, postnote \- kernel process creation, termination and interrupt
+.SH SYNOPSIS
+.ta \w'\fLchar* 'u
+.B
+void kproc(char *name, void (*func)(void*), void *arg)
+.PP
+.B
+void pexit(char *note, int freemem)
+.PP
+.B
+void postnote(Proc *p, int dolock, char *n, int flag)
+.SH DESCRIPTION
+.I Kproc
+creates a new kernel process
+to run the function
+.IR func ,
+which is invoked as
+.BR "(*func)(arg)" .
+The string
+.I name
+is copied into the
+.B text
+field of the
+.B Proc
+structure of the new process; this value is the name of the kproc in
+the output of
+.IR ps (1).
+The process is made runnable; it
+will run when selected by the scheduler
+.IR sched (9).
+The process is created with base and current priorities set to
+.BR PriKproc .
+It shares the kernel process group and thus name space.
+.PP
+A kernel process terminates only when it calls
+.IR pexit ,
+thereby terminating itself.
+There is no mechanism for one process to force the termination of another,
+although it can send a software interrupt using
+.IR postnote .
+.I Note
+is a null string on normal termination, or
+the cause of
+If
+.I freemem
+is non-zero,
+any memory allocated by the process is discarded;
+it should normally be non-zero for any process created
+by
+.IR kproc .
+Use the following to terminate a kernel process normally:
+.IP
+.EX
+pexit("", 1);
+.EE
+.PP
+to terminate a kernel process normally.
+.PP
+.I Postnote
+sends a software interrupt to process
+.IR p ,
+causing it, if necessary, to wake from
+.IR sleep (9)
+or break out of a
+.IR rendezvous (2),
+with an
+.IR error (9)
+`interrupted'.
+Up to
+.B NNOTE
+notes can be pending at once (currently 5);
+if more than that arrive, the process is forced
+out of
+.I sleep
+and
+.IR rendezvous ,
+but the message itself is discarded.
+.I Postnote
+returns non-zero iff the note has been
+delivered successfully.
+If
+.I dolock
+is non-zero,
+.I postnote
+synchronises delivery of the note with the debugger
+and other operations of
+.IR proc (3).
+.I Flag
+is zero, or one of the following
+.TP
+.B NDebug
+Print the note message on the user's standard error.
+Furthermore, suspend the process in a
+.B Broken
+state, preserving its memory, for later debugging.
+.TP
+.B NExit
+Deliver the note quietly.
+.TP
+.B NUser
+The note comes from another process, not the system.
+.PP
+The kernel uses
+.I postnote
+to signal processes that commit grave faults,
+and to implement the note and kill functions of
+.IR proc (3).
+A device driver should use
+.I postnote
+only to tell a service process,
+previously started by the driver using
+.I kproc ,
+that it should stop;
+the note will cause that process to raise an
+.IR error (9).
+For example, a process started to read packets from a network device could
+be stopped as follows when the interface is unbound:
+.IP
+.EX
+postnote(readp, 1, "unbind", 0);
+.EE
+.PP
+where
+.I readp
+points to the appropriate
+.BR Proc .
+The text of the message is typically irrelevant.
+.SH SOURCE
+.B /sys/src/9/port/proc.c
diff -Nru /sys/man/9/lib /sys/man/9/lib
--- /sys/man/9/lib Thu Jan 1 00:00:00 1970
+++ /sys/man/9/lib Sat Jan 5 00:00:00 2013
@@ -0,0 +1,161 @@
+.TH LIB 9
+.SH NAME
+lib \- C library functions used by the kernel
+.SH SYNOPSIS
+.B
+#include "../port/lib.h"
+.SH DESCRIPTION
+A small collection of functions from the normal Plan 9 C
+library is used in the kernel.
+Only a subset is made available by declarations in
+.BR lib.h ,
+which must be included instead of the usual
+.BR <libc.h> .
+Here is a list of the manual pages, and the functions from them declared
+by
+.B lib.h
+for kernel use:
+.IR
+.TP
+.IR abs (2)
+.br
+.I abs
+.TP
+.IR atof (2)
+.br
+.IR atoi ,
+.IR strtol ,
+.IR strtoul ,
+.IR strtoll ,
+and
+.I strtoull
+.TP
+.IR cleanname (2)
+.br
+.I cleanname
+.TP
+.IR encode (2)
+.IR dec64
+and
+.I encodefmt
+.TP
+.IR fmtinstall (2)
+.br
+.BR Fmt ,
+.IR fmtinstall ,
+.IR fmtprint
+and
+.IR fmtstrcpy
+.TP
+.IR getbe (2)
+.IR getbe ,
+.IR putbe ,
+.IR getle ,
+and
+.I putle
+.TP
+.IR getcallerpc (2)
+.br
+.I getcallerpc
+.TP
+.IR getfields (2)
+.br
+.I getfields
+and
+.I tokenize
+(see also
+.IR parsecmd (9))
+.TP
+.IR quote (2)
+.br
+for
+.IR quotefmtinstall
+.TP
+.IR print (2)
+.br
+.IR print ,
+.IR seprint ,
+.IR snprint ,
+.IR sprint ,
+.IR vseprint
+and
+.IR vsnprint ,
+.TP
+.IR memory (2)
+.br
+.IR memccpy ,
+.IR memchr ,
+.IR memcmp ,
+.IR memmove
+and
+.IR memset
+.TP
+.IR rune (2)
+.br
+.IR chartorune ,
+.IR runetochar ,
+.IR runelen ,
+.IR utflen
+and
+.IR utfrune
+.TP
+.IR open (2)
+.br
+values
+.BR OCEXEC ,
+.BR OEXCL ,
+.BR OEXEC ,
+.BR ORCLOSE ,
+.BR ORDWR ,
+.BR OREAD ,
+.BR OTRUNC
+and
+.BR OWRITE ,
+.TP
+.IR stat (2)
+.br
+data structures
+.BR Dir
+and
+.BR Qid ,
+and values
+.B DMDIR
+etc.
+and
+.B QTDIR
+etc.
+.TP
+.IR strcat (2)
+.br
+.IR strcat ,
+.IR strchr ,
+.IR strcmp ,
+.IR strcpy ,
+.IR strecpy ,
+.IR strlen ,
+.IR strncat ,
+.IR strncmp ,
+.IR strncpy ,
+.IR strrchr
+and
+.IR strstr
+.TP
+.IR wait (2)
+.br
+data structure
+.B Waitmsg
+.PP
+.B lib.h
+also defines
+.B ERRMAX
+(the limit in bytes for error strings)
+and
+.B KNAMELEN
+(fixed-length limit in bytes for device driver file names)
+.PP
+A few other libraries such as
+.IR memdraw (2)
+and
+.IR mp (2)
+are called by specialised kernel components and drivers but they use
+the normal include file for each library.
diff -Nru /sys/man/9/lock /sys/man/9/lock
--- /sys/man/9/lock Thu Jan 1 00:00:00 1970
+++ /sys/man/9/lock Sat Jan 5 00:00:00 2013
@@ -0,0 +1,106 @@
+.TH LOCK 9
+.SH NAME
+lock, canlock, ilock, iunlock, unlock \- spin locks
+.SH SYNOPSIS
+.ta \w'\fLvoid 'u
+.B
+void lock(Lock *l)
+.PP
+.B
+int canlock(Lock *l)
+.PP
+.B
+void unlock(Lock *l)
+.PP
+.B
+void ilock(Lock *l)
+.PP
+.B
+void iunlock(Lock *l)
+.SH DESCRIPTION
+These primitives control access to shared
+resources using spin locks.
+They in turn are used to build higher-level synchronisation mechanisms
+such as those described in
+.IR sleep (9),
+.IR qlock (9)
+and
+.IR qio (9).
+They should be used only to protect short critical sections
+that update shared data structures.
+.PP
+.I Lock
+loops repeatedly attempting acquire the spin lock
+.I l
+until it succeeds.
+.I Lock
+should not be used to lock a structure shared with an interrupt handler
+unless interrupts are disabled by
+.IR splhi (9)
+before attempting the lock;
+it is better to use
+.IR ilock ,
+below.
+.PP
+.I Canlock
+is non-blocking.
+Only one attempt is made for the lock.
+It returns non-zero if the lock was successfully acquired; 0 otherwise.
+.PP
+.I Unlock
+releases the lock
+.IR l .
+A lock must be unlocked only by the locking process.
+.PP
+When called by a process, the functions above temporarily boost its priority
+to the highest priority,
+.BR PriLock ;
+its original priority is restored at the end of the critical section by
+.IR unlock .
+On a uniprocessor, if
+.I l
+is unavailable,
+.I lock
+can reschedule unless interrupts are disabled before entering
+.I lock
+or there is no current process (eg, when executing the scheduler).
+.PP
+.I Ilock
+disables interrupts before attempting to acquire the lock.
+It should be used to lock a resource shared between a process and an interrupt handler.
+On a uniprocessor, disabling interrupts is sufficient to exclude an interrupt handler
+from the critical section,
+and on a multiprocessor the spin lock excludes an interrupt handler running on another processor.
+.I Ilock
+never reschedules the caller, nor must a caller allow itself to be rescheduled
+(eg, by calling
+.IR sleep (9))
+before releasing the lock.
+.PP
+.I Iunlock
+releases a lock previously got by
+.IR ilock .
+.SH SOURCE
+.B /sys/src/9/port/taslock.c
+.br
+.B /sys/src/9/*/l.s
+.SH SEE ALSO
+.IR qlock (9)
+.SH DIAGNOSTICS
+The lock functions
+guard against the possibility of never acquiring the lock by capping the number of lock attempts.
+If the limit is reached, a message of
+the following form is written on the console:
+.IP
+.EX
+lock loop on \fIlock-address\fP key \fIkey-value\fP pc \fIcaller-pc\fP held by pc \fIlock-pc\fP
+.EE
+.PP
+Most lock loops represent deadlocks caused by failing to unlock a resource,
+attempting to lock (eg, by recursive call) a resource already held by the process,
+inconsistent locking and unlocking of nested resources, using a spin-lock
+to guard code that reschedules, using
+.I lock
+not
+.I ilock
+to interlock with an interrupt routine, and similar blunders.
diff -Nru /sys/man/9/malloc /sys/man/9/malloc
--- /sys/man/9/malloc Thu Jan 1 00:00:00 1970
+++ /sys/man/9/malloc Sat Jan 5 00:00:00 2013
@@ -0,0 +1,193 @@
+.TH MALLOC 9
+.SH NAME
+malloc, mallocz, smalloc, realloc, calloc, free, msize, setmalloctag, setrealloctag, getmalloctag, getrealloctag, malloctopoolblock \- kernel memory allocator
+.SH SYNOPSIS
+.ta \w'\fLvoid* 'u
+.B
+void* malloc(ulong size)
+.PP
+.B
+void* mallocalign(ulong size, ulong align, long offset, ulong span)
+.PP
+.B
+void* mallocz(ulong size, int clr)
+.PP
+.B
+void* smalloc(ulong size)
+.PP
+.B
+void* realloc(void *p, ulong size)
+.PP
+.B
+void* calloc(ulong n, ulong szelem)
+.PP
+.B
+void free(void *ptr)
+.PP
+.B
+ulong msize(void *ptr)
+.PP
+.B
+void setmalloctag(void *ptr, ulong tag)
+.PP
+.B
+ulong getmalloctag(void *ptr)
+.PP
+.B
+void setrealloctag(void *ptr, ulong tag)
+.PP
+.B
+ulong getrealloctag(void *ptr)
+.PP
+.B
+void* malloctopoolblock(void*)
+.PP
+.SH DESCRIPTION
+These are kernel versions of the functions in
+.IR malloc (2).
+They allocate memory from the
+.B mainmem
+memory pool,
+which is managed by
+the allocator
+.IR pool (2),
+which in turn replenishes the pool as required by calling
+.IR xalloc (9).
+All but
+.I smalloc
+(which calls
+.IR sleep (9))
+may safely be called by interrupt handlers.
+.PP
+.I Malloc
+returns a pointer to a block of at least
+.I size
+bytes, initialised to zero.
+The block is suitably aligned for storage of any type of object.
+The call
+.B malloc(0)
+returns a valid pointer rather than null.
+.I Mallocz
+is similar, but only clears the memory if
+.I clr
+is non-zero.
+.PP
+.I Smalloc
+returns a pointer to a block of
+.I size
+bytes, initialised to zero.
+If the memory is not immediately available,
+.I smalloc
+retries every 100 milliseconds until the memory is acquired.
+.PP
+.I Mallocalign
+allocates a block of at least
+.I n
+bytes of memory respecting alignment contraints.
+If
+.I align
+is non-zero,
+the returned pointer is aligned to be equal to
+.I offset
+modulo
+.IR align .
+If
+.I span
+is non-zero,
+the
+.I n
+byte block allocated will not span a
+.IR span -byte
+boundary.
+.PP
+.I Realloc
+changes the size of the block pointed to by
+.I p
+to
+.I size
+bytes,
+if possible without moving the data,
+and returns a pointer to the block.
+The contents are unchanged up to the lesser of old and new sizes,
+and any new space allocated is initialised to zero.
+.I Realloc
+takes on special meanings when one or both arguments are zero:
+.TP
+.B "realloc(0,\ size)
+means
+.LR malloc(size) ;
+returns a pointer to the newly-allocated memory
+.TP
+.B "realloc(ptr,\ 0)
+means
+.LR free(ptr) ;
+returns null
+.TP
+.B "realloc(0,\ 0)
+no-op; returns null
+.PD
+.PP
+.I Calloc
+returns a pointer to a block of memory of at least
+.I "n*szelem"
+bytes, initialised to zero.
+New code should use
+.I mallocz
+instead.
+.PP
+The argument to
+.I free
+is a pointer to a block of memory allocated by one of the routines above, which
+is returned to the allocation pool, or a null pointer, which is ignored.
+.PP
+When a block is allocated, sometimes there is some extra unused space at the end.
+.I Msize
+grows the block to encompass this unused space and returns the new number
+of bytes that may be used.
+.PP
+The memory allocator maintains two word-sized fields
+associated with each block, the ``malloc tag'' and the ``realloc tag''.
+By convention, the malloc tag is the PC that allocated the block,
+and the realloc tag the PC that last reallocated the block.
+These may be set or examined with
+.IR setmalloctag ,
+.IR getmalloctag ,
+.IR setrealloctag ,
+and
+.IR getrealloctag .
+When allocating blocks directly with
+.I malloc
+and
+.IR realloc ,
+these tags will be set properly.
+If a custom allocator wrapper is used,
+the allocator wrapper can set the tags
+itself (usually by passing the result of
+.IR getcallerpc (2)
+to
+.IR setmalloctag )
+to provide more useful information about
+the source of allocation.
+.PP
+.I Malloctopoolblock
+takes the address of a block returned by
+.I malloc
+and returns the address of the corresponding
+block allocated by the
+.IR pool (2)
+routines.
+.SH SOURCE
+.B /sys/src/9/port/alloc.c
+.SH DIAGNOSTICS
+All functions except
+.I smalloc
+return a null pointer if space is unavailable.
+If the allocated blocks have no malloc or realloc tags,
+.I getmalloctag
+and
+.I getrealloctag
+return
+.BR ~0 .
+.SH SEE ALSO
+.IR pool (2),
+.IR xalloc (9)
diff -Nru /sys/man/9/newchan /sys/man/9/newchan
--- /sys/man/9/newchan Thu Jan 1 00:00:00 1970
+++ /sys/man/9/newchan Sat Jan 5 00:00:00 2013
@@ -0,0 +1,225 @@
+.TH NEWCHAN 9
+.SH NAME
+newchan, chanfree, cclose, eqqid, eqchan, isdir, fdtochan, namec \- channel operations
+.SH SYNOPSIS
+.ta \w'\fLChan* 'u
+.B
+Chan* newchan(void)
+.PP
+.B
+void chanfree(Chan *c)
+.PP
+.B
+int eqqid(Qid a, Qid b)
+.PP
+.B
+int eqchan(Chan *a, Chan *b, int pathonly)
+.PP
+.B
+void isdir(Chan *c)
+.PP
+.B
+Chan* fdtochan(Fgrp *f, int fd, int mode, int chkmnt, int iref)
+.PP
+.B
+Chan* namec(char *pathname, int amode, int omode, ulong perm)
+.PP
+.B
+void cclose(Chan *c)
+.SH DESCRIPTION
+A value of type
+.B Chan
+represents a kernel channel for I/O and name space operations.
+It has the following public structure:
+.IP
+.EX
+typedef struct Chan{
+ ushort type; /* driver name */
+ ulong dev; /* instance number */
+ ushort mode; /* open mode */
+ ushort flag; /* COPEN set once opened */
+ ulong offset; /* current file offset */
+ Qid qid; /* unique id (path, vers) */
+ Path* path; /* name by which it was accessed */
+.EE
+.PP
+.I Newchan
+returns a pointer to a newly allocated channel (sleeping if necessary until memory is available).
+Device drivers do not normally call
+.IR newchan
+directly, but instead allocate channels using either
+.IR devattach ,
+when a process attaches to the device's root,
+or
+.IR devclone ,
+when an existing channel is cloned;
+see
+.IR devattach (9).
+.PP
+.I Chanfree
+frees the channel structure
+.I c
+for reuse.
+.PP
+.I Eqqid
+returns 1 if
+.B Qid
+values
+.I a
+and
+.I b
+are equal
+(ie,
+both their
+.B path
+and
+.B vers
+members are equal);
+it returns 0 otherwise.
+.PP
+.I Eqchan
+returns 1 if
+.I a
+and
+.I b
+have the same
+.BR qid ,
+.BR type
+and
+.BR dev
+members
+(ie, they represent the same file);
+it returns 0 otherwise.
+If
+.I pathonly
+is non-zero, the comparison of the two
+.B qid
+members compares only their
+.B path
+values,
+ignoring the version field
+.BR vers .
+.PP
+.I Isdir
+checks that a given channel
+.I c
+is a directory.
+If so, it returns;
+otherwise, it generates an
+.IR error (9),
+.BR Enotdir .
+.PP
+The
+.B Fgrp
+structure represents an array of open files, each
+represented by a
+.BR Chan ,
+indexed by integer file descriptors.
+A given
+.B Fgrp
+can be shared between processes.
+.PP
+.I Fdtochan
+returns a pointer to the
+.B Chan
+corresponding to file descriptor
+.I fd
+in file descriptor group
+.I f
+(almost invariably
+.BR up->fgrp ,
+the file descriptor group for the current process).
+If
+.I mode
+is a valid mode for
+.IR open (2),
+typically
+.BR OREAD ,
+.B OWRITE
+or
+.BR ORDWR ,
+it must correspond to the mode with which
+.I fd
+was originally opened; if
+.I mode
+is
+.BR -1 ,
+no check is made.
+If
+.I chkmnt
+is non-zero,
+.I c
+must not be a channel in use by the mount driver
+.IR mnt (3).
+On successful return, if
+.I iref
+is non-zero, the channel's reference count has been incremented.
+.I Fdtochan
+calls
+.IR error (9)
+if it detects invalid uses, in particular an invalid file descriptor
+.IR fd .
+.PP
+.I Namec
+looks up a
+.I pathname
+in the current name space and returns a channel.
+.I Amode
+determines the mode of look up, and must be one of the constants below:
+.TF Aaccess
+.PD
+.TP
+.B Aaccess
+Access file for information, as in the stat command or call.
+.TP
+.B Atodir
+Access file as directory (the
+.B QTDIR
+bit of its
+.B qid.type
+must be set).
+.TP
+.B Aopen
+Access for I/O.
+.TP
+.B Amount
+Access directory to be mounted upon.
+.TP
+.B Acreate
+File is to be created.
+.PP
+If
+.I amode
+is
+.B Aopen
+or
+.BR Acreate ,
+.I omode
+should be a mode suitable for
+.IR open (2);
+if
+.BR Acreate ,
+.I perm
+should be valid file permissions.
+In all other cases,
+.I omode
+and
+.I perm
+can be zero.
+.PP
+.I Cclose
+decrements the reference count on
+.IR c ;
+if no further references remain, it
+calls the corresponding device's
+.B Dev.close
+to close the channel, and frees
+.IR c .
+.SH SOURCE
+.B /sys/src/9/port/chan.c
+.SH DIAGNOSTICS
+Most functions call
+.IR error (9)
+on any sort of error.
+.SH SEE ALSO
+.IR ref (9)
diff -Nru /sys/man/9/panic /sys/man/9/panic
--- /sys/man/9/panic Thu Jan 1 00:00:00 1970
+++ /sys/man/9/panic Sat Jan 5 00:00:00 2013
@@ -0,0 +1,25 @@
+.TH PANIC 9
+.SH NAME
+panic \- abandon hope
+.SH SYNOPSIS
+.ta \w'\fLchar* 'u
+.B
+void panic(char *fmt, ...)
+.SH DESCRIPTION
+.I Panic
+writes a message to the console and
+causes the system to give up the ghost.
+It enables interrupts, dumps the kernel stack,
+and halts the current processor;
+if more than one, others will gradually come to a halt.
+Depending on configuration settings, the platform-dependent
+.I exit
+might reboot the system.
+The format
+.I fmt
+and associated arguments are the same as those for
+.IR print (9).
+.I Panic
+adds a prefix
+.L "panic: "
+and a trailing newline.
diff -Nru /sys/man/9/parsecmd /sys/man/9/parsecmd
--- /sys/man/9/parsecmd Thu Jan 1 00:00:00 1970
+++ /sys/man/9/parsecmd Sat Jan 5 00:00:00 2013
@@ -0,0 +1,107 @@
+.TH PARSECMD 9
+.SH NAME
+parsecmd, cmderror, lookupcmd \- parse device commands
+.SH SYNOPSIS
+.ta \w'\fLCmdbuf* 'u
+.B
+Cmdbuf* parsecmd(char *a, int n)
+.PP
+.B
+void cmderror(Cmdbuf *cb, char *s)
+.PP
+.B
+Cmdtab* lookupcmd(Cmdbuf *cb, Cmdtab *ctab, int nctab)
+.SH DESCRIPTION
+.I Parsecmd
+is an interface to
+.I tokenize
+(see
+.IR getfields (2)),
+that safely parses a command, with blank-separated fields, as might be
+written to a device's
+.B ctl
+file.
+The buffer
+.I a
+and count
+.I n
+can be those passed to the driver's
+.I write
+function.
+.I Parsecmd
+converts the byte array (which might not be null-terminated) to a null-terminated string,
+trimming any trailing new line,
+before invoking
+.I tokenize
+to break the string into arguments, interpreting blank and tab as field separators
+when they are not quoted
+(in the style of
+.IR rc (1)).
+It returns a pointer to a dynamically-allocated
+.B Cmdbuf
+structure,
+which holds a copy of the string as
+modified by
+.IR parsefields ,
+and the resulting fields; it is defined as follows:
+.IP
+.EX
+.ta 6n +\w'char* 'u
+typedef
+struct Cmdbuf
+{
+ char buf[128];
+ char *f[16];
+ int nf;
+} Cmdbuf;
+.EE
+.PP
+The array
+.B f
+holds the field pointers;
+.B nf
+gives the number of fields.
+.B Cmdbuf
+is allocated by
+.I smalloc
+(see
+.IR malloc (9)),
+and the caller is responsible for freeing it using
+.IR free .
+.I Cmderror
+prepends the given format with the original command,
+then calls
+.IR error (9).
+.PP
+Command strings may be turned into a (typically enumerated)
+integer with
+.IR lookupcmd .
+The catchall
+.L *
+matches any text. Unrecognized commands, or commands
+given an unacceptable number of arguments generate a
+call to
+.IR error .
+The definition is as follows
+.IP
+.EX
+.ta 6n +\w'char* 'u
+struct Cmdtab
+{
+ int index;
+ char *cmd;
+ int narg;
+};
+.EE
+.PP
+The integer
+.B index
+is the number returned on command match.
+The string
+.B cmd
+is the command name, and
+.B narg
+is 0 (indicating a varadic function) or the
+number of arguments.
+.SH SOURCE
+.B /sys/src/9/port/parse.c
diff -Nru /sys/man/9/qio /sys/man/9/qio
--- /sys/man/9/qio Thu Jan 1 00:00:00 1970
+++ /sys/man/9/qio Sat Jan 5 00:00:00 2013
@@ -0,0 +1,480 @@
+.TH QIO 9
+.SH NAME
+qio: qget, qdiscard, qconsume, qpass, qproduce, qcopy, qopen, qbread, qread, qbwrite, qwrite, qiwrite, qfree, qclose, qhangup, qreopen, qlen, qwindow, qcanread, qsetlimit, qnoblock, qflush, qfull \- queued I/O for devices
+.SH SYNOPSIS
+.ta \w'\fLQueue* 'u
+.B
+Queue* qopen(int limit,int msg, void (*kick)(void*),void *arg)
+.PP
+.B
+void qhangup(Queue *q, char *reason)
+.PP
+.B
+void qclose(Queue *q)
+.PP
+.B
+void qreopen(Queue *q)
+.PP
+.B
+void qfree(Queue *q)
+.PP
+.B
+long qbwrite(Queue *q, Block *b)
+.PP
+.B
+long qwrite(Queue *q, void *buf, int len)
+.PP
+.B
+int qpass(Queue *q, Block *b)
+.PP
+.B
+int qpassnolim(Queue *q, Block *b)
+.PP
+.B
+int qproduce(Queue *q, void *buf, int len)
+.PP
+.B
+int qiwrite(Queue *q, void *buf, int len)
+.PP
+.B
+Block* qbread(Queue *q, int len)
+.PP
+.B
+long qread(Queue *q, void *buf, int len)
+.PP
+.B
+Block* qcopy(Queue *q, int len, ulong offset)
+.PP
+.B
+Block* qget(Queue *q)
+.PP
+.B
+int qconsume(Queue *q, void *buf, int len)
+.PP
+.B
+int qdiscard(Queue *q, int len)
+.PP
+.B
+void qflush(Queue *q)
+.PP
+.B
+int qlen(Queue *q)
+.PP
+.B
+int qwindow(Queue *q)
+.PP
+.B
+int qcanread(Queue *q)
+.PP
+.B
+void qsetlimit(Queue *q, int limit)
+.PP
+.B
+void qnoblock(Queue *q, int nonblock)
+.PP
+.B
+int qfull(Queue *q)
+.SH DESCRIPTION
+This suite of functions provides serial data buffering for device drivers.
+Data is stored in a
+.B Queue
+structure as a sequence of variable-sized
+.BR Blocks ;
+see
+.IR allocb (9).
+.PP
+.I Qopen
+initialises and returns a pointer to a new
+.BR Queue ,
+configuring it according to the following parameters:
+.TF limit
+.PD
+.TP
+.I limit
+Set the queue limit (high water mark) in bytes.
+.TP
+.I msg
+Set message mode if non-zero; otherwise, stream mode (discussed below).
+.TP
+.I kick
+Optional flow-control function called by
+.I qbread
+to restart writers, and by
+.I qbwrite
+(also
+.IR qiwrite )
+to restart readers.
+.TP
+.I arg
+Argument to pass to
+.I kick
+.PP
+.I Qhangup
+marks
+.I q
+as `hung up'
+for the given
+.IR reason
+.RB ( Ehungup
+by default).
+Subsequent attempts to write to the queue raise an
+.IR error (9).
+.I Qhangup
+does not flush the queue: subsequent read requests are
+handled normally until the queue empties.
+.I Qread
+and the other functions then return their conventional values
+for a hungup stream: 0, -1 or a null pointer, depending on the function.
+After a few such attempts by any process, an
+.IR error (9)
+is raised (typically
+.BR Ehungup )
+on each subsequent read.
+.PP
+If queued data is left unread, and not flushed by
+.I qflush
+or
+.IR qclose ,
+the data will again be readable following a subsequent
+.IR qreopen .
+.PP
+.I Qclose
+also marks a given
+.I q
+as `hung up',
+but removes and frees any queued data Blocks.
+.I Qclose
+ignores calls when
+.I q
+is null.
+.PP
+.I Qreopen
+makes a closed or hung up queue available for use again.
+The queue's data limit is reset to the
+.I limit
+value given when the queue was first created by
+.IR qopen ,
+cancelling the effect of any previous call to
+.IR qsetlimit .
+.PP
+.I Qfree
+closes
+.I q
+with
+.I qclose
+and frees it.
+The caller must ensure that no references remain;
+these functions do not keep a reference count.
+.SS "Flow control"
+The queue I/O routines provide a flow control mechanism to coordinate producers and consumers.
+Each queue has a limit on the number of bytes queued, its `high water mark',
+initially set when the queue is created, but adjustable by
+.IR qsetlimit ,
+below.
+The low water mark is not set explicitly:
+it is always half the current queue limit.
+When the high water mark is exceeded, writes normally block until a reader drains the
+queue below its low water mark; the writer is then allowed to proceed.
+Conversely, readers normally block when the queue is empty, until a writer
+arrives with data, or the queue is closed.
+.PP
+A queue can be given a
+.I kick
+function when the queue is created by
+.IR qopen .
+The function is invoked by
+.IR qread
+and
+.IR qbread ,
+to prod an output routine when the queue falls below the low-water mark, and by
+.IR qwrite ,
+.IR qbwrite
+and
+.IR qiwrite ,
+to notify a reader that a queue is no longer empty.
+Because
+.I kick
+is called from the reading (or writing) process, or an interrupt handler, it
+must not block.
+.PP
+Interrupt handlers must not
+.IR sleep (9),
+and are therefore restricted to using only the non-blocking functions described below.
+.SS "Stream mode and message mode"
+In stream mode,
+no read will return more than one
+block
+of data, but
+a read can split a block that contains more data than requested, leaving the remainder
+in a new block at the front of the Queue.
+Writes of more than the maximum
+.B Block
+size (currently 128k bytes)
+are split into as many Blocks as required, each written separately to the queue,
+in order, but with possible flow-control between them.
+The queue is locked meanwhile, however, so that data from other writers is not intermingled.
+.PP
+In message mode, by contrast, a read will return at most
+one block's worth of data, but the remainder of a partially-read block will be discarded,
+not returned to the queue.
+If a write count exceeds the maximum
+.B Block
+size, the excess data is discarded:
+at most a single block can be queued.
+.PP
+The mode of the queue should be taken into account in the descriptions below
+of the following functions:
+.IR qwrite ,
+.IR qiwrite ,
+.IR qbread
+and
+.IR qconsume .
+No other functions are aware of the distinction.
+.SS "Write operations (flow controlled)"
+.I Qwrite
+copies
+.I len
+bytes of data from
+.I buf
+into one or more
+.B Blocks
+which it places on the
+.IR q .
+.I Qwrite
+always returns
+.IR len .
+It can implement message mode.
+.PP
+.I Qbwrite
+places the single Block
+.I b
+on the tail of
+.IR q ,
+waking any sleeping reader.
+If the queue is full, the
+writing process blocks until a reader
+has reduced the queued data to
+the low-water mark;
+if the queue is non-blocking
+(see
+.I qnoblock
+below),
+the data is discarded without notice.
+.I Qbwrite
+normally returns
+.IR len ,
+but raises an
+.IR error (9)
+if the queue is closed (see
+.I qhangup
+and
+.IR qclose ).
+The block
+.I b
+is always freed.
+Note that
+.I b
+can be empty (zero-length), to punctuate the data in a queue.
+.I Qbwrite
+cannot handle a list of Blocks;
+.I qpass
+must be used instead.
+.SS Non-blocking writes
+.PP
+.I Qproduce
+returns -1immediately if
+.I q
+is full.
+Otherwise, it queues
+.I len
+bytes of data from
+.I buf
+in a single
+.B Block
+on
+.I q
+and returns the number of bytes written.
+.PP
+.I Qpass
+attempts to place the list of Blocks headed by
+.I b
+on
+.IR q ,
+returning the number of bytes written if successful.
+If
+.I q
+was full, it
+frees the Block list
+.I b
+and returns -1.
+.PP
+.I Qpassnolim
+puts the Block list
+.I b
+on
+.I q
+regardless of flow control; it returns the number of bytes in the list
+.IR b .
+.PP
+.I Qiwrite
+is a variant of
+.I qwrite
+used exclusively by the kernel print function,
+to allow printing by interrupt handlers;
+.I qiwrite
+could be used with care by other routines, but
+.IR qproduce
+is preferable.
+.I Qiwrite
+writes the
+.I len
+bytes of data at
+.I buf
+into the
+.I q
+without regard to flow control;
+the writer never blocks.
+The queue is assumed to be open.
+.I Qiwrite
+always returns
+.IR len .
+It can implement message mode.
+.SS "Read operations (flow controlled)"
+.I Qbread
+blocks until data arrives on
+.IR q ,
+then
+returns the first
+.BR Block ;
+it limits the data returned
+to
+.I len
+bytes (in the manner depending on the mode of
+.IR q ).
+It returns a null pointer if the queue has hung up.
+.PP
+.I Qread
+reads a Block of up to
+.I len
+bytes from
+.I q
+using
+.IR qbread ,
+and copies the data in the Block into
+.IR buf ,
+then frees the Block and returns
+the number of bytes read.
+.I Qread
+returns 0 on end of file or error (hangup).
+It can implement message mode.
+.PP
+.I Qcopy
+returns a Block with a copy of data from the queue (the data remains on the queue).
+The copy begins
+.I offset
+bytes into the queue's data and proceeds until
+.I len
+bytes have been copied or no more data remains.
+The Block's read and write pointers delimit the data copied into it.
+.I Qcopy
+can be used by a reliable transport protocol to copy a packet for transmission,
+leaving the data queued for possible retransmission, if unacknowledged.
+.SS Non-blocking reads
+.PP
+.I Qconsume
+returns -1 immediately if
+.I q
+is empty.
+Otherwise, it
+copies up to
+.I len
+bytes from the first
+.B Block
+on the queue into
+.IR buf ,
+returning the number of bytes copied.
+It can implement message mode.
+.PP
+.I Qget
+returns a null pointer immediately if
+.I q
+is empty or closed.
+Otherwise, it
+returns the first
+.B Block
+on the queue.
+.SS "Discard and flush"
+.I Qdiscard
+removes the first
+.I len
+data bytes from
+.IR q ;
+it returns the number of bytes actually discarded, in case
+the queue is shorter than
+.IR len .
+If the queue drains below the low-water mark,
+.I qdiscard
+wakes any sleeping writers.
+Since it does not block,
+.I qdiscard
+can safely be called from interrupt handlers.
+It is useful in transport protocol drivers to remove data from the queue
+once acknowledged.
+.PP
+.I Qflush
+discards all data waiting on
+.IR q ,
+waking any waiting writer.
+.SS "Queue status"
+The following functions return a Queue's status.
+Note that between a call to one of these functions and another operation,
+the state can change if a driver allows concurrent access by
+either another process or an interrupt handler.
+.PP
+.I Qlen
+returns the number of bytes queued on
+.IR q .
+.PP
+.I Qwindow
+returns the number of bytes that can be written before reaching the queue's high-water mark.
+A return of 0 means that a write operation will certainly block;
+a non-zero return gives no guarantees (see
+.IR qfull ,
+below).
+.PP
+.I Qcanread
+returns 1 if any data queued is queued. A subsequent read operation will not block.
+.PP
+.I Qfull
+returns non-zero if
+.I q
+is flow-controlled and a write would block or a non-blocking write would return an error.
+(Note that the implementation allows
+.I qwindow
+to return non-zero yet
+.I qfull
+to return true.)
+.SS "Queue control"
+.I Qsetlimit
+sets the high water mark for the queue to
+.IR limit .
+Note that
+.I qopen
+saves the initial queue limit.
+If the queue is closed and reopened (by
+.IR qreopen )
+that initial limit is restored.
+.PP
+.I Qnoblock
+sets or resets non-blocking mode.
+If
+.I nonblock
+is non-zero,
+the queue becomes non-blocking, and
+data written to a queue beyond its high water mark is discarded
+by calls that would otherwise block.
+.SH SOURCE
+.B /sys/src/9/port/qio.c
+.SH SEE ALSO
+.IR allocb (9),
+.IR ref (9)
diff -Nru /sys/man/9/qlock /sys/man/9/qlock
--- /sys/man/9/qlock Thu Jan 1 00:00:00 1970
+++ /sys/man/9/qlock Sat Jan 5 00:00:00 2013
@@ -0,0 +1,105 @@
+.TH QLOCK 9
+.SH NAME
+qlock, qunlock, canqlock, rlock, runlock, wlock, wunlock \- serial synchronisation
+.SH SYNOPSIS
+.ta \w'\fLvoid 'u
+.B
+void qlock(QLock *l)
+.PP
+.B
+void qunlock(QLock *l)
+.PP
+.B
+int canqlock(QLock *l)
+.PP
+.B
+void rlock(RWlock *l)
+.PP
+.B
+void runlock(RWlock *l)
+.PP
+.B
+int canrlock(RWlock *l)
+.PP
+.B
+void wlock(RWlock *l)
+.PP
+.B
+void wunlock(RWlock *l)
+.SH DESCRIPTION
+The primitive locking functions described in
+.IR lock (9)
+guarantee mutual exclusion, but they implement spin locks,
+and should not be used if the process might
+.IR sleep (9)
+within a critical section.
+The following functions serialise access to a resource by forming an orderly
+queue of processes.
+.PP
+Each resource to be controlled is given an associated
+.B QLock
+structure; it is usually most straightforward to put the
+.B QLock
+in the structure that represents the resource.
+It must be initialised to zero before use
+(as guaranteed for global variables and for structures allocated by
+.IR malloc ).
+.PP
+On return from
+.IR qlock ,
+the process has acquired the lock
+.IR l ,
+and can assume exclusive access to the associated resource.
+If the lock is not immediately available, the requesting process is placed on a
+FIFO queue of processes that have requested the lock.
+Processes on this list are blocked in the
+.L Queueing
+state.
+.PP
+.I Qunlock
+unlocks
+.I l
+and schedules the first process queued for it (if any).
+.PP
+.I Canqlock
+is a non-blocking form of
+.IR qlock .
+It tries to obtain the lock
+.I l
+and returns true if successful, and 0 otherwise;
+it always returns immediately.
+.PP
+.B RWlock
+is a form of lock for resources that have distinct readers and writers.
+It allows concurrent readers but gives each writer exclusive access.
+A caller announces its read or write intentions by choice of lock (and unlock) function;
+the system assumes the caller will not modify a structure accessed under read lock.
+.PP
+.I Rlock
+acquires
+.I l
+for reading.
+The holder can read but agrees not to modify the resource.
+There may be several concurrent readers.
+.I Canrlock
+is non-blocking: it returns non-zero if it successfully acquired the lock immediately,
+and 0 if the resource was unavailable.
+.PP
+.I Runlock
+returns a read lock;
+the last reader out enables the first writer waiting (if any).
+.PP
+.I Wlock
+acquires a write lock.
+The holder of such a lock may assume exclusive access to the resource,
+and is allowed to modify it.
+.PP
+.I Wunlock
+returns a write lock.
+The next pending process, whether reader or writer, is scheduled.
+.SH SOURCE
+.B /sys/src/9/port/qlock.c
+.br
+.SH SEE ALSO
+.IR lock (9),
+.IR splhi (9)
diff -Nru /sys/man/9/readnum /sys/man/9/readnum
--- /sys/man/9/readnum Thu Jan 1 00:00:00 1970
+++ /sys/man/9/readnum Sat Jan 5 00:00:00 2013
@@ -0,0 +1,58 @@
+.TH READNUM 9
+.SH NAME
+readnum, readstr \- return values from read from device
+.SH SYNOPSIS
+.ta \w'\fLchar* 'u
+.B
+int readstr(ulong off, char *buf, ulong n, char *str)
+.PP
+.B
+int readnum(ulong off, char *buf, ulong n, ulong val, int size)
+.SH DESCRIPTION
+.I Readstr
+and
+.I readnum
+simplify the return of strings and numbers from device
+.I read
+routines,
+because they deal with any buffering and boundary cases.
+Several parameters to the read call are often handed on directly
+to these functions:
+the file offset, as
+.IR off ;
+the address of the user's buffer, as
+.IR buf ;
+and the number of bytes requested, as
+.IR n .
+Both functions return the number of bytes they have stored in
+.IR buf ,
+and which can often be returned directly from the device read routine.
+.PP
+.I Readstr
+satisfies a read by copying data into
+.I buf
+from the NUL-terminated string in
+.IR str .
+The data transferred is selected and limited by
+.IR off ,
+.I n
+and the length of
+.IR str .
+.PP
+.I Readnum
+converts the unsigned integer
+.I val
+to a decimal representation in
+.IR buf .
+The value is right-justified in a field of
+.IR size "-1"
+places and is followed by a blank.
+.I Size
+can be the global constant
+.L NUMSIZE
+for 32-bit integers;
+the largest
+.I size
+allowed is 64 bytes.
+.SH SOURCE
+.B /sys/src/9/port/devcons.c
diff -Nru /sys/man/9/ref /sys/man/9/ref
--- /sys/man/9/ref Thu Jan 1 00:00:00 1970
+++ /sys/man/9/ref Sat Jan 5 00:00:00 2013
@@ -0,0 +1,59 @@
+.TH REF 9
+.SH NAME
+Ref, incref, decref \- reference counts
+.SH SYNOPSIS
+.ta \w'\fLchar* 'u
+.PP
+.B
+int incref(Ref *r)
+.PP
+.B
+int decref(Ref *r)
+.SH DESCRIPTION
+A
+.B Ref
+structure holds a reference count for a data structure:
+.IP
+.EX
+typedef struct
+struct Ref
+{
+ Lock;
+ long ref;
+} Ref;
+.EE
+.PP
+The reference count proper is found in
+.BR ref ;
+the
+.B Lock
+prevents concurrent updates
+(see
+.IR lock (9)).
+.PP
+.I Incref
+atomically increments the reference count
+.IR r ,
+and returns the new count.
+.PP
+.I Decref
+atomically decrements the reference count
+.IR r ,
+and returns the new count.
+.SH EXAMPLES
+Release a structure containing a
+.B Ref
+on last use.
+.IP
+.EX
+if(decref(s) == 0)
+ free(s);
+.EE
+.SH SOURCE
+.B /sys/src/9/port/chan.c
+.SH DIAGNOSTICS
+.I Decref
+will
+.IR panic (9)
+if the count goes negative,
+revealing a reference counting bug.
diff -Nru /sys/man/9/seconds /sys/man/9/seconds
--- /sys/man/9/seconds Thu Jan 1 00:00:00 1970
+++ /sys/man/9/seconds Sat Jan 5 00:00:00 2013
@@ -0,0 +1,93 @@
+.TH SECONDS 9
+.SH NAME
+seconds, ticks, fastticks, HZ, MS2HZ, MS2TK, TK2MS, TK2SEC \- kernel times and time conversions
+.SH SYNOPSIS
+.ta \w'\fL#define 'u
+.B
+long seconds(void)
+.PP
+.B
+m->ticks
+.br
+MACHP(0)->ticks
+.PP
+.B
+vlong fastticks(uvlong *hz)
+.PP
+.EX
+#define HZ ...
+#define MS2HZ(t) ...
+#define TK2SEC(t) ...
+#define TK2MS(t) ...
+#define MS2TK(m) ...
+.EE
+.SH DESCRIPTION
+.I Seconds
+returns the system's idea of the current time as the number of seconds
+since the start of the epoch
+(00:00:00 GMT, January 1, 1970).
+.PP
+The
+.B ticks
+field of the
+.B Mach
+structure pointed to by
+.B m
+returns the number of system-dependent clock ticks on the
+given processor since system boot.
+On a multiprocessor,
+.B MACHP(0)
+is sometimes used to provide a reference time, since the tick value
+might vary slightly across processors.
+.PP
+.I Fastticks
+returns the number of ticks since boot as measured by the
+fastest clock provided by the platform.
+The frequency of the clock, in ticks per second,
+is returned through
+.IR hz ,
+unless it is nil.
+.PP
+The system clock frequencies are platform-dependent.
+Several symbolic constants and macro functions are defined by
+the file
+.B mem.h
+to convert between different time units:
+.TF TK2SEC(t)
+.PD
+.TP
+.B HZ
+The number of clock ticks per second.
+.TP
+.B MS2HZ
+Milliseconds per clock tick.
+.TP
+.BI TK2SEC( t )
+Convert
+.I t
+clock ticks to seconds and return the result (truncating not rounding).
+.TP
+.BI TK2MS( t )
+Convert
+.I t
+clock ticks to milliseconds and return the result.
+.TP
+.BI MS2TK( m )
+Convert
+.I m
+milliseconds to clock ticks and return the result (truncating).
+.PP
+The functions are often used to calculate delays for timing functions,
+for instance:
+.IP
+.EX
+if(atactlrwait(dp->cp, DHmagic, 0, MS2TK(100))){
+ ...
+}
+.EE
+.SH SOURCE
+.B /sys/src/9/*/mem.h
+.br
+.B /sys/src/9/*/clock.c
+.br
+.B /sys/src/9/port/tod.c
diff -Nru /sys/man/9/sleep /sys/man/9/sleep
--- /sys/man/9/sleep Thu Jan 1 00:00:00 1970
+++ /sys/man/9/sleep Sat Jan 5 00:00:00 2013
@@ -0,0 +1,123 @@
+.TH SLEEP 9
+.SH NAME
+sleep, wakeup, tsleep, return0 \- process synchronisation
+.SH SYNOPSIS
+.ta \w'\fLvoid 'u
+.B
+void sleep(Rendez *r, int (*f)(void*), void *arg)
+.PP
+.B
+void wakeup(Rendez *r)
+.PP
+.B
+void tsleep(Rendez *r, int (*f)(void*), void *arg, int ms)
+.PP
+.B
+int return0(void *arg)
+.PP
+.SH DESCRIPTION
+A process running in the kernel can use these functions to
+synchronise with an interrupt handler or another kernel process.
+In particular, they are used by device drivers to wait for an event to be signalled on
+receipt of an interrupt.
+(In practice, they are most often used indirectly, through
+.IR qio (9)
+for instance.)
+.PP
+The caller of
+.I sleep
+and a caller of
+.I wakeup
+share a
+.B Rendez
+structure, to provide a rendezvous point between them
+to synchronise on an event.
+.I Sleep
+uses a condition function
+.I f
+that returns true if the event has occurred.
+.PP
+.I Sleep
+evaluates
+.IB f ( arg ).
+If true, the event has happened and
+.I sleep
+returns immediately.
+Otherwise,
+.I sleep
+blocks on the event variable
+.IR r ,
+awaiting
+.IR wakeup .
+.PP
+.I Wakeup
+is called by either a process or an interrupt handler to wake any process
+sleeping at
+.IR r ,
+signifying that the corresponding condition is true (the event has occurred).
+It has no effect if there is no sleeping process.
+.PP
+.I Tsleep
+is similar to
+.IR sleep ,
+except that if the condition
+.IB f ( arg )
+is false and the caller does sleep,
+and nothing else wakes it within
+.I ms
+millliseconds,
+the system will wake it.
+.IR Tsleep 's
+caller must check its environment to decide whether timeout or the event
+occurred.
+The timing provided by
+.I tsleep
+is imprecise, but adequate in practice for the normal use of protecting against
+lost interrupts and otherwise unresponsive devices or software.
+.PP
+.I Return0
+ignores its arguments and returns zero. It is commonly used as
+the predicate
+.I f
+in a call to
+.I tsleep
+to obtain a time delay, using a
+.B Rendez
+variable
+.B sleep
+in the
+.B Proc
+structure, for example:
+.IP
+.B tsleep(&up->sleep, return0, nil, 10);
+.PP
+Both
+.I sleep
+and
+.I tsleep
+can be interrupted by
+.IR swiproc
+(see
+.IR kproc (9)),
+causing a non-local goto through a call to
+.IR error (9).
+.SH SOURCE
+.B /sys/src/9/port/proc.c
+.SH DIAGNOSTICS
+There can be at most one process waiting on a
+.BR Rendez ,
+and if two processes collide, the system will
+.IR panic (9)
+.RB (`` "double sleep" '').
+Access to a
+.B Rendez
+must therefore be serialised by some other mechanism, usually
+.IR qlock (9).
+.SH SEE ALSO
+.IR lock (9),
+.IR qlock (9),
+.IR delay (9)
+.br
+``Process Sleep and Wakeup on a Shared-memory Multiprocessor'',
+in
+.I "Plan 9 Programmer's Manual: Volume 2".
diff -Nru /sys/man/9/splhi /sys/man/9/splhi
--- /sys/man/9/splhi Thu Jan 1 00:00:00 1970
+++ /sys/man/9/splhi Sat Jan 5 00:00:00 2013
@@ -0,0 +1,57 @@
+.TH SPLHI 9
+.SH NAME
+splhi, spllo, splx, islo \- enable and disable interrupts
+.SH SYNOPSIS
+.ta \w'\fLvoid 'u
+.B
+int spllo(void)
+.PP
+.B
+int splhi(void)
+.PP
+.B
+void splx(int x)
+.PP
+.B
+int islo(void)
+.SH DESCRIPTION
+These primitives enable and disable maskable interrupts on the current
+processor.
+Generally, device drivers should use
+.I ilock
+(see
+.IR lock (9)),
+.IR sleep (9),
+or the functions in
+.IR qio (9)
+to control interaction between processes and interrupt handlers.
+Those routines (but not these) provide correct synchronisation on multiprocessors.
+.PP
+.I Spllo
+enables interrupts and returns a flag representing the previous interrupt enable state.
+It must not normally be called from interrupt level.
+.PP
+.I Splhi
+disables all maskable interrupts and returns the previous interrupt enable state.
+The period during which interrupts are disabled had best be short,
+or real-time applications will suffer.
+.PP
+.I Splx
+restores the interrupt enable state
+state to
+.IR x ,
+which must be a value returned
+by a previous call to
+.I splhi
+or
+.IR spllo .
+.PP
+.I Islo
+returns true (non-zero) if interrupts are currently enabled, and 0 otherwise.
+.SH SOURCE
+.B /sys/src/9/*/l.s
+.SH SEE ALSO
+.IR lock (9),
+.IR qio (9),
+.IR sleep (9),
+.IR intrenable (9)
diff -Nru /sys/man/9/uartp8250 /sys/man/9/uartp8250
--- /sys/man/9/uartp8250 Thu Jan 1 00:00:00 1970
+++ /sys/man/9/uartp8250 Sat Jan 5 00:00:00 2013
@@ -0,0 +1,77 @@
+.TH UARTP8250 9
+.SH NAME
+uartp8250 \- portable 8250-style uarts
+.SH SYNOPSIS
+.EX
+#include "../port/uartp8250.h"
+
+typedef struct Ctlr Ctlr;
+struct Ctlr {
+ void *reg;
+ uint (*get)(void*, int);
+ void (*set)(void*, int, uint);
+ int (*itr)(Uart*, int);
+
+ int irq;
+ int tbdf;
+ int iena;
+
+ uchar sticky[8];
+
+ Lock;
+ int hasfifo;
+ int checkfifo;
+ int fena;
+};
+.EE
+.PP
+.ta \w'\fLPhysUart 'u
+.PP
+.B
+PhysUart p8250physuart;
+.PP
+.B
+void i8250interrupt(Ureg*, void*);
+.SH DESCRIPTION
+P8250 provides a portable interface for 8250-style uarts.
+All necessary functions are provided except for
+.BR get ,
+.BR set ,
+and
+.BR itr .
+These functions get or set an 8250 register or enable
+or disable the interrupt, respectively. Since the
+.B PhysUart
+structure is required for device discovery, a dummy
+version needs to be provided
+.IP
+.EX
+PhysUart myphysuart = {
+ .name = "myuart",
+ .pnp = mypnp,
+};
+.EE
+.PP
+On entry of the pnp function, the
+.B PhysUart
+can be filled out:
+.EX
+ memmove(&myphysuart, &p8250physuart, sizeof(PhysUart));
+ myphysuart.name = "myuart";
+ myphysuart.pnp = mypnp;
+.EE
+.PP
+as can the
+.B Ctlr
+structure, which is assigned to
+.BR "uart->regs" .
+.SH SOURCE
+.B /sys/src/9/port/uartp8250.h
+.br
+.B /sys/src/9/port/uartp8250.c
+.SH "SEE ALSO"
+.IR uart (3).
+.SH BUGS
+The
+.B PhysUart
+is uncomfortable to use for device discovery.
diff -Nru /sys/man/9/xalloc /sys/man/9/xalloc
--- /sys/man/9/xalloc Thu Jan 1 00:00:00 1970
+++ /sys/man/9/xalloc Sat Jan 5 00:00:00 2013
@@ -0,0 +1,72 @@
+.TH XALLOC 9
+.SH NAME
+xalloc, xspanalloc, xfree \- basic memory management
+.SH SYNOPSIS
+.ta \w'\fLvoid* 'u
+.B
+void* xalloc(ulong size)
+.PP
+.B
+void* xspanalloc(ulong size, int align, ulong span)
+.PP
+.B
+void xfree(void *p)
+.SH DESCRIPTION
+.I Xalloc
+and
+.I xfree
+are primitives used by higher-level memory allocators in the kernel,
+such as
+.IR malloc (9).
+They are not intended for use directly by most kernel routines.
+The main exceptions are routines that permanently allocate large structures,
+or need the special alignment properties guaranteed by
+.IR xspanalloc .
+.PP
+.I Xalloc
+returns a pointer to a range of size bytes of memory. The memory will be zero filled and aligned on a 8 byte
+.RB ( BY2V )
+address. If the memory is not available,
+.B xalloc
+returns a null pointer.
+.PP
+.I Xspanalloc
+allocates memory given alignment and spanning constraints.
+The block returned will contain
+.I size
+bytes, aligned on a boundary that is
+.BI "0 mod" " align,"
+in such a way that the memory in the block does not
+span an address that is
+.BI "0 mod" " span."
+.I Xspanalloc
+is intended for use
+allocating hardware data structures (eg, page tables) or I/O buffers
+that must satisfy specific alignment restrictions.
+If
+.I xspanalloc
+cannot allocate memory to satisfy the given constraints, it will
+.IR panic (9).
+The technique it uses can sometimes cause memory to be wasted.
+Consequently,
+.I xspanalloc
+should be used sparingly.
+.PP
+.I Xfree
+frees the block of memory at
+.IR p ,
+which must be an address previously returned by
+.I xalloc
+(not
+.IR xspanalloc ).
+.SS Allocation status
+Some memory allocation statistics are written to the console in response to
+the debugging sequence
+.LR "control-T control-T x" .
+The output includes the total free space, the number of free holes,
+and a summary of active holes.
+Each line shows `address top size'.
+.SH SOURCE
+.B /sys/src/9/port/xalloc.c
+.SH SEE ALSO
+.IR malloc (9)
|