A P P E N D I X  B

Software Functional Description

This appendix contains a functional description of the SunHSI/S 3.0 software.


Software Initialization

The SunHSI/S 3.0 driver software is dynamically loadable and unloadable to help conserve memory resources. During software installation, the driver is installed to the system with add_drv(1m) , which temporarily loads the driver into the kernel and uses the attach routine of the driver to dynamically create the device nodes for each hardware instance installed. This autoconfiguration feature is provided in the Solaris software, and it is also supported in the SunHSI/S 3.0 driver software.

After the autoconfiguration, the module is unloaded. The driver module is loaded to the system again when the driver is first referenced. The autoconfiguration and initialization of the SunHSI/S driver software is performed through a set of standard SBus device driver routines:

static int hsidentify (dev_info_t *dip)

This routine is called at initialization time to find out whether the driver controls the device specified by parameter dip . The driver compares ddi_get_name(9E) with a hard-coded string "HSI" with strcmp(3C) . This routine returns the DDI_IDENTIFIED message if both strings match. Otherwise, the DDI_NOT_IDENTIFIED message is returned.

static int hsprobe (dev_info_t *dip)

This routine is called at initialization when the calling of hsidentify succeeded. Since SunHSI/S hardware is a self-identifying device, the system performs the probe function. This routine always returns the DDI_PROBE_SUCCESS message.

static int hsattach (dev_info_t *dip, ddi_attach_cmd_t cmd)

This routine is called at autoconfiguration time when the driver module is loaded into the system and the calling of hsprobe routine succeeded. It calls the protocol-dependent routine hih_attach to create device nodes that the driver needs to access the hardware and hih_init to set up a control structure for each port on the board.

The structure includes information such as hardware address, transmission state, minor number, and port configuration parameters. The hsattach routine also calls the standard DDI routines to map SunHSI/S hardware registers and to add device interrupt service routine to the kernel.

static int hsdetach (dev_info_t *dip, ddi_detach_cmd_t cmd)

This routine is called when the driver module is unloaded from the system. It calls the protocol-dependent routine hih_detach to remove the device node and reset the hardware. It also calls standard DDI routines to un-map the hardware registers and delete the device interrupt service routine from the system.


External Interfaces

The SunHSI/S 3.0 driver provides a streams-based interface to the Solaris kernel and user program. The driver software can be reached from the user program through standard open(2) , close(2) , putmsg(2) , getmsg(2 ), and ioctl(2) system calls. The driver software communicates with other kernel resident (upper protocol) streams modules using the standard utility putnext(9F) .

The driver software can also be reached through hardware interrupts from the SunHSI/S hardware. Hardware interrupts, both standard serial control interrupts and on-chip DMA interrupts, are received through the SunHSI/S hardware from the Integrated Serial Communications Controller (ISCC).

The SunHSI/S driver software interface diagram, shown in FIGURE B-1 , shows the external interfaces of the driver.

FIGURE B-1 SunHSI/S 3.0 Driver Software Interface


IOCTLs

All driver control is achieved through IOCTL system calls (refer to the ioctl(2) man page for more information). TABLE B-2 lists the IOCTL parameters for the SunHSI/S Driver

TABLE B-1 IOCTL Parameters for the SunHSI/S Driver

IOCTL Name

Purpose and Structure

S_IOCGETMODE

Retrieves the current transmission parameters setting for a particular port. Structure required:

struct scc_mode {

char sm_txclock; /*transmit clock sources */

char sm_rxclock; /*receive clock sources */

char sm_iflags; /*data and clock invert flags */

u_char sm_config; /*boolean configuration options*/

int sm_baudrate; /*real baud rate */

int sm_retval; /*SMERR codes go here,

query with GETMODE */

};

S_IOCSETMODE

Reinitializes a particular port with new transmission parameters setting.

Structure required:

Same as S_IOCGETMODE

S_IOCGETSPEED

Retrieves the current baud rate setting for a particular port.

Structure required:

int speed;

S_IOCGETMRU

Retrieves the current Maximum Receiving Unit (MRU) setting for a particular port. Structure required:

int mru;

S_IOCSETMRU

Sets to a new Maximum Receiving Unit (MRU) for a particular port.

Structure required:

int mru;

S_IOCGETMTU

Retrieves the current Maximum Transmission Unit (MTU) setting for a particular port. Structure required:

int mru;

S_IOCSETMTU

Sets to a new Maximum Transmission Unit (MTU) setting for a particular port.

Structure required:

int mru;

S_IOCGETMCTL

Retrieves the current DCD/CTS state for a particular port.

Structure required:

u_char mctl;

S_IOCGETSTATS

Retrieves the data or errors statistics that SunHSI/S driver has accumulated for a particular port. Structure required:

struct hs_stats {

long ipack; /*input packets*/

long opack; /*output packets*/

long ichar; /*input bytes*/

long ochar; /*output bytes*/

long abort; /*abort received*/

long crc; /*CRC error*/

long cts; /*CTS timeouts*/

long dcd; /*Carrier drops*/

long overrun; /*receiver overrun*/

long underrun; /*xmitter underrun*/

long ierror; /*input error (rxbad)*/

long oerror; /*output error

(watchdog timeout)*/

long nobuffers; /*no active receive block available

long ishort; /*input packet too short

(<CRC-bytes+1)*/

long ilong; /*input packet too long (> mru)*/

long inactive; /*input packet received

when inactive*/

long idma; /*receive dma error*/

long olong; /*output packet too long (> mtu)*/

long ohung; /*transmit hung (usually

missing clock)*/

long odma; /*transmit dma error*/

};

or:

struct sl_stats {

long ipack; /*input packets*/

long opack; /*output packets*/

long ichar; /*input bytes*/

long ochar; /*output bytes*/

long abort; /*abort received*/

long crc; /*CRC error*/

long cts; /*CTS timeouts*/

long dcd; /*Carrier drops*/

long overrun; /*receiver overrun*/

long underrun; /*xmitter underrun*/

long ierror; /*input error (rxbad)*/

long oerror; /*output error (watchdog timeout)*/

long nobuffers; /*no active receive block available*/

};

S_IOCCLRSTATS

Clears the data and error statistics that SunHSI/S driver has accumulated for a particular port. Structure required:

Same as S_IOCGETSTATS


The scc_mode and sl_stats structures defined in the system include file
(/usr/include/sys/ser_sync.h) .


Interrupts

Hardware interrupts are serviced through the hsintr interrupt service routine. This routine determines the source of the interrupt using an interrupt vector read from the ISCC chip. If the interrupt is not from the SunHSI/S adapter(s), the procedure returns a zero value. If the interrupt is from the ISCC chip, the interrupt is serviced. The possible hardware interrupts are listed in the following table.

TABLE B-2 Hardware Interrupts

Interrupt

Cause

External Status

Either a Break or an Abort was transmitted over the DLC line. An Abort is series of 15 successive ones sent over the line by the transmitting side.

Transmit Interrupt

A full packet was transmitted over the line.

Receive Interrupt

Special circuitry on the SunHSI/S adapter detects the receipt of a complete frame and interrupts the system processor(s).

DMA Transmit Terminal Count

A complete packet was generated. In addition to this interrupt, a Transmit Interrupt occurs at transmission.

DMA Receive Terminal Count

The received packet is larger than the DMA Receive Buffer.



Packet Transmission and Reception

When an upper-protocol layer or a user program has a packet ready for transmission by the interface, it calls either the putnext(9F) utility or the putmsg(2) system call to pass the packet to the SunHSI/S driver. If the SunHSI/S driver transmission buffer is empty, the hih_wput routine of the driver copies the packet into the RAM buffer on the SunHSI/S adapter. From there, the packet is transmitted across the serial line. If the transmit buffer is full, the packet is queued at the local WRITE queue for later transmission by the hih_wsrv routine.

If the local WRITE queue has too many packets (beyond the high-water mark), the upper layers detect the congestion by calling canputnext and slow down the traffic until the congestion is resolved.

When a correct packet is received, it is copied from the SunHSI/S board RAM to a stream message buffer. When a complete packet is received, the hih_rsrv routine of the driver is called to send the packet to upper layers.

The Z16C35 ISCC support an internal status FIFO of approximately ten packets. As a result, you can queue many packets during reception without servicing an interrupt. Since most synchronous protocols require relatively fast reception of control packets, you do not want packets to queue at the driver level for long. To alleviate this possible problem, an algorithm based on the receive queue size and a timer is used. Either event causes the packets to be sent to the upper level.