ne device driver

This document applies to r2.0 of the ne device driver.

QUICK START (using defaults for one card only):

--- note --- type the exact keystrokes listed.


1. Install one NE2000 compatible ethernet card with jumpers set
to IRQ 10 and IO Base 0x300.

2. While logged in as superuser, change directory to
/etc/conf/ne/src and command:
	neinstall<enter>

3. When installer screen comes up, hit <enter> twice to speed
past the opening installer screens, then type:
	bsbb

(DO NOT HIT ENTER YET. Let the installer build some files,
and build a new kernel first.)

4. When kernel is built, read the message box, then hit <enter>
to quit.

--------

The ne device driver is a traditional Coherent CON style
driver for NE1000 and NE2000 compatible ethernet boards.
The driver is both simple and very fast. The NE style board
is characterized by port rather than memory based io and
jumpers to configure hardware parameters.

The driver has a major number of 19 and minor numbers of 0
and 1 are available as supplied. In the distribution, only
one card has default hardware parameters. This will be 
generally be accessed by character special file /dev/ne0
with major number 19 and minor number 0. The default IRQ
is 10 and the default io base is 0x300. Of course, the
device driver IRQ and io base MUST match the jumper settings
on your ethernet card. The driver does not care which
physical medium you use (eg: 10baseT, 10base2, 10base5).
These are dependant on the type of hardware you have
purchased.  In addition, the driver works only with
regular "Blue book" ethernet packets and does not handle
IEEE 802.3

----
A full screen installation program binary has been developed and
included with the driver. It reduces the installation process to
3 steps and includes help screens to guide the installer. Every 
attempt has been made to make the ne installation as close to 
'plug and play' as is possible. The program is called neinstall.

To do the installation, the installer must know the IRQ and IOBASE
numbers that correspond to the jumper (or switch) settings on the
ethernet hardware. Each card must have a unique IRQ and IOBASE that
do not conflict with any other hardware on the system.

The default installation is for one ethernet card using IRQ 10,
and IOBASE of 0x300. Use of these default settings on hardware
jumpers will allow the user complete installation by invoking
the Build menu's Space selection, followed by the Build menu's
Build selection. This will allow a complete software installation
with only 8 keystrokes and will require less than 5 minutes.

neinstall creates /etc/conf/ne/Space.c and calls the system
scripts to enable the driver and build a kernel. It also
creates the device special files. A successful installation
of hardware and software will result in a boot time banner
that tells the ethernet address of the hardware.

----

Technical stuff:

Upon boot up, the driver tests for the existance of an
NE compatible ethernet card at 0x300. The driver is able
to automatically determine whether the card is an 8 bit 
NE1000 compatible or a 16 bit NE2000 compatible board. If
a working card is found the ethernet address will be extracted
and announced in the boot up messages. However, interrupts
on the card will remain disabled until the card is 'opened'.

read(), write() and poll():

The ne device driver deals with data in complete ethernet
packets only. That is, the sending software must supply a
packet suitable for sending on ethernet, complete with a
source and destination address and protocol descriptor.
The sent packet must be at least 64 bytes long and no more
than 1500 bytes long, including all headers. It must be
contiguous .. that is, it cannot be scattered about memory
in various mbufs or similar fragments. The fragments
must be gathered into a single buffer for the call
to write().

The following is an ethernet header as defined in neioctl.h:

struct ether_header {
	unsigned char ether_dhost[6];
	unsigned char ether_shost[6];
	unsigned short ether_type;
	};

ether_dhost is a 6 byte ethernet address for the destination machine.
ether_shost is a 6 byte ethernet address for the source machine.
ether_type is the protocol descriptor that tells the protocol software
how to process the packet.

A packet is transmited by using write() and received packets
are collected by read(). Poll is supported for data recieved
and space available for outgoing data. No priority polls are
available. There is a watchdog timeout mechanism, so be sure
to check the return values of both read and write because it
is quite possible for a timeout to occur on a loaded network.

The user buffer into which a received packet is collected should
be no less than 1536 bytes and the read should always ask for 1536
bytes. read() will return the actual number of bytes transfered
to the user buffer which will always be the contents of 1 full
packet including the ethernet header.

ne does not demultiplex packets, therefore, it should be used
with only one protocol suite at a time unless arrangements are
made to demulitplex packets based on protocol descriptors.

ioctl() calls:
The constants and structs for ioctls for ne are listed in neioctl.h.

	/* ioctl commands */
struct arpcom {
	unsigned char ac_enaddr[6];
	unsigned short if_flags;
	char *acc_if;
	};

NEIOCGFLAGS is used to get the flags and NEIOCSFLAGS is used to set
the flags. These flags control "promiscous" mode for the ethernet driver.
If you set it to promiscous mode, it will receive all ethernet packets
on the network no matter who they are addressed to. This is useful
for network monitoring and gateway systems. In non-promiscous mode,
only packets addressed to this ethernet controller and broadcast packets
are received.

The following code fragment illustrates turning off promiscous mode.

struct arpcom myaprcom;

	/* get flags */
ioctl( fd, NEIOCGFLAGS, &myarpcom );
	/* turn off promiscous bit */
myarpcom.if_flags &= ~IFF_PROMISC;
	/* set flags */
ioctl( fd, NEIOCSFLAGS, &myarpcom );


The NEIOCGSTATS command is used to retreive a copy of the statistics
kept by the driver for each board. The struct nestats is used as the
third argument to the ioctl(). The following code fragment illustrates
the method for getting statistics from the device driver:

struct nestats mynestats;

	/* download the stats */
ioctl( fd,  NEIOCGSTATS, &mynestats );

	/* display them */
printf( "number of collisions       : %d\n", mynestats.nestat_collisions );
printf( "number of xmit errors      : %d\n", mynestats.nestat_oerrors );
printf( "number of recv errors      : %d\n", mynestats.nestat_ierrors );
printf( "xmitted packets            : %d\n", mynestats.nestat_opackets );
printf( "recv'd packets             : %d\n", mynestats.nestat_ipackets );
printf( "incoming packets discarded : %d\n", mynestats.nestat_idiscards );
printf( "xmit buffer supply         : %d\n", mystats.nestat_lox);
printf( "recv buffer supply         : %d\n", mystats.nestat_lor);

Note: "nestat_lox" and "nestat_lor" are used to determine how well
the buffering is working. These values are the lowest number available
packet buffers since the last call to this ioctl. If the value is
equal to the number of buffers (default is 16), then the device driver
has not had to dip into its buffer cache in order to handle the traffic.
If the value is equal to low-water as returned by the next ioctl() the 
driver is in danger of buffer starvation. "nestat_lox" and "nestat_lor"
are both reset to the number of buffer in the cache when this ioctl()
is called, so the value returned is a reflection of what has occured
since the last call to this ioctl().

NEIOCGLOWWAT and NEIOCSLOWWAT are used to get and set the low water
figure used in send buffer flow control. The third argument in the
ioctl is a neattr_t which is currently defined as an int. To understand
how ne performs flow control, you need to realize that ne uses fixed
length, static buffers and avoids turning off interrupts while
transfering data from the user area into the transmit queue. This
is because the hardware has only a single transmit buffer. The low water
maker is in terms of packets, not bytes. It should be no less than 2,
in order to keep from overwriting the buffer that is currently being
loaded into the tranmitter, however, in some circumstances, the
protocol software can queue up a number of packets for tranmission
faster than the hardware can send packets. In this case, the
low water mark can be set to a greater level. It represents the
minimum number of available transmission buffers before more
packets will be accepted via a write() call. Most users will
never need to use this feature.

-------

Modifying the source code:

A competent device driver programmer will be able to easily alter
the ne.c source code file to do such things as increase or decrease
the number of static packet buffers or the number of cards supported.

A device driver on a gateway between networks of radically different
speeds or loads may benefit from substantially increased numbers of
packet buffers. Since static buffers use ram whther a card is present
or not, it is wise to change the source code to reflect the real
number of cards present if a large amount of buffering is to be used.

-------
