Cronyx/Sigma sync/async serial driver with PPP support

from Serge Vakulenko
This commit is contained in:
Garrett Wollman 1994-12-02 23:23:01 +00:00
parent 114a506d1a
commit 6014635361
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/cvs2svn/branches/cronyx/; revision=4910
15 changed files with 7204 additions and 0 deletions

4
sbin/cxconfig/Makefile Normal file
View File

@ -0,0 +1,4 @@
PROG = cxconfig
MAN8 = cxconfig.8
.include <bsd.prog.mk>

297
sbin/cxconfig/cxconfig.8 Normal file
View File

@ -0,0 +1,297 @@
.TH Cronyx-Sigma 1
.rm ES
.rm EE
.de ES
.PP
.nf
.in +0.5i
..
.de EE
.in -0.5i
.fi
..
.na
.SH NAME
.B cxconfig
\- channel options management utility for Cronyx-Sigma adapter
.SH DESCRIPTION
.PP
The \fBcxconfig\fP utility is used for configuring the channel options of
the Cronyx-Sigma adapter.
.PP
To change cha options the channel should be free: the corresponding
network interface in ``down'' state, the asynchronous terminal device /dev/tty*
closed.
Generally, the channel options are set up during the operating
system startup, for example from the \fI/etc/rc\fP file.
.PP
Note, that not all options have a sense for every particular
case, and an attempt to set some of them can hang up the channel or
the whole adapter.
.SH "Usage"
.IP "cxconfig"
The brief information about all channels.
.IP "cxconfig -a"
The full information about all channels.
.IP "cxconfig <channel>"
The brief information about the channel.
.IP "cxconfig -a <channel>"
The full information about the channel.
.IP "cxconfig <channel> <option>..."
Setting the channel options.
.SH "Channel options"
.IP ispeed=#
Set the receiver baud rate to the number given.
The maximal value is 256000 bits/sec.
In the synchronous mode the receiver baud rate is significant
only when DPLL mode is used.
.IP ospeed=#
Set the transmitter baud rate to the number given.
The maximal value is 256000 bits/sec.
In the synchronous mode the transmitter baud rate is significant
only in the case of the internal clock source.
If receiver and transmitter have equal data rate, then it could
be set by specifying only the numerical argument.
.IP async
Set the asynchronous channel mode.
.IP "hdlc, bisync, bsc, x.21, x21
Set the synchronous channel mode: HDLC, Bisync (BSC) or X.21.
.IP ppp
Set the link-level protocol: PPP/HDLC. The built-in simplified synchronous PPP
implementation is used (see RFC-1548, RFC-1549).
.IP cisco
Set the link-level protocol: Cisco/HDLC (see RFC-1547).
This protocol is intended for compatibility with old models of Cisco routers,
and with early versions of BSD/386 drivers.
The extensive usage of this protocol is not recommended.
.IP ext
Use the external link-level protocol suite (for BSD/386 only).
.IP "+keepalive, -keepalive"
Enable the automatic line state control sub-protocol.
This setting is not significant when the external link-level protocol is used.
.IP "+autorts, -autorts"
Enable the automatic RTS signal control.
When enabled, the RTS signal goes up only when both halves of
the receiver ring buffer are free and ready for receive,
and goes down when one or both buffers are busy.
.IP "port=rs232, port=rs449, port=v35
Set the zero channel hardware interface type.
.SH "Common options"
.IP "nrz, nrzi, manchester
Set the data line signal encoding.
In the case of \fINRZ\fP encoding the zero bit is transmitted by the zero signal
level, the one bit - by the positive signal level.
In the case of \fINRZI\fP encoding the zero bit is transmitted by the change of
the signal level, the one bit - by the constant signal level.
In the case of \fIManchester\fP encoding the zero bit is encoded as 01 value,
the one bit - as 10 value.
.IP "+dpll, -dpll"
Enable the digital phase locked loop mode (DPLL).
When enabled, the receiver timing clock signal
is derived from the received data.
.IP "+lloop, -lloop"
Set the local loopback mode.
.IP "+extclock, -extclock"
Set the timing clock source of synchronous channels. There are
two possible variants: \fIexternal clock\fP source or \fIinternal clock\fP
generation.
.br
\fIExternal clock\fP mode is the most common method for connecting
external modem hardware. In this mode the external timing
signal is received on TXCIN pin of the connector, and it is
used as a synchronization clock for transmitting data (TXD).
.br
In the case of \fIinternal clock\fP mode the transmitted data (TXD)
are synchronized using the internal on-board timing generator,
the internally generated timing signal is driven on the TXCOUT
pin, and the signal on the TXCIN pin is ignored. This mode
is used for direct terminal-to-terminal communication,
e.g. for connecting two computers together in a synchronous mode
via relatively short cable. This method should also be used
for testing channels with an external loopback connector.
.IP fifo=#
FIFO threshold level setup for receiver and transmitter.
.IP rfifo=#
Hardware RTS/CTS flow control FIFO threshold setup.
.IP "+ctsup, -ctsup"
Enable/disable interrupts on CTS (Clear To Send) signal setup (0 to 1 transition).
.IP "+ctsdown, -ctsdown"
Enable/disable interrupts on CTS (Clear To Send) signal clear (1 to 0 transition).
.IP "+cdup, -cdup"
Enable/disable interrupts on CD (Carrier Detect) signal setup (0 to 1 transition).
.IP "+cddown, -cddown"
Enable/disable interrupts on CD (Carrier Detect) signal clear (1 to 0 transition).
.IP "+dsrup, -dsrup"
Enable/disable interrupts on DSR (Data Set Ready) signal setup (0 to 1 transition).
.IP "+dsrdown, -dsrdown"
Enable/disable interrupts on DSR (Data Set Ready) signal clear (1 to 0 transition).
.SH "Asynchronous mode options"
.IP cs#
Select character size: 5, 6, 7 or 8 bits.
.IP "parodd, pareven
Parity mode: odd or even.
.IP "+ignpar, -ignpar
Disable/enable parity detection.
.IP nopar
Disable parity bit generation.
.IP forcepar
Force parity: even - 0, odd - 1.
.IP "stopb1, stopb1.5, stopb2
Use 1 or 1.5 or 2 stop bits per character.
.IP "+dsr, -dsr"
Use the DSR input signal as receiver enable/disable.
.IP "+cts, -cts"
Use the CTS input signal as transmitter enable/disable.
.IP "+rts, -rts"
Drive the RTS output signal as transmitter ready.
.IP "+rloop, -rloop"
Set the remote loopback mode.
.IP "+etc, -etc"
Enable the embedded transmit commands mode.
.IP "+ixon, -ixon"
Enable the hardware XON/XOFF flow control support.
.IP "+ixany, -ixany"
Use the hardware IXANY mode support.
.IP "+sdt, -sdt"
Detect the spec. characters SCHR1 and SCHR2 in the receive data.
.IP "+flowct, -flowct"
Receive the flow control spec. characters as data.
.IP "+rdt, -rdt"
Detect the spec. characters in range SCRL..SCRH in the receive data.
.IP "+exdt, -exdt"
Detect the spec. characters SCHR3 and SCHR4 in the receive data.
.IP "parintr, parnull, parign, pardisc, parffnull
Action on parity errors:
.ES
Mode Action
-----------------------------------------------------
parintr Generate the receiver error interrupt
parnull Input the NULL character
parign Ignore the error, receive as good data
pardisc Ignore the character
parffnull Input the sequence <0xFF, NULL, character>
.EE
.IP "brkintr, brknull, brkdisc
Line break state action:
.ES
Mode Action
---------------------------------------------------
brkintr Generate the receiver error interrupt
brknull Input the NULL character
brkdisc Ignore the line break state
.EE
.IP "+inlcr, -inlcr"
Translate received NL characters to CR.
.IP "+icrnl, -icrnl"
Translate received CR characters to NL.
.IP "+igncr, -igncr"
Ignore received CR characters.
.IP "+ocrnl, -ocrnl"
Translate transmitted CR characters to NL.
.IP "+onlcr, -onlcr"
Translate transmitted NL characters to CR.
.IP "+fcerr, -fcerr"
Process (don't process) the characters, received with errors,
for special character/flow control matching.
.IP "+lnext, -lnext"
Enable the LNEXT character option: the character following
the LNEXT character is not processed for special character/flow
control matching.
.IP "+istrip, -istrip"
Strip input characters to seven bits.
.IP schr1=#
The XON flow control character value.
.IP schr2=#
The XOFF flow control character value.
.IP schr3=#
The SCHR3 spec. character value.
.IP schr4=#
The SCHR4 spec. character value.
.IP "scrl=#, scrh=#
The spec. character range (inclusive).
.IP lnext=#
The LNEXT spec. character value.
.SH "HDLC mode options"
.IP if#
The minimum number of flags transmitted before a frame is started.
.IP noaddr
No frame address recognition.
.IP "addrlen1, addrlen2"
Address field length: 1 or 2 bytes.
.IP "addr1, addr2"
Addressing mode: 4x1 bytes or 2x2 bytes.
Registers RFAR1..RFAR4 should contain the address to be matched.
.IP "+clrdet, -clrdet"
Enable/disable clear detect for X.21 protocol support.
.IP "+dsr, -dsr"
Use the DSR input signal as receiver enable/disable.
.IP "+cts, -cts"
Use the CTS input signal as transmitter enable/disable.
.IP "+rts, -rts"
Drive the RTS output signal as transmitter ready.
.IP "+fcs, -fcs"
Enable/disable the frame checksum generation and checking.
.IP "crc-16, crc-v.41
Select the CRC polynomial: CRC-16 (x^16+x^15+x^2+1)
or CRC V.41 (x^16+x^12+x^5+1).
.IP "fcs-crc-16, fcs-v.41
Frame checksum preset: all zeros (CRC-16) or all ones (CRC V.41).
.IP "+crcinv, -crcinv"
Invert (ie. CRC V.41) or don't invert (ie. CRC-16) the transmitted frame checksum.
.IP "+fcsapd, -fcsapd"
Pass the received CRC to the host at the end of receiver data buffer.
.IP "idlemark, idleflag
Idle mode: idle in mark (transmit all ones) or idle in flag (transmit flag).
.IP "+syn, -syn"
Enable/disable sending pad characters before sending flag when coming out
of the idle mode.
.IP pad#
The number of synchronous characters sent (0..4).
.IP "syn=0xaa, syn=0x00
Send sync pattern.
.IP "rfar1=#, rfar2=#, rfar3=#, rfar4=#
Frame address registers for address recognition.
.SH EXAMPLES
.PP
Set up the channel 7 of the adapter Sigma-400 under FreeBSD.
Physical 4-wire leased line with Zelax+ M115 short-range modems.
Synchronous mode, 128000 bits/sec, interface RS-232,
protocol PPP/HDLC without keepalive support, NRZI encoding,
DPLL mode, no flow control:
.ES
cxconfig cx7 128000 hdlc ppp -keepalive nrzi -cts +dpll -extclock
ifconfig cx7 158.250.244.2 158.250.244.1 up
.EE
.PP
Set up the channel 0 of the adapter Sigma-100 under FreeBSD.
Attachment to the near computer by short cable, internal clock source.
Synchronous mode, 256000 bits/sec, interface RS-232,
protocol Cisco/HDLC with keepalive support:
.ES
cxconfig cx0 hdlc 256000 cisco +keepalive -extclock
ifconfig cx0 200.1.1.1 200.1.1.2 up
.EE
.PP
Set up the channel 1 of the adapter Sigma-840 under BSD/386.
Synchronous 64 kbit/sec leased line, external clock source.
Synchronous mode, interface V.35, external protocol suite:
.ES
cxconfig cx1 hdlc ext
ifconfig cx1 193.124.254.50 193.124.254.49 multicast up
.EE
.PP
Set up the channel 0 of the adapter Sigma-840 under FreeBSD.
Attachment to the Cisco-4000 router by null-modem cable, internal clock source.
Synchronous mode, 64000 bits/sec, interface RS-232,
protocol PPP/HDLC with keepalive support and flow control,
LCP and IPCP protocols (see RFC-1548 and RFC-1332) debug tracing enabled:
.ES
cxconfig cx0 hdlc 64000 port=rs232 ppp +keepalive -extclock +cts
ifconfig cx0 100.0.0.2 100.0.0.1 debug up
.EE
.SH FILES
.IP /dev/cronyx
The special device file for adapter options management.
.SH SEE ALSO
.PP
cx(4)

704
sbin/cxconfig/cxconfig.c Normal file
View File

@ -0,0 +1,704 @@
/*
* Cronyx-Sigma adapter configuration utility for Unix.
*
* Copyright (C) 1994 Cronyx Ltd.
* Author: Serge Vakulenko, <vak@zebub.msk.su>
*
* This software is distributed with NO WARRANTIES, not even the implied
* warranties for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*
* Authors grant any other persons or organisations permission to use
* or modify this software as long as this message is kept with the software,
* all derivative works or modified versions.
*
* Version 1.1, Wed Oct 26 16:08:09 MSK 1994
*
* Usage:
* cxconfig [-a]
* -- print status of all channels
* cxconfig [-a] <channel>
* -- print status of the channel
* cxconfig <channel> <option>...
* -- set channel options
*/
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <sys/cronyx.h>
#include <net/if.h>
#include <stdio.h>
#define CXDEV "/dev/cronyx"
#define atoi(a) strtol((a), (char**)0, 0)
cx_options_t o;
int aflag;
char *symbol (unsigned char sym)
{
static char buf[40];
if (sym < ' ')
sprintf (buf, "^%c", sym+0100);
else if (sym == '\\')
strcat (buf, "\\\\");
else if (sym < 127)
sprintf (buf, "%c", sym);
else
sprintf (buf, "\\%03o", sym);
return (buf);
}
unsigned char atosym (char *s)
{
unsigned char c;
if (*s == '^')
return (*++s & 037);
if (*s == '\\')
return (strtol (++s, 0, 8));
return (*s);
}
void usage ()
{
printf ("Cronyx-Sigma Adapter Configuration Utility, Version 1.0\n");
printf ("Copyright (C) 1994 Cronyx Ltd.\n");
printf ("Usage:\n");
printf ("\tcxconfig [-a]\n");
printf ("\t\t-- print status of all channels\n");
printf ("\tcxconfig [-a] <channel>\n");
printf ("\t\t-- print status of the channel\n");
printf ("\tcxconfig <channel> [async | hdlc | bisync | x.21] [ispeed #] [ospeed #]\n");
printf ("\t\t[+cts | -cts]\n");
printf ("\t\t-- set channel options\n");
exit (1);
}
char *chantype (int type)
{
switch (type) {
case T_NONE: return ("none");
case T_ASYNC: return ("RS-232");
case T_UNIV_RS232: return ("RS-232");
case T_UNIV_RS449: return ("RS-232/RS-449");
case T_UNIV_V35: return ("RS-232/V.35");
case T_SYNC_RS232: return ("RS-232");
case T_SYNC_V35: return ("V.35");
case T_SYNC_RS449: return ("RS-449");
}
}
char *chanmode (int mode)
{
switch (mode) {
case M_ASYNC: return ("Async");
case M_HDLC: return ("HDLC");
case M_BISYNC: return ("Bisync");
case M_X21: return ("X.21");
default: return ("???");
}
}
void getchan (int channel)
{
int s = open (CXDEV, 0);
if (s < 0) {
perror (CXDEV);
exit (1);
}
o.board = channel/NCHAN;
o.channel = channel%NCHAN;
if (ioctl (s, CXIOCGETMODE, (caddr_t)&o) < 0) {
perror ("cxconfig: CXIOCGETMODE");
exit (1);
}
close (s);
if (o.type == T_NONE) {
fprintf (stderr, "cx%d: channel %d not configured\n", o.board,
o.channel);
exit (1);
}
}
void setchan (int channel)
{
int s = open (CXDEV, 0);
if (s < 0) {
perror (CXDEV);
exit (1);
}
o.board = channel/NCHAN;
o.channel = channel%NCHAN;
if (ioctl (s, CXIOCSETMODE, (caddr_t)&o) < 0) {
perror ("cxconfig: CXIOCSETMODE");
exit (1);
}
close (s);
}
void printopt ()
{
/* Common channel options */
/* channel option register 4 */
printf ("\t");
printf ("fifo=%d ", o.opt.cor4.thr); /* FIFO threshold */
printf ("%cctsdown ", o.opt.cor4.cts_zd ? '+' : '-'); /* detect 1 to 0 transition on the CTS */
printf ("%ccddown ", o.opt.cor4.cd_zd ? '+' : '-'); /* detect 1 to 0 transition on the CD */
printf ("%cdsrdown ", o.opt.cor4.dsr_zd ? '+' : '-'); /* detect 1 to 0 transition on the DSR */
printf ("\n");
/* channel option register 5 */
printf ("\t");
printf ("rfifo=%d ", o.opt.cor5.rx_thr); /* receive flow control FIFO threshold */
printf ("%cctsup ", o.opt.cor5.cts_od ? '+' : '-'); /* detect 0 to 1 transition on the CTS */
printf ("%ccdup ", o.opt.cor5.cd_od ? '+' : '-'); /* detect 0 to 1 transition on the CD */
printf ("%cdsrup ", o.opt.cor5.dsr_od ? '+' : '-'); /* detect 0 to 1 transition on the DSR */
printf ("\n");
/* receive clock option register */
printf ("\t");
printf ("%s ", o.opt.rcor.encod == ENCOD_NRZ ? "nrz" : /* signal encoding */
o.opt.rcor.encod == ENCOD_NRZI ? "nrzi" :
o.opt.rcor.encod == ENCOD_MANCHESTER ? "manchester" : "???");
printf ("%cdpll ", o.opt.rcor.dpll ? '+' : '-'); /* DPLL enable */
/* transmit clock option register */
printf ("%clloop ", o.opt.tcor.llm ? '+' : '-'); /* local loopback mode */
printf ("%cextclock ", o.opt.tcor.ext1x ? '+' : '-'); /* external 1x clock mode */
printf ("\n");
switch (o.mode) {
case M_ASYNC: /* async mode options */
/* channel option register 1 */
printf ("\t");
printf ("cs%d ", o.aopt.cor1.charlen+1); /* character length, 5..8 */
printf ("par%s ", o.aopt.cor1.parity ? "odd" : "even"); /* parity */
printf ("%cignpar ", o.aopt.cor1.ignpar ? '+' : '-'); /* ignore parity */
if (o.aopt.cor1.parmode != PARM_NORMAL) /* parity mode */
printf ("%s ", o.aopt.cor1.parmode == PARM_NOPAR ? "nopar" :
o.aopt.cor1.parmode == PARM_FORCE ? "forcepar" : "???");
printf ("\n");
/* channel option register 2 */
printf ("\t");
printf ("%cdsr ", o.aopt.cor2.dsrae ? '+' : '-'); /* DSR automatic enable */
printf ("%ccts ", o.aopt.cor2.ctsae ? '+' : '-'); /* CTS automatic enable */
printf ("%crts ", o.aopt.cor2.rtsao ? '+' : '-'); /* RTS automatic output enable */
printf ("%crloop ", o.aopt.cor2.rlm ? '+' : '-'); /* remote loopback mode enable */
printf ("%cetc ", o.aopt.cor2.etc ? '+' : '-'); /* embedded transmitter cmd enable */
printf ("%cxon ", o.aopt.cor2.ixon ? '+' : '-'); /* in-band XON/XOFF enable */
printf ("%cxany ", o.aopt.cor2.ixany ? '+' : '-'); /* XON on any character */
printf ("\n");
/* option register 3 */
printf ("\t");
printf ("%s ", o.aopt.cor3.stopb == STOPB_1 ? "stopb1" : /* stop bit length */
o.aopt.cor3.stopb == STOPB_15 ? "stopb1.5" :
o.aopt.cor3.stopb == STOPB_2 ? "stopb2" : "???");
printf ("%csdt ", o.aopt.cor3.scde ? '+' : '-'); /* special char detection enable */
printf ("%cflowct ", o.aopt.cor3.flowct ? '+' : '-'); /* flow control transparency mode */
printf ("%crdt ", o.aopt.cor3.rngde ? '+' : '-'); /* range detect enable */
printf ("%cexdt ", o.aopt.cor3.escde ? '+' : '-'); /* extended spec. char detect enable */
printf ("\n");
/* channel option register 6 */
printf ("\t");
printf ("%s ", o.aopt.cor6.parerr == PERR_INTR ? "parintr" : /* parity/framing error actions */
o.aopt.cor6.parerr == PERR_NULL ? "parnull" :
o.aopt.cor6.parerr == PERR_IGNORE ? "parign" :
o.aopt.cor6.parerr == PERR_DISCARD ? "pardisc" :
o.aopt.cor6.parerr == PERR_FFNULL ? "parffnull" : "???");
printf ("%s ", o.aopt.cor6.brk == BRK_INTR ? "brkintr" : /* action on break condition */
o.aopt.cor6.brk == BRK_NULL ? "brknull" :
o.aopt.cor6.brk == BRK_DISCARD ? "brkdisc" : "???");
printf ("%cinlcr ", o.aopt.cor6.inlcr ? '+' : '-'); /* translate NL to CR on input */
printf ("%cicrnl ", o.aopt.cor6.icrnl ? '+' : '-'); /* translate CR to NL on input */
printf ("%cigncr ", o.aopt.cor6.igncr ? '+' : '-'); /* discard CR on input */
printf ("\n");
/* channel option register 7 */
printf ("\t");
printf ("%cocrnl ", o.aopt.cor7.ocrnl ? '+' : '-'); /* translate CR to NL on output */
printf ("%conlcr ", o.aopt.cor7.onlcr ? '+' : '-'); /* translate NL to CR on output */
printf ("%cfcerr ", o.aopt.cor7.fcerr ? '+' : '-'); /* process flow ctl err chars enable */
printf ("%clnext ", o.aopt.cor7.lnext ? '+' : '-'); /* LNext option enable */
printf ("%cistrip ", o.aopt.cor7.istrip ? '+' : '-'); /* strip 8-bit on input */
printf ("\n");
printf ("\t");
printf ("schr1=%s ", symbol (o.aopt.schr1)); /* special character register 1 (XON) */
printf ("schr2=%s ", symbol (o.aopt.schr2)); /* special character register 2 (XOFF) */
printf ("schr3=%s ", symbol (o.aopt.schr3)); /* special character register 3 */
printf ("schr4=%s ", symbol (o.aopt.schr4)); /* special character register 4 */
printf ("scrl=%s ", symbol (o.aopt.scrl)); /* special character range low */
printf ("scrh=%s ", symbol (o.aopt.scrh)); /* special character range high */
printf ("lnext=%s ", symbol (o.aopt.lnxt)); /* LNext character */
printf ("\n");
break;
case M_HDLC: /* hdlc mode options */
/* hdlc channel option register 1 */
printf ("\t");
printf ("if%d ", o.hopt.cor1.ifflags); /* number of inter-frame flags sent */
printf ("%s ", o.hopt.cor1.admode == ADMODE_NOADDR ? "noaddr" : /* addressing mode */
o.hopt.cor1.admode == ADMODE_4_1 ? "addr1" :
o.hopt.cor1.admode == ADMODE_2_2 ? "addr2" : "???");
printf ("%cclrdet ", o.hopt.cor1.clrdet ? '+' : '-'); /* clear detect for X.21 data transfer phase */
printf ("addrlen%d ", o.hopt.cor1.aflo + 1); /* address field length option */
printf ("\n");
/* hdlc channel option register 2 */
printf ("\t");
printf ("%cdsr ", o.hopt.cor2.dsrae ? '+' : '-'); /* DSR automatic enable */
printf ("%ccts ", o.hopt.cor2.ctsae ? '+' : '-'); /* CTS automatic enable */
printf ("%crts ", o.hopt.cor2.rtsao ? '+' : '-'); /* RTS automatic output enable */
printf ("%ccrcinv ", o.hopt.cor2.crcninv ? '-' : '+'); /* CRC invertion option */
printf ("%cfcsapd ", o.hopt.cor2.fcsapd ? '+' : '-'); /* FCS append */
printf ("\n");
/* hdlc channel option register 3 */
printf ("\t");
printf ("pad%d ", o.hopt.cor3.padcnt); /* pad character count */
printf ("idle%s ", o.hopt.cor3.idle ? "mark" : "flag"); /* idle mode */
printf ("%cfcs ", o.hopt.cor3.nofcs ? '-' : '+'); /* FCS disable */
printf ("fcs-%s ", o.hopt.cor3.fcspre ? "crc-16" : "v.41"); /* FCS preset */
printf ("syn=%s ", o.hopt.cor3.syncpat ? "0xAA" : "0x00"); /* send sync pattern */
printf ("%csyn ", o.hopt.cor3.sndpad ? '+' : '-'); /* send pad characters before flag enable */
printf ("\n");
printf ("\t");
printf ("rfar1=0x%02x ", o.hopt.rfar1); /* receive frame address register 1 */
printf ("rfar2=0x%02x ", o.hopt.rfar2); /* receive frame address register 2 */
printf ("rfar3=0x%02x ", o.hopt.rfar3); /* receive frame address register 3 */
printf ("rfar4=0x%02x ", o.hopt.rfar4); /* receive frame address register 4 */
printf ("crc-%s ", o.hopt.cpsr ? "16" : "v.41"); /* CRC polynomial select */
printf ("\n");
break;
case M_BISYNC: /* bisync mode options */
/* channel option register 1 */
printf ("\t");
printf ("cs%d ", o.bopt.cor1.charlen+1); /* character length, 5..8 */
printf ("par%s ", o.bopt.cor1.parity ? "odd" : "even"); /* parity */
printf ("%cignpar ", o.bopt.cor1.ignpar ? '+' : '-'); /* ignore parity */
if (o.bopt.cor1.parmode != PARM_NORMAL) /* parity mode */
printf ("%s ", o.bopt.cor1.parmode == PARM_NOPAR ? "nopar" :
o.bopt.cor1.parmode == PARM_FORCE ? "forcepar" : "???");
printf ("\n");
/* channel option register 2 */
printf ("\t");
printf ("syn%d ", o.bopt.cor2.syns+2); /* number of extra SYN chars before a frame */
printf ("%ccrcinv ", o.bopt.cor2.crcninv ? '-' : '+'); /* CRC invertion option */
printf ("%s ", o.bopt.cor2.ebcdic ? "ebcdic" : "ascii"); /* use EBCDIC as char set (instead of ASCII) */
printf ("%cbccapd ", o.bopt.cor2.bcc ? '+' : '-'); /* BCC append enable */
printf ("%s ", o.bopt.cor2.lrc ? "lrc" : "crc-16"); /* longitudinal redundancy check */
printf ("\n");
/* channel option register 3 */
printf ("\t");
printf ("pad%d ", o.bopt.cor3.padcnt); /* pad character count */
printf ("idle%s ", o.bopt.cor3.idle ? "mark" : "syn"); /* idle mode */
printf ("%cfcs ", o.bopt.cor3.nofcs ? '-' : '+'); /* FCS disable */
printf ("fcs-%s ", o.bopt.cor3.fcspre ? "crc-16" : "v.41"); /* FCS preset */
printf ("syn=%s ", o.bopt.cor3.padpat ? "0x55" : "0xAA"); /* send sync pattern */
printf ("%csyn ", o.bopt.cor3.sndpad ? '+' : '-'); /* send pad characters before flag enable */
printf ("\n");
/* channel option register 6 */
printf ("\t");
printf ("specterm=%s ", symbol (o.bopt.cor6.specterm)); /* special termination character */
printf ("crc-%s ", o.bopt.cpsr ? "16" : "v.41"); /* CRC polynomial select */
printf ("\n");
break;
case M_X21: /* x.21 mode options */
/* channel option register 1 */
printf ("\t");
printf ("cs%d ", o.xopt.cor1.charlen+1); /* character length, 5..8 */
printf ("par%s ", o.xopt.cor1.parity ? "odd" : "even"); /* parity */
printf ("%cignpar ", o.xopt.cor1.ignpar ? '+' : '-'); /* ignore parity */
if (o.xopt.cor1.parmode != PARM_NORMAL) /* parity mode */
printf ("%s ", o.xopt.cor1.parmode == PARM_NOPAR ? "nopar" :
o.xopt.cor1.parmode == PARM_FORCE ? "forcepar" : "???");
printf ("\n");
/* channel option register 2 */
printf ("\t");
printf ("%cetc ", o.xopt.cor2.etc ? '+' : '-'); /* embedded transmitter cmd enable */
/* channel option register 3 */
printf ("%csdt ", o.xopt.cor3.scde ? '+' : '-'); /* special char detection enable */
printf ("%cstripsyn ", o.xopt.cor3.stripsyn ? '+' : '-'); /* treat SYN chars as special condition */
printf ("%cssdt ", o.xopt.cor3.ssde ? '+' : '-'); /* steady state detect enable */
printf ("syn%c ", o.xopt.cor3.syn ? '1' : '2'); /* the number of SYN chars on receive */
printf ("\n");
/* channel option register 6 */
printf ("\t");
printf ("syn=%s ", symbol (o.xopt.cor6.synchar)); /* syn character */
printf ("schr1=%s ", symbol (o.xopt.schr1)); /* special character register 1 */
printf ("schr2=%s ", symbol (o.xopt.schr2)); /* special character register 2 */
printf ("schr3=%s ", symbol (o.xopt.schr3)); /* special character register 3 */
printf ("\n");
break;
}
}
void printchan (int channel)
{
printf ("cx%d (%s) %s", channel, chantype (o.type), chanmode (o.mode));
if (o.txbaud == o.rxbaud)
printf (" %d", o.rxbaud);
else
printf (" ospeed=%d ispeed=%d", o.txbaud, o.rxbaud);
if ((o.channel == 0 || o.channel == 8) &&
(o.type == T_UNIV_V35 || o.type == T_UNIV_RS449))
printf (" port=%s", o.iftype ? (o.type == T_UNIV_V35 ?
"v35" : "rs449") : "rs232");
printf (o.sopt.ext ? " ext" : o.sopt.cisco ? " cisco" : " ppp");
printf (" %ckeepalive", o.sopt.keepalive ? '+' : '-');
printf (" %cautorts", o.sopt.norts ? '-' : '+');
printf ("\n");
if (aflag)
printopt ();
}
void printall ()
{
struct ifconf ifc;
struct ifreq *ifr;
char buf[BUFSIZ], *cp;
int s, c;
s = socket (AF_INET, SOCK_DGRAM, 0);
if (s < 0) {
perror ("cxconfig: socket");
exit (1);
}
ifc.ifc_len = sizeof (buf);
ifc.ifc_buf = buf;
if (ioctl (s, SIOCGIFCONF, (caddr_t)&ifc) < 0) {
perror ("cxconfig: SIOCGIFCONF");
exit (1);
}
close (s);
s = open (CXDEV, 0);
if (s < 0) {
perror (CXDEV);
exit (1);
}
ifr = ifc.ifc_req;
#define max(a,b) ((a)>(b) ? (a) : (b))
#define size(p) max((p).sa_len, sizeof(p))
for (cp=buf; cp<buf+ifc.ifc_len; cp+=sizeof(ifr->ifr_name)+size(ifr->ifr_addr)) {
ifr = (struct ifreq*) cp;
if (ifr->ifr_addr.sa_family != AF_LINK)
continue;
if (strncmp (ifr->ifr_name, "cx", 2) != 0)
continue;
c = atoi (ifr->ifr_name + 2);
o.board = c/NCHAN;
o.channel = c%NCHAN;
if (ioctl (s, CXIOCGETMODE, (caddr_t)&o) < 0) {
perror ("cxconfig: CXIOCGETMODE");
exit (1);
}
printchan (c);
}
close (s);
}
void set_interface_type (char *type)
{
if (o.channel != 0 && o.channel != 8) {
printf ("interface option is applicable only for channels 0 and 8\n");
exit (1);
}
if (o.type != T_UNIV_V35 && o.type != T_UNIV_RS449) {
printf ("interface option is applicable only for universal channels\n");
exit (1);
}
if (! strcasecmp (type, "port=rs232"))
o.iftype = 0;
else
o.iftype = 1;
}
void set_async_opt (char *opt)
{
/* channel option register 1 */
if (! strncasecmp (opt, "cs", 2)) o.aopt.cor1.charlen = atoi (opt + 2) - 1;
else if (! strcasecmp (opt, "parodd")) o.aopt.cor1.parity = 1;
else if (! strcasecmp (opt, "pareven")) o.aopt.cor1.parity = 0;
else if (! strcasecmp (opt, "-ignpar")) o.aopt.cor1.ignpar = 0;
else if (! strcasecmp (opt, "+ignpar")) o.aopt.cor1.ignpar = 1;
else if (! strcasecmp (opt, "nopar")) o.aopt.cor1.parmode = PARM_NOPAR;
else if (! strcasecmp (opt, "forcepar")) o.aopt.cor1.parmode = PARM_FORCE;
/* channel option register 2 */
else if (! strcasecmp (opt, "-dsr")) o.aopt.cor2.dsrae = 0;
else if (! strcasecmp (opt, "+dsr")) o.aopt.cor2.dsrae = 1;
else if (! strcasecmp (opt, "-cts")) o.aopt.cor2.ctsae = 0;
else if (! strcasecmp (opt, "+cts")) o.aopt.cor2.ctsae = 1;
else if (! strcasecmp (opt, "-rts")) o.aopt.cor2.rtsao = 0;
else if (! strcasecmp (opt, "+rts")) o.aopt.cor2.rtsao = 1;
else if (! strcasecmp (opt, "-rloop")) o.aopt.cor2.rlm = 0;
else if (! strcasecmp (opt, "+rloop")) o.aopt.cor2.rlm = 1;
else if (! strcasecmp (opt, "-etc")) o.aopt.cor2.etc = 0;
else if (! strcasecmp (opt, "+etc")) o.aopt.cor2.etc = 1;
else if (! strcasecmp (opt, "-ixon")) o.aopt.cor2.ixon = 0;
else if (! strcasecmp (opt, "+ixon")) o.aopt.cor2.ixon = 1;
else if (! strcasecmp (opt, "-ixany")) o.aopt.cor2.ixany = 0;
else if (! strcasecmp (opt, "+ixany")) o.aopt.cor2.ixany = 1;
/* option register 3 */
else if (! strcasecmp (opt, "stopb1")) o.aopt.cor3.stopb = STOPB_1;
else if (! strcasecmp (opt, "stopb1.5")) o.aopt.cor3.stopb = STOPB_15;
else if (! strcasecmp (opt, "stopb2")) o.aopt.cor3.stopb = STOPB_2;
else if (! strcasecmp (opt, "-sdt")) o.aopt.cor3.scde = 0;
else if (! strcasecmp (opt, "+sdt")) o.aopt.cor3.scde = 1;
else if (! strcasecmp (opt, "-flowct")) o.aopt.cor3.flowct = 0;
else if (! strcasecmp (opt, "+flowct")) o.aopt.cor3.flowct = 1;
else if (! strcasecmp (opt, "-rdt")) o.aopt.cor3.rngde = 0;
else if (! strcasecmp (opt, "+rdt")) o.aopt.cor3.rngde = 1;
else if (! strcasecmp (opt, "-exdt")) o.aopt.cor3.escde = 0;
else if (! strcasecmp (opt, "+exdt")) o.aopt.cor3.escde = 1;
/* channel option register 6 */
else if (! strcasecmp (opt, "parintr")) o.aopt.cor6.parerr = PERR_INTR;
else if (! strcasecmp (opt, "parnull")) o.aopt.cor6.parerr = PERR_NULL;
else if (! strcasecmp (opt, "parign")) o.aopt.cor6.parerr = PERR_IGNORE;
else if (! strcasecmp (opt, "pardisc")) o.aopt.cor6.parerr = PERR_DISCARD;
else if (! strcasecmp (opt, "parffnull")) o.aopt.cor6.parerr = PERR_FFNULL;
else if (! strcasecmp (opt, "brkintr")) o.aopt.cor6.brk = BRK_INTR;
else if (! strcasecmp (opt, "brknull")) o.aopt.cor6.brk = BRK_NULL;
else if (! strcasecmp (opt, "brkdisc")) o.aopt.cor6.brk = BRK_DISCARD;
else if (! strcasecmp (opt, "-inlcr")) o.aopt.cor6.inlcr = 0;
else if (! strcasecmp (opt, "+inlcr")) o.aopt.cor6.inlcr = 1;
else if (! strcasecmp (opt, "-icrnl")) o.aopt.cor6.icrnl = 0;
else if (! strcasecmp (opt, "+icrnl")) o.aopt.cor6.icrnl = 1;
else if (! strcasecmp (opt, "-igncr")) o.aopt.cor6.igncr = 0;
else if (! strcasecmp (opt, "+igncr")) o.aopt.cor6.igncr = 1;
/* channel option register 7 */
else if (! strcasecmp (opt, "-ocrnl")) o.aopt.cor7.ocrnl = 0;
else if (! strcasecmp (opt, "+ocrnl")) o.aopt.cor7.ocrnl = 1;
else if (! strcasecmp (opt, "-onlcr")) o.aopt.cor7.onlcr = 0;
else if (! strcasecmp (opt, "+onlcr")) o.aopt.cor7.onlcr = 1;
else if (! strcasecmp (opt, "-fcerr")) o.aopt.cor7.fcerr = 0;
else if (! strcasecmp (opt, "+fcerr")) o.aopt.cor7.fcerr = 1;
else if (! strcasecmp (opt, "-lnext")) o.aopt.cor7.lnext = 0;
else if (! strcasecmp (opt, "+lnext")) o.aopt.cor7.lnext = 1;
else if (! strcasecmp (opt, "-istrip")) o.aopt.cor7.istrip = 0;
else if (! strcasecmp (opt, "+istrip")) o.aopt.cor7.istrip = 1;
else if (! strncasecmp (opt, "schr1=", 6)) o.aopt.schr1 = atosym (opt+6);
else if (! strncasecmp (opt, "schr2=", 6)) o.aopt.schr2 = atosym (opt+6);
else if (! strncasecmp (opt, "schr3=", 6)) o.aopt.schr3 = atosym (opt+6);
else if (! strncasecmp (opt, "schr4=", 6)) o.aopt.schr4 = atosym (opt+6);
else if (! strncasecmp (opt, "scrl=", 5)) o.aopt.scrl = atosym (opt+5);
else if (! strncasecmp (opt, "scrh=", 5)) o.aopt.scrh = atosym (opt+5);
else if (! strncasecmp (opt, "lnext=", 6)) o.aopt.lnxt = atosym (opt+6);
else
usage ();
}
void set_hdlc_opt (char *opt)
{
/* hdlc channel option register 1 */
if (! strncasecmp (opt, "if", 2)) o.hopt.cor1.ifflags = atoi (opt + 2);
else if (! strcasecmp (opt, "noaddr")) o.hopt.cor1.admode = ADMODE_NOADDR;
else if (! strcasecmp (opt, "addr1")) o.hopt.cor1.admode = ADMODE_4_1;
else if (! strcasecmp (opt, "addr2")) o.hopt.cor1.admode = ADMODE_2_2;
else if (! strcasecmp (opt, "-clrdet")) o.hopt.cor1.clrdet = 0;
else if (! strcasecmp (opt, "+clrdet")) o.hopt.cor1.clrdet = 1;
else if (! strcasecmp (opt, "addrlen1")) o.hopt.cor1.aflo = 0;
else if (! strcasecmp (opt, "addrlen2")) o.hopt.cor1.aflo = 1;
/* hdlc channel option register 2 */
else if (! strcasecmp (opt, "-dsr")) o.hopt.cor2.dsrae = 0;
else if (! strcasecmp (opt, "+dsr")) o.hopt.cor2.dsrae = 1;
else if (! strcasecmp (opt, "-cts")) o.hopt.cor2.ctsae = 0;
else if (! strcasecmp (opt, "+cts")) o.hopt.cor2.ctsae = 1;
else if (! strcasecmp (opt, "-rts")) o.hopt.cor2.rtsao = 0;
else if (! strcasecmp (opt, "+rts")) o.hopt.cor2.rtsao = 1;
else if (! strcasecmp (opt, "-fcsapd")) o.hopt.cor2.fcsapd = 0;
else if (! strcasecmp (opt, "+fcsapd")) o.hopt.cor2.fcsapd = 1;
else if (! strcasecmp (opt, "-crcinv")) o.hopt.cor2.crcninv = 1;
else if (! strcasecmp (opt, "+crcinv")) o.hopt.cor2.crcninv = 0;
/* hdlc channel option register 3 */
else if (! strncasecmp (opt, "pad", 3)) o.hopt.cor3.padcnt = atoi (opt + 3);
else if (! strcasecmp (opt, "idlemark")) o.hopt.cor3.idle = 1;
else if (! strcasecmp (opt, "idleflag")) o.hopt.cor3.idle = 0;
else if (! strcasecmp (opt, "-fcs")) o.hopt.cor3.nofcs = 1;
else if (! strcasecmp (opt, "+fcs")) o.hopt.cor3.nofcs = 0;
else if (! strcasecmp (opt, "fcs-crc-16")) o.hopt.cor3.fcspre = 1;
else if (! strcasecmp (opt, "fcs-v.41")) o.hopt.cor3.fcspre = 0;
else if (! strcasecmp (opt, "syn=0xaa")) o.hopt.cor3.syncpat = 1;
else if (! strcasecmp (opt, "syn=0x00")) o.hopt.cor3.syncpat = 0;
else if (! strcasecmp (opt, "-syn")) o.hopt.cor3.sndpad = 0;
else if (! strcasecmp (opt, "+syn")) o.hopt.cor3.sndpad = 1;
else if (! strncasecmp (opt, "rfar1=", 6)) o.hopt.rfar1 = atoi (opt + 6);
else if (! strncasecmp (opt, "rfar2=", 6)) o.hopt.rfar2 = atoi (opt + 6);
else if (! strncasecmp (opt, "rfar3=", 6)) o.hopt.rfar3 = atoi (opt + 6);
else if (! strncasecmp (opt, "rfar4=", 6)) o.hopt.rfar4 = atoi (opt + 6);
else if (! strcasecmp (opt, "crc-16")) o.hopt.cpsr = 1;
else if (! strcasecmp (opt, "crc-v.41")) o.hopt.cpsr = 0;
else usage ();
}
void set_bisync_opt (char *opt)
{
usage ();
}
void set_x21_opt (char *opt)
{
usage ();
}
int main (int argc, char **argv)
{
int channel;
for (--argc, ++argv; argc>0 && **argv=='-'; --argc, ++argv)
if (! strcasecmp (*argv, "-a"))
++aflag;
else
usage ();
if (argc <= 0) {
printall ();
return (0);
}
if (argv[0][0]=='c' && argv[0][1]=='x')
*argv += 2;
if (**argv<'0' || **argv>'9')
usage ();
channel = atoi (*argv);
--argc, ++argv;
getchan (channel);
if (argc <= 0) {
printchan (channel);
return (0);
}
for (; argc>0; --argc, ++argv)
if (**argv == '(')
continue;
else if (! strncasecmp (*argv, "ispeed=", 7))
o.rxbaud = atoi (*argv+7);
else if (! strncasecmp (*argv, "ospeed=", 7))
o.txbaud = atoi (*argv+7);
else if (! strcasecmp (*argv, "async"))
o.mode = M_ASYNC;
else if (! strcasecmp (*argv, "hdlc"))
o.mode = M_HDLC;
else if (! strcasecmp (*argv, "bisync") ||
! strcasecmp (*argv, "bsc"))
o.mode = M_BISYNC;
else if (! strcasecmp (*argv, "x.21") ||
! strcasecmp (*argv, "x21"))
o.mode = M_X21;
else if (**argv>='0' && **argv<='9')
o.txbaud = o.rxbaud = atoi (*argv);
else if (! strcasecmp (*argv, "cisco")) {
o.sopt.cisco = 1;
o.sopt.ext = 0;
} else if (! strcasecmp (*argv, "ppp")) {
o.sopt.cisco = 0;
o.sopt.ext = 0;
} else if (! strcasecmp (*argv, "ext"))
o.sopt.ext = 1;
else if (! strcasecmp (*argv, "+keepalive"))
o.sopt.keepalive = 1;
else if (! strcasecmp (*argv, "-keepalive"))
o.sopt.keepalive = 0;
else if (! strcasecmp (*argv, "+autorts"))
o.sopt.norts = 0;
else if (! strcasecmp (*argv, "-autorts"))
o.sopt.norts = 1;
else if (! strcasecmp (*argv, "port=rs232") ||
! strcasecmp (*argv, "port=rs449") ||
! strcasecmp (*argv, "port=v35"))
set_interface_type (*argv);
/*
* Common channel options
*/
/* channel option register 4 */
else if (! strcasecmp (*argv, "-ctsdown"))
o.opt.cor4.cts_zd = 0;
else if (! strcasecmp (*argv, "+ctsdown"))
o.opt.cor4.cts_zd = 1;
else if (! strcasecmp (*argv, "-cddown"))
o.opt.cor4.cd_zd = 0;
else if (! strcasecmp (*argv, "+cddown"))
o.opt.cor4.cd_zd = 1;
else if (! strcasecmp (*argv, "-dsrdown"))
o.opt.cor4.dsr_zd = 0;
else if (! strcasecmp (*argv, "+dsrdown"))
o.opt.cor4.dsr_zd = 1;
else if (! strncasecmp (*argv, "fifo=", 5))
o.opt.cor4.thr = atoi (*argv + 5);
/* channel option register 5 */
else if (! strcasecmp (*argv, "-ctsup"))
o.opt.cor5.cts_od = 0;
else if (! strcasecmp (*argv, "+ctsup"))
o.opt.cor5.cts_od = 1;
else if (! strcasecmp (*argv, "-cdup"))
o.opt.cor5.cd_od = 0;
else if (! strcasecmp (*argv, "+cdup"))
o.opt.cor5.cd_od = 1;
else if (! strcasecmp (*argv, "-dsrup"))
o.opt.cor5.dsr_od = 0;
else if (! strcasecmp (*argv, "+dsrup"))
o.opt.cor5.dsr_od = 1;
else if (! strncasecmp (*argv, "rfifo=", 6))
o.opt.cor5.rx_thr = atoi (*argv + 6);
/* receive clock option register */
else if (! strcasecmp (*argv, "nrz"))
o.opt.rcor.encod = ENCOD_NRZ;
else if (! strcasecmp (*argv, "nrzi"))
o.opt.rcor.encod = ENCOD_NRZI;
else if (! strcasecmp (*argv, "manchester"))
o.opt.rcor.encod = ENCOD_MANCHESTER;
else if (! strcasecmp (*argv, "-dpll"))
o.opt.rcor.dpll = 0;
else if (! strcasecmp (*argv, "+dpll"))
o.opt.rcor.dpll = 1;
/* transmit clock option register */
else if (! strcasecmp (*argv, "-lloop"))
o.opt.tcor.llm = 0;
else if (! strcasecmp (*argv, "+lloop"))
o.opt.tcor.llm = 1;
else if (! strcasecmp (*argv, "-extclock"))
o.opt.tcor.ext1x = 0;
else if (! strcasecmp (*argv, "+extclock"))
o.opt.tcor.ext1x = 1;
/*
* Mode dependent channel options
*/
else switch (o.mode) {
case M_ASYNC: set_async_opt (*argv); break;
case M_HDLC: set_hdlc_opt (*argv); break;
case M_BISYNC: set_bisync_opt (*argv); break;
case M_X21: set_x21_opt (*argv); break;
}
setchan (channel);
return (0);
}

5
sbin/i386/Makefile Normal file
View File

@ -0,0 +1,5 @@
# $Id$
SUBDIR= cxconfig
.include <bsd.subdir.mk>

View File

@ -0,0 +1,4 @@
PROG = cxconfig
MAN8 = cxconfig.8
.include <bsd.prog.mk>

View File

@ -0,0 +1,297 @@
.TH Cronyx-Sigma 1
.rm ES
.rm EE
.de ES
.PP
.nf
.in +0.5i
..
.de EE
.in -0.5i
.fi
..
.na
.SH NAME
.B cxconfig
\- channel options management utility for Cronyx-Sigma adapter
.SH DESCRIPTION
.PP
The \fBcxconfig\fP utility is used for configuring the channel options of
the Cronyx-Sigma adapter.
.PP
To change cha options the channel should be free: the corresponding
network interface in ``down'' state, the asynchronous terminal device /dev/tty*
closed.
Generally, the channel options are set up during the operating
system startup, for example from the \fI/etc/rc\fP file.
.PP
Note, that not all options have a sense for every particular
case, and an attempt to set some of them can hang up the channel or
the whole adapter.
.SH "Usage"
.IP "cxconfig"
The brief information about all channels.
.IP "cxconfig -a"
The full information about all channels.
.IP "cxconfig <channel>"
The brief information about the channel.
.IP "cxconfig -a <channel>"
The full information about the channel.
.IP "cxconfig <channel> <option>..."
Setting the channel options.
.SH "Channel options"
.IP ispeed=#
Set the receiver baud rate to the number given.
The maximal value is 256000 bits/sec.
In the synchronous mode the receiver baud rate is significant
only when DPLL mode is used.
.IP ospeed=#
Set the transmitter baud rate to the number given.
The maximal value is 256000 bits/sec.
In the synchronous mode the transmitter baud rate is significant
only in the case of the internal clock source.
If receiver and transmitter have equal data rate, then it could
be set by specifying only the numerical argument.
.IP async
Set the asynchronous channel mode.
.IP "hdlc, bisync, bsc, x.21, x21
Set the synchronous channel mode: HDLC, Bisync (BSC) or X.21.
.IP ppp
Set the link-level protocol: PPP/HDLC. The built-in simplified synchronous PPP
implementation is used (see RFC-1548, RFC-1549).
.IP cisco
Set the link-level protocol: Cisco/HDLC (see RFC-1547).
This protocol is intended for compatibility with old models of Cisco routers,
and with early versions of BSD/386 drivers.
The extensive usage of this protocol is not recommended.
.IP ext
Use the external link-level protocol suite (for BSD/386 only).
.IP "+keepalive, -keepalive"
Enable the automatic line state control sub-protocol.
This setting is not significant when the external link-level protocol is used.
.IP "+autorts, -autorts"
Enable the automatic RTS signal control.
When enabled, the RTS signal goes up only when both halves of
the receiver ring buffer are free and ready for receive,
and goes down when one or both buffers are busy.
.IP "port=rs232, port=rs449, port=v35
Set the zero channel hardware interface type.
.SH "Common options"
.IP "nrz, nrzi, manchester
Set the data line signal encoding.
In the case of \fINRZ\fP encoding the zero bit is transmitted by the zero signal
level, the one bit - by the positive signal level.
In the case of \fINRZI\fP encoding the zero bit is transmitted by the change of
the signal level, the one bit - by the constant signal level.
In the case of \fIManchester\fP encoding the zero bit is encoded as 01 value,
the one bit - as 10 value.
.IP "+dpll, -dpll"
Enable the digital phase locked loop mode (DPLL).
When enabled, the receiver timing clock signal
is derived from the received data.
.IP "+lloop, -lloop"
Set the local loopback mode.
.IP "+extclock, -extclock"
Set the timing clock source of synchronous channels. There are
two possible variants: \fIexternal clock\fP source or \fIinternal clock\fP
generation.
.br
\fIExternal clock\fP mode is the most common method for connecting
external modem hardware. In this mode the external timing
signal is received on TXCIN pin of the connector, and it is
used as a synchronization clock for transmitting data (TXD).
.br
In the case of \fIinternal clock\fP mode the transmitted data (TXD)
are synchronized using the internal on-board timing generator,
the internally generated timing signal is driven on the TXCOUT
pin, and the signal on the TXCIN pin is ignored. This mode
is used for direct terminal-to-terminal communication,
e.g. for connecting two computers together in a synchronous mode
via relatively short cable. This method should also be used
for testing channels with an external loopback connector.
.IP fifo=#
FIFO threshold level setup for receiver and transmitter.
.IP rfifo=#
Hardware RTS/CTS flow control FIFO threshold setup.
.IP "+ctsup, -ctsup"
Enable/disable interrupts on CTS (Clear To Send) signal setup (0 to 1 transition).
.IP "+ctsdown, -ctsdown"
Enable/disable interrupts on CTS (Clear To Send) signal clear (1 to 0 transition).
.IP "+cdup, -cdup"
Enable/disable interrupts on CD (Carrier Detect) signal setup (0 to 1 transition).
.IP "+cddown, -cddown"
Enable/disable interrupts on CD (Carrier Detect) signal clear (1 to 0 transition).
.IP "+dsrup, -dsrup"
Enable/disable interrupts on DSR (Data Set Ready) signal setup (0 to 1 transition).
.IP "+dsrdown, -dsrdown"
Enable/disable interrupts on DSR (Data Set Ready) signal clear (1 to 0 transition).
.SH "Asynchronous mode options"
.IP cs#
Select character size: 5, 6, 7 or 8 bits.
.IP "parodd, pareven
Parity mode: odd or even.
.IP "+ignpar, -ignpar
Disable/enable parity detection.
.IP nopar
Disable parity bit generation.
.IP forcepar
Force parity: even - 0, odd - 1.
.IP "stopb1, stopb1.5, stopb2
Use 1 or 1.5 or 2 stop bits per character.
.IP "+dsr, -dsr"
Use the DSR input signal as receiver enable/disable.
.IP "+cts, -cts"
Use the CTS input signal as transmitter enable/disable.
.IP "+rts, -rts"
Drive the RTS output signal as transmitter ready.
.IP "+rloop, -rloop"
Set the remote loopback mode.
.IP "+etc, -etc"
Enable the embedded transmit commands mode.
.IP "+ixon, -ixon"
Enable the hardware XON/XOFF flow control support.
.IP "+ixany, -ixany"
Use the hardware IXANY mode support.
.IP "+sdt, -sdt"
Detect the spec. characters SCHR1 and SCHR2 in the receive data.
.IP "+flowct, -flowct"
Receive the flow control spec. characters as data.
.IP "+rdt, -rdt"
Detect the spec. characters in range SCRL..SCRH in the receive data.
.IP "+exdt, -exdt"
Detect the spec. characters SCHR3 and SCHR4 in the receive data.
.IP "parintr, parnull, parign, pardisc, parffnull
Action on parity errors:
.ES
Mode Action
-----------------------------------------------------
parintr Generate the receiver error interrupt
parnull Input the NULL character
parign Ignore the error, receive as good data
pardisc Ignore the character
parffnull Input the sequence <0xFF, NULL, character>
.EE
.IP "brkintr, brknull, brkdisc
Line break state action:
.ES
Mode Action
---------------------------------------------------
brkintr Generate the receiver error interrupt
brknull Input the NULL character
brkdisc Ignore the line break state
.EE
.IP "+inlcr, -inlcr"
Translate received NL characters to CR.
.IP "+icrnl, -icrnl"
Translate received CR characters to NL.
.IP "+igncr, -igncr"
Ignore received CR characters.
.IP "+ocrnl, -ocrnl"
Translate transmitted CR characters to NL.
.IP "+onlcr, -onlcr"
Translate transmitted NL characters to CR.
.IP "+fcerr, -fcerr"
Process (don't process) the characters, received with errors,
for special character/flow control matching.
.IP "+lnext, -lnext"
Enable the LNEXT character option: the character following
the LNEXT character is not processed for special character/flow
control matching.
.IP "+istrip, -istrip"
Strip input characters to seven bits.
.IP schr1=#
The XON flow control character value.
.IP schr2=#
The XOFF flow control character value.
.IP schr3=#
The SCHR3 spec. character value.
.IP schr4=#
The SCHR4 spec. character value.
.IP "scrl=#, scrh=#
The spec. character range (inclusive).
.IP lnext=#
The LNEXT spec. character value.
.SH "HDLC mode options"
.IP if#
The minimum number of flags transmitted before a frame is started.
.IP noaddr
No frame address recognition.
.IP "addrlen1, addrlen2"
Address field length: 1 or 2 bytes.
.IP "addr1, addr2"
Addressing mode: 4x1 bytes or 2x2 bytes.
Registers RFAR1..RFAR4 should contain the address to be matched.
.IP "+clrdet, -clrdet"
Enable/disable clear detect for X.21 protocol support.
.IP "+dsr, -dsr"
Use the DSR input signal as receiver enable/disable.
.IP "+cts, -cts"
Use the CTS input signal as transmitter enable/disable.
.IP "+rts, -rts"
Drive the RTS output signal as transmitter ready.
.IP "+fcs, -fcs"
Enable/disable the frame checksum generation and checking.
.IP "crc-16, crc-v.41
Select the CRC polynomial: CRC-16 (x^16+x^15+x^2+1)
or CRC V.41 (x^16+x^12+x^5+1).
.IP "fcs-crc-16, fcs-v.41
Frame checksum preset: all zeros (CRC-16) or all ones (CRC V.41).
.IP "+crcinv, -crcinv"
Invert (ie. CRC V.41) or don't invert (ie. CRC-16) the transmitted frame checksum.
.IP "+fcsapd, -fcsapd"
Pass the received CRC to the host at the end of receiver data buffer.
.IP "idlemark, idleflag
Idle mode: idle in mark (transmit all ones) or idle in flag (transmit flag).
.IP "+syn, -syn"
Enable/disable sending pad characters before sending flag when coming out
of the idle mode.
.IP pad#
The number of synchronous characters sent (0..4).
.IP "syn=0xaa, syn=0x00
Send sync pattern.
.IP "rfar1=#, rfar2=#, rfar3=#, rfar4=#
Frame address registers for address recognition.
.SH EXAMPLES
.PP
Set up the channel 7 of the adapter Sigma-400 under FreeBSD.
Physical 4-wire leased line with Zelax+ M115 short-range modems.
Synchronous mode, 128000 bits/sec, interface RS-232,
protocol PPP/HDLC without keepalive support, NRZI encoding,
DPLL mode, no flow control:
.ES
cxconfig cx7 128000 hdlc ppp -keepalive nrzi -cts +dpll -extclock
ifconfig cx7 158.250.244.2 158.250.244.1 up
.EE
.PP
Set up the channel 0 of the adapter Sigma-100 under FreeBSD.
Attachment to the near computer by short cable, internal clock source.
Synchronous mode, 256000 bits/sec, interface RS-232,
protocol Cisco/HDLC with keepalive support:
.ES
cxconfig cx0 hdlc 256000 cisco +keepalive -extclock
ifconfig cx0 200.1.1.1 200.1.1.2 up
.EE
.PP
Set up the channel 1 of the adapter Sigma-840 under BSD/386.
Synchronous 64 kbit/sec leased line, external clock source.
Synchronous mode, interface V.35, external protocol suite:
.ES
cxconfig cx1 hdlc ext
ifconfig cx1 193.124.254.50 193.124.254.49 multicast up
.EE
.PP
Set up the channel 0 of the adapter Sigma-840 under FreeBSD.
Attachment to the Cisco-4000 router by null-modem cable, internal clock source.
Synchronous mode, 64000 bits/sec, interface RS-232,
protocol PPP/HDLC with keepalive support and flow control,
LCP and IPCP protocols (see RFC-1548 and RFC-1332) debug tracing enabled:
.ES
cxconfig cx0 hdlc 64000 port=rs232 ppp +keepalive -extclock +cts
ifconfig cx0 100.0.0.2 100.0.0.1 debug up
.EE
.SH FILES
.IP /dev/cronyx
The special device file for adapter options management.
.SH SEE ALSO
.PP
cx(4)

View File

@ -0,0 +1,704 @@
/*
* Cronyx-Sigma adapter configuration utility for Unix.
*
* Copyright (C) 1994 Cronyx Ltd.
* Author: Serge Vakulenko, <vak@zebub.msk.su>
*
* This software is distributed with NO WARRANTIES, not even the implied
* warranties for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*
* Authors grant any other persons or organisations permission to use
* or modify this software as long as this message is kept with the software,
* all derivative works or modified versions.
*
* Version 1.1, Wed Oct 26 16:08:09 MSK 1994
*
* Usage:
* cxconfig [-a]
* -- print status of all channels
* cxconfig [-a] <channel>
* -- print status of the channel
* cxconfig <channel> <option>...
* -- set channel options
*/
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <sys/cronyx.h>
#include <net/if.h>
#include <stdio.h>
#define CXDEV "/dev/cronyx"
#define atoi(a) strtol((a), (char**)0, 0)
cx_options_t o;
int aflag;
char *symbol (unsigned char sym)
{
static char buf[40];
if (sym < ' ')
sprintf (buf, "^%c", sym+0100);
else if (sym == '\\')
strcat (buf, "\\\\");
else if (sym < 127)
sprintf (buf, "%c", sym);
else
sprintf (buf, "\\%03o", sym);
return (buf);
}
unsigned char atosym (char *s)
{
unsigned char c;
if (*s == '^')
return (*++s & 037);
if (*s == '\\')
return (strtol (++s, 0, 8));
return (*s);
}
void usage ()
{
printf ("Cronyx-Sigma Adapter Configuration Utility, Version 1.0\n");
printf ("Copyright (C) 1994 Cronyx Ltd.\n");
printf ("Usage:\n");
printf ("\tcxconfig [-a]\n");
printf ("\t\t-- print status of all channels\n");
printf ("\tcxconfig [-a] <channel>\n");
printf ("\t\t-- print status of the channel\n");
printf ("\tcxconfig <channel> [async | hdlc | bisync | x.21] [ispeed #] [ospeed #]\n");
printf ("\t\t[+cts | -cts]\n");
printf ("\t\t-- set channel options\n");
exit (1);
}
char *chantype (int type)
{
switch (type) {
case T_NONE: return ("none");
case T_ASYNC: return ("RS-232");
case T_UNIV_RS232: return ("RS-232");
case T_UNIV_RS449: return ("RS-232/RS-449");
case T_UNIV_V35: return ("RS-232/V.35");
case T_SYNC_RS232: return ("RS-232");
case T_SYNC_V35: return ("V.35");
case T_SYNC_RS449: return ("RS-449");
}
}
char *chanmode (int mode)
{
switch (mode) {
case M_ASYNC: return ("Async");
case M_HDLC: return ("HDLC");
case M_BISYNC: return ("Bisync");
case M_X21: return ("X.21");
default: return ("???");
}
}
void getchan (int channel)
{
int s = open (CXDEV, 0);
if (s < 0) {
perror (CXDEV);
exit (1);
}
o.board = channel/NCHAN;
o.channel = channel%NCHAN;
if (ioctl (s, CXIOCGETMODE, (caddr_t)&o) < 0) {
perror ("cxconfig: CXIOCGETMODE");
exit (1);
}
close (s);
if (o.type == T_NONE) {
fprintf (stderr, "cx%d: channel %d not configured\n", o.board,
o.channel);
exit (1);
}
}
void setchan (int channel)
{
int s = open (CXDEV, 0);
if (s < 0) {
perror (CXDEV);
exit (1);
}
o.board = channel/NCHAN;
o.channel = channel%NCHAN;
if (ioctl (s, CXIOCSETMODE, (caddr_t)&o) < 0) {
perror ("cxconfig: CXIOCSETMODE");
exit (1);
}
close (s);
}
void printopt ()
{
/* Common channel options */
/* channel option register 4 */
printf ("\t");
printf ("fifo=%d ", o.opt.cor4.thr); /* FIFO threshold */
printf ("%cctsdown ", o.opt.cor4.cts_zd ? '+' : '-'); /* detect 1 to 0 transition on the CTS */
printf ("%ccddown ", o.opt.cor4.cd_zd ? '+' : '-'); /* detect 1 to 0 transition on the CD */
printf ("%cdsrdown ", o.opt.cor4.dsr_zd ? '+' : '-'); /* detect 1 to 0 transition on the DSR */
printf ("\n");
/* channel option register 5 */
printf ("\t");
printf ("rfifo=%d ", o.opt.cor5.rx_thr); /* receive flow control FIFO threshold */
printf ("%cctsup ", o.opt.cor5.cts_od ? '+' : '-'); /* detect 0 to 1 transition on the CTS */
printf ("%ccdup ", o.opt.cor5.cd_od ? '+' : '-'); /* detect 0 to 1 transition on the CD */
printf ("%cdsrup ", o.opt.cor5.dsr_od ? '+' : '-'); /* detect 0 to 1 transition on the DSR */
printf ("\n");
/* receive clock option register */
printf ("\t");
printf ("%s ", o.opt.rcor.encod == ENCOD_NRZ ? "nrz" : /* signal encoding */
o.opt.rcor.encod == ENCOD_NRZI ? "nrzi" :
o.opt.rcor.encod == ENCOD_MANCHESTER ? "manchester" : "???");
printf ("%cdpll ", o.opt.rcor.dpll ? '+' : '-'); /* DPLL enable */
/* transmit clock option register */
printf ("%clloop ", o.opt.tcor.llm ? '+' : '-'); /* local loopback mode */
printf ("%cextclock ", o.opt.tcor.ext1x ? '+' : '-'); /* external 1x clock mode */
printf ("\n");
switch (o.mode) {
case M_ASYNC: /* async mode options */
/* channel option register 1 */
printf ("\t");
printf ("cs%d ", o.aopt.cor1.charlen+1); /* character length, 5..8 */
printf ("par%s ", o.aopt.cor1.parity ? "odd" : "even"); /* parity */
printf ("%cignpar ", o.aopt.cor1.ignpar ? '+' : '-'); /* ignore parity */
if (o.aopt.cor1.parmode != PARM_NORMAL) /* parity mode */
printf ("%s ", o.aopt.cor1.parmode == PARM_NOPAR ? "nopar" :
o.aopt.cor1.parmode == PARM_FORCE ? "forcepar" : "???");
printf ("\n");
/* channel option register 2 */
printf ("\t");
printf ("%cdsr ", o.aopt.cor2.dsrae ? '+' : '-'); /* DSR automatic enable */
printf ("%ccts ", o.aopt.cor2.ctsae ? '+' : '-'); /* CTS automatic enable */
printf ("%crts ", o.aopt.cor2.rtsao ? '+' : '-'); /* RTS automatic output enable */
printf ("%crloop ", o.aopt.cor2.rlm ? '+' : '-'); /* remote loopback mode enable */
printf ("%cetc ", o.aopt.cor2.etc ? '+' : '-'); /* embedded transmitter cmd enable */
printf ("%cxon ", o.aopt.cor2.ixon ? '+' : '-'); /* in-band XON/XOFF enable */
printf ("%cxany ", o.aopt.cor2.ixany ? '+' : '-'); /* XON on any character */
printf ("\n");
/* option register 3 */
printf ("\t");
printf ("%s ", o.aopt.cor3.stopb == STOPB_1 ? "stopb1" : /* stop bit length */
o.aopt.cor3.stopb == STOPB_15 ? "stopb1.5" :
o.aopt.cor3.stopb == STOPB_2 ? "stopb2" : "???");
printf ("%csdt ", o.aopt.cor3.scde ? '+' : '-'); /* special char detection enable */
printf ("%cflowct ", o.aopt.cor3.flowct ? '+' : '-'); /* flow control transparency mode */
printf ("%crdt ", o.aopt.cor3.rngde ? '+' : '-'); /* range detect enable */
printf ("%cexdt ", o.aopt.cor3.escde ? '+' : '-'); /* extended spec. char detect enable */
printf ("\n");
/* channel option register 6 */
printf ("\t");
printf ("%s ", o.aopt.cor6.parerr == PERR_INTR ? "parintr" : /* parity/framing error actions */
o.aopt.cor6.parerr == PERR_NULL ? "parnull" :
o.aopt.cor6.parerr == PERR_IGNORE ? "parign" :
o.aopt.cor6.parerr == PERR_DISCARD ? "pardisc" :
o.aopt.cor6.parerr == PERR_FFNULL ? "parffnull" : "???");
printf ("%s ", o.aopt.cor6.brk == BRK_INTR ? "brkintr" : /* action on break condition */
o.aopt.cor6.brk == BRK_NULL ? "brknull" :
o.aopt.cor6.brk == BRK_DISCARD ? "brkdisc" : "???");
printf ("%cinlcr ", o.aopt.cor6.inlcr ? '+' : '-'); /* translate NL to CR on input */
printf ("%cicrnl ", o.aopt.cor6.icrnl ? '+' : '-'); /* translate CR to NL on input */
printf ("%cigncr ", o.aopt.cor6.igncr ? '+' : '-'); /* discard CR on input */
printf ("\n");
/* channel option register 7 */
printf ("\t");
printf ("%cocrnl ", o.aopt.cor7.ocrnl ? '+' : '-'); /* translate CR to NL on output */
printf ("%conlcr ", o.aopt.cor7.onlcr ? '+' : '-'); /* translate NL to CR on output */
printf ("%cfcerr ", o.aopt.cor7.fcerr ? '+' : '-'); /* process flow ctl err chars enable */
printf ("%clnext ", o.aopt.cor7.lnext ? '+' : '-'); /* LNext option enable */
printf ("%cistrip ", o.aopt.cor7.istrip ? '+' : '-'); /* strip 8-bit on input */
printf ("\n");
printf ("\t");
printf ("schr1=%s ", symbol (o.aopt.schr1)); /* special character register 1 (XON) */
printf ("schr2=%s ", symbol (o.aopt.schr2)); /* special character register 2 (XOFF) */
printf ("schr3=%s ", symbol (o.aopt.schr3)); /* special character register 3 */
printf ("schr4=%s ", symbol (o.aopt.schr4)); /* special character register 4 */
printf ("scrl=%s ", symbol (o.aopt.scrl)); /* special character range low */
printf ("scrh=%s ", symbol (o.aopt.scrh)); /* special character range high */
printf ("lnext=%s ", symbol (o.aopt.lnxt)); /* LNext character */
printf ("\n");
break;
case M_HDLC: /* hdlc mode options */
/* hdlc channel option register 1 */
printf ("\t");
printf ("if%d ", o.hopt.cor1.ifflags); /* number of inter-frame flags sent */
printf ("%s ", o.hopt.cor1.admode == ADMODE_NOADDR ? "noaddr" : /* addressing mode */
o.hopt.cor1.admode == ADMODE_4_1 ? "addr1" :
o.hopt.cor1.admode == ADMODE_2_2 ? "addr2" : "???");
printf ("%cclrdet ", o.hopt.cor1.clrdet ? '+' : '-'); /* clear detect for X.21 data transfer phase */
printf ("addrlen%d ", o.hopt.cor1.aflo + 1); /* address field length option */
printf ("\n");
/* hdlc channel option register 2 */
printf ("\t");
printf ("%cdsr ", o.hopt.cor2.dsrae ? '+' : '-'); /* DSR automatic enable */
printf ("%ccts ", o.hopt.cor2.ctsae ? '+' : '-'); /* CTS automatic enable */
printf ("%crts ", o.hopt.cor2.rtsao ? '+' : '-'); /* RTS automatic output enable */
printf ("%ccrcinv ", o.hopt.cor2.crcninv ? '-' : '+'); /* CRC invertion option */
printf ("%cfcsapd ", o.hopt.cor2.fcsapd ? '+' : '-'); /* FCS append */
printf ("\n");
/* hdlc channel option register 3 */
printf ("\t");
printf ("pad%d ", o.hopt.cor3.padcnt); /* pad character count */
printf ("idle%s ", o.hopt.cor3.idle ? "mark" : "flag"); /* idle mode */
printf ("%cfcs ", o.hopt.cor3.nofcs ? '-' : '+'); /* FCS disable */
printf ("fcs-%s ", o.hopt.cor3.fcspre ? "crc-16" : "v.41"); /* FCS preset */
printf ("syn=%s ", o.hopt.cor3.syncpat ? "0xAA" : "0x00"); /* send sync pattern */
printf ("%csyn ", o.hopt.cor3.sndpad ? '+' : '-'); /* send pad characters before flag enable */
printf ("\n");
printf ("\t");
printf ("rfar1=0x%02x ", o.hopt.rfar1); /* receive frame address register 1 */
printf ("rfar2=0x%02x ", o.hopt.rfar2); /* receive frame address register 2 */
printf ("rfar3=0x%02x ", o.hopt.rfar3); /* receive frame address register 3 */
printf ("rfar4=0x%02x ", o.hopt.rfar4); /* receive frame address register 4 */
printf ("crc-%s ", o.hopt.cpsr ? "16" : "v.41"); /* CRC polynomial select */
printf ("\n");
break;
case M_BISYNC: /* bisync mode options */
/* channel option register 1 */
printf ("\t");
printf ("cs%d ", o.bopt.cor1.charlen+1); /* character length, 5..8 */
printf ("par%s ", o.bopt.cor1.parity ? "odd" : "even"); /* parity */
printf ("%cignpar ", o.bopt.cor1.ignpar ? '+' : '-'); /* ignore parity */
if (o.bopt.cor1.parmode != PARM_NORMAL) /* parity mode */
printf ("%s ", o.bopt.cor1.parmode == PARM_NOPAR ? "nopar" :
o.bopt.cor1.parmode == PARM_FORCE ? "forcepar" : "???");
printf ("\n");
/* channel option register 2 */
printf ("\t");
printf ("syn%d ", o.bopt.cor2.syns+2); /* number of extra SYN chars before a frame */
printf ("%ccrcinv ", o.bopt.cor2.crcninv ? '-' : '+'); /* CRC invertion option */
printf ("%s ", o.bopt.cor2.ebcdic ? "ebcdic" : "ascii"); /* use EBCDIC as char set (instead of ASCII) */
printf ("%cbccapd ", o.bopt.cor2.bcc ? '+' : '-'); /* BCC append enable */
printf ("%s ", o.bopt.cor2.lrc ? "lrc" : "crc-16"); /* longitudinal redundancy check */
printf ("\n");
/* channel option register 3 */
printf ("\t");
printf ("pad%d ", o.bopt.cor3.padcnt); /* pad character count */
printf ("idle%s ", o.bopt.cor3.idle ? "mark" : "syn"); /* idle mode */
printf ("%cfcs ", o.bopt.cor3.nofcs ? '-' : '+'); /* FCS disable */
printf ("fcs-%s ", o.bopt.cor3.fcspre ? "crc-16" : "v.41"); /* FCS preset */
printf ("syn=%s ", o.bopt.cor3.padpat ? "0x55" : "0xAA"); /* send sync pattern */
printf ("%csyn ", o.bopt.cor3.sndpad ? '+' : '-'); /* send pad characters before flag enable */
printf ("\n");
/* channel option register 6 */
printf ("\t");
printf ("specterm=%s ", symbol (o.bopt.cor6.specterm)); /* special termination character */
printf ("crc-%s ", o.bopt.cpsr ? "16" : "v.41"); /* CRC polynomial select */
printf ("\n");
break;
case M_X21: /* x.21 mode options */
/* channel option register 1 */
printf ("\t");
printf ("cs%d ", o.xopt.cor1.charlen+1); /* character length, 5..8 */
printf ("par%s ", o.xopt.cor1.parity ? "odd" : "even"); /* parity */
printf ("%cignpar ", o.xopt.cor1.ignpar ? '+' : '-'); /* ignore parity */
if (o.xopt.cor1.parmode != PARM_NORMAL) /* parity mode */
printf ("%s ", o.xopt.cor1.parmode == PARM_NOPAR ? "nopar" :
o.xopt.cor1.parmode == PARM_FORCE ? "forcepar" : "???");
printf ("\n");
/* channel option register 2 */
printf ("\t");
printf ("%cetc ", o.xopt.cor2.etc ? '+' : '-'); /* embedded transmitter cmd enable */
/* channel option register 3 */
printf ("%csdt ", o.xopt.cor3.scde ? '+' : '-'); /* special char detection enable */
printf ("%cstripsyn ", o.xopt.cor3.stripsyn ? '+' : '-'); /* treat SYN chars as special condition */
printf ("%cssdt ", o.xopt.cor3.ssde ? '+' : '-'); /* steady state detect enable */
printf ("syn%c ", o.xopt.cor3.syn ? '1' : '2'); /* the number of SYN chars on receive */
printf ("\n");
/* channel option register 6 */
printf ("\t");
printf ("syn=%s ", symbol (o.xopt.cor6.synchar)); /* syn character */
printf ("schr1=%s ", symbol (o.xopt.schr1)); /* special character register 1 */
printf ("schr2=%s ", symbol (o.xopt.schr2)); /* special character register 2 */
printf ("schr3=%s ", symbol (o.xopt.schr3)); /* special character register 3 */
printf ("\n");
break;
}
}
void printchan (int channel)
{
printf ("cx%d (%s) %s", channel, chantype (o.type), chanmode (o.mode));
if (o.txbaud == o.rxbaud)
printf (" %d", o.rxbaud);
else
printf (" ospeed=%d ispeed=%d", o.txbaud, o.rxbaud);
if ((o.channel == 0 || o.channel == 8) &&
(o.type == T_UNIV_V35 || o.type == T_UNIV_RS449))
printf (" port=%s", o.iftype ? (o.type == T_UNIV_V35 ?
"v35" : "rs449") : "rs232");
printf (o.sopt.ext ? " ext" : o.sopt.cisco ? " cisco" : " ppp");
printf (" %ckeepalive", o.sopt.keepalive ? '+' : '-');
printf (" %cautorts", o.sopt.norts ? '-' : '+');
printf ("\n");
if (aflag)
printopt ();
}
void printall ()
{
struct ifconf ifc;
struct ifreq *ifr;
char buf[BUFSIZ], *cp;
int s, c;
s = socket (AF_INET, SOCK_DGRAM, 0);
if (s < 0) {
perror ("cxconfig: socket");
exit (1);
}
ifc.ifc_len = sizeof (buf);
ifc.ifc_buf = buf;
if (ioctl (s, SIOCGIFCONF, (caddr_t)&ifc) < 0) {
perror ("cxconfig: SIOCGIFCONF");
exit (1);
}
close (s);
s = open (CXDEV, 0);
if (s < 0) {
perror (CXDEV);
exit (1);
}
ifr = ifc.ifc_req;
#define max(a,b) ((a)>(b) ? (a) : (b))
#define size(p) max((p).sa_len, sizeof(p))
for (cp=buf; cp<buf+ifc.ifc_len; cp+=sizeof(ifr->ifr_name)+size(ifr->ifr_addr)) {
ifr = (struct ifreq*) cp;
if (ifr->ifr_addr.sa_family != AF_LINK)
continue;
if (strncmp (ifr->ifr_name, "cx", 2) != 0)
continue;
c = atoi (ifr->ifr_name + 2);
o.board = c/NCHAN;
o.channel = c%NCHAN;
if (ioctl (s, CXIOCGETMODE, (caddr_t)&o) < 0) {
perror ("cxconfig: CXIOCGETMODE");
exit (1);
}
printchan (c);
}
close (s);
}
void set_interface_type (char *type)
{
if (o.channel != 0 && o.channel != 8) {
printf ("interface option is applicable only for channels 0 and 8\n");
exit (1);
}
if (o.type != T_UNIV_V35 && o.type != T_UNIV_RS449) {
printf ("interface option is applicable only for universal channels\n");
exit (1);
}
if (! strcasecmp (type, "port=rs232"))
o.iftype = 0;
else
o.iftype = 1;
}
void set_async_opt (char *opt)
{
/* channel option register 1 */
if (! strncasecmp (opt, "cs", 2)) o.aopt.cor1.charlen = atoi (opt + 2) - 1;
else if (! strcasecmp (opt, "parodd")) o.aopt.cor1.parity = 1;
else if (! strcasecmp (opt, "pareven")) o.aopt.cor1.parity = 0;
else if (! strcasecmp (opt, "-ignpar")) o.aopt.cor1.ignpar = 0;
else if (! strcasecmp (opt, "+ignpar")) o.aopt.cor1.ignpar = 1;
else if (! strcasecmp (opt, "nopar")) o.aopt.cor1.parmode = PARM_NOPAR;
else if (! strcasecmp (opt, "forcepar")) o.aopt.cor1.parmode = PARM_FORCE;
/* channel option register 2 */
else if (! strcasecmp (opt, "-dsr")) o.aopt.cor2.dsrae = 0;
else if (! strcasecmp (opt, "+dsr")) o.aopt.cor2.dsrae = 1;
else if (! strcasecmp (opt, "-cts")) o.aopt.cor2.ctsae = 0;
else if (! strcasecmp (opt, "+cts")) o.aopt.cor2.ctsae = 1;
else if (! strcasecmp (opt, "-rts")) o.aopt.cor2.rtsao = 0;
else if (! strcasecmp (opt, "+rts")) o.aopt.cor2.rtsao = 1;
else if (! strcasecmp (opt, "-rloop")) o.aopt.cor2.rlm = 0;
else if (! strcasecmp (opt, "+rloop")) o.aopt.cor2.rlm = 1;
else if (! strcasecmp (opt, "-etc")) o.aopt.cor2.etc = 0;
else if (! strcasecmp (opt, "+etc")) o.aopt.cor2.etc = 1;
else if (! strcasecmp (opt, "-ixon")) o.aopt.cor2.ixon = 0;
else if (! strcasecmp (opt, "+ixon")) o.aopt.cor2.ixon = 1;
else if (! strcasecmp (opt, "-ixany")) o.aopt.cor2.ixany = 0;
else if (! strcasecmp (opt, "+ixany")) o.aopt.cor2.ixany = 1;
/* option register 3 */
else if (! strcasecmp (opt, "stopb1")) o.aopt.cor3.stopb = STOPB_1;
else if (! strcasecmp (opt, "stopb1.5")) o.aopt.cor3.stopb = STOPB_15;
else if (! strcasecmp (opt, "stopb2")) o.aopt.cor3.stopb = STOPB_2;
else if (! strcasecmp (opt, "-sdt")) o.aopt.cor3.scde = 0;
else if (! strcasecmp (opt, "+sdt")) o.aopt.cor3.scde = 1;
else if (! strcasecmp (opt, "-flowct")) o.aopt.cor3.flowct = 0;
else if (! strcasecmp (opt, "+flowct")) o.aopt.cor3.flowct = 1;
else if (! strcasecmp (opt, "-rdt")) o.aopt.cor3.rngde = 0;
else if (! strcasecmp (opt, "+rdt")) o.aopt.cor3.rngde = 1;
else if (! strcasecmp (opt, "-exdt")) o.aopt.cor3.escde = 0;
else if (! strcasecmp (opt, "+exdt")) o.aopt.cor3.escde = 1;
/* channel option register 6 */
else if (! strcasecmp (opt, "parintr")) o.aopt.cor6.parerr = PERR_INTR;
else if (! strcasecmp (opt, "parnull")) o.aopt.cor6.parerr = PERR_NULL;
else if (! strcasecmp (opt, "parign")) o.aopt.cor6.parerr = PERR_IGNORE;
else if (! strcasecmp (opt, "pardisc")) o.aopt.cor6.parerr = PERR_DISCARD;
else if (! strcasecmp (opt, "parffnull")) o.aopt.cor6.parerr = PERR_FFNULL;
else if (! strcasecmp (opt, "brkintr")) o.aopt.cor6.brk = BRK_INTR;
else if (! strcasecmp (opt, "brknull")) o.aopt.cor6.brk = BRK_NULL;
else if (! strcasecmp (opt, "brkdisc")) o.aopt.cor6.brk = BRK_DISCARD;
else if (! strcasecmp (opt, "-inlcr")) o.aopt.cor6.inlcr = 0;
else if (! strcasecmp (opt, "+inlcr")) o.aopt.cor6.inlcr = 1;
else if (! strcasecmp (opt, "-icrnl")) o.aopt.cor6.icrnl = 0;
else if (! strcasecmp (opt, "+icrnl")) o.aopt.cor6.icrnl = 1;
else if (! strcasecmp (opt, "-igncr")) o.aopt.cor6.igncr = 0;
else if (! strcasecmp (opt, "+igncr")) o.aopt.cor6.igncr = 1;
/* channel option register 7 */
else if (! strcasecmp (opt, "-ocrnl")) o.aopt.cor7.ocrnl = 0;
else if (! strcasecmp (opt, "+ocrnl")) o.aopt.cor7.ocrnl = 1;
else if (! strcasecmp (opt, "-onlcr")) o.aopt.cor7.onlcr = 0;
else if (! strcasecmp (opt, "+onlcr")) o.aopt.cor7.onlcr = 1;
else if (! strcasecmp (opt, "-fcerr")) o.aopt.cor7.fcerr = 0;
else if (! strcasecmp (opt, "+fcerr")) o.aopt.cor7.fcerr = 1;
else if (! strcasecmp (opt, "-lnext")) o.aopt.cor7.lnext = 0;
else if (! strcasecmp (opt, "+lnext")) o.aopt.cor7.lnext = 1;
else if (! strcasecmp (opt, "-istrip")) o.aopt.cor7.istrip = 0;
else if (! strcasecmp (opt, "+istrip")) o.aopt.cor7.istrip = 1;
else if (! strncasecmp (opt, "schr1=", 6)) o.aopt.schr1 = atosym (opt+6);
else if (! strncasecmp (opt, "schr2=", 6)) o.aopt.schr2 = atosym (opt+6);
else if (! strncasecmp (opt, "schr3=", 6)) o.aopt.schr3 = atosym (opt+6);
else if (! strncasecmp (opt, "schr4=", 6)) o.aopt.schr4 = atosym (opt+6);
else if (! strncasecmp (opt, "scrl=", 5)) o.aopt.scrl = atosym (opt+5);
else if (! strncasecmp (opt, "scrh=", 5)) o.aopt.scrh = atosym (opt+5);
else if (! strncasecmp (opt, "lnext=", 6)) o.aopt.lnxt = atosym (opt+6);
else
usage ();
}
void set_hdlc_opt (char *opt)
{
/* hdlc channel option register 1 */
if (! strncasecmp (opt, "if", 2)) o.hopt.cor1.ifflags = atoi (opt + 2);
else if (! strcasecmp (opt, "noaddr")) o.hopt.cor1.admode = ADMODE_NOADDR;
else if (! strcasecmp (opt, "addr1")) o.hopt.cor1.admode = ADMODE_4_1;
else if (! strcasecmp (opt, "addr2")) o.hopt.cor1.admode = ADMODE_2_2;
else if (! strcasecmp (opt, "-clrdet")) o.hopt.cor1.clrdet = 0;
else if (! strcasecmp (opt, "+clrdet")) o.hopt.cor1.clrdet = 1;
else if (! strcasecmp (opt, "addrlen1")) o.hopt.cor1.aflo = 0;
else if (! strcasecmp (opt, "addrlen2")) o.hopt.cor1.aflo = 1;
/* hdlc channel option register 2 */
else if (! strcasecmp (opt, "-dsr")) o.hopt.cor2.dsrae = 0;
else if (! strcasecmp (opt, "+dsr")) o.hopt.cor2.dsrae = 1;
else if (! strcasecmp (opt, "-cts")) o.hopt.cor2.ctsae = 0;
else if (! strcasecmp (opt, "+cts")) o.hopt.cor2.ctsae = 1;
else if (! strcasecmp (opt, "-rts")) o.hopt.cor2.rtsao = 0;
else if (! strcasecmp (opt, "+rts")) o.hopt.cor2.rtsao = 1;
else if (! strcasecmp (opt, "-fcsapd")) o.hopt.cor2.fcsapd = 0;
else if (! strcasecmp (opt, "+fcsapd")) o.hopt.cor2.fcsapd = 1;
else if (! strcasecmp (opt, "-crcinv")) o.hopt.cor2.crcninv = 1;
else if (! strcasecmp (opt, "+crcinv")) o.hopt.cor2.crcninv = 0;
/* hdlc channel option register 3 */
else if (! strncasecmp (opt, "pad", 3)) o.hopt.cor3.padcnt = atoi (opt + 3);
else if (! strcasecmp (opt, "idlemark")) o.hopt.cor3.idle = 1;
else if (! strcasecmp (opt, "idleflag")) o.hopt.cor3.idle = 0;
else if (! strcasecmp (opt, "-fcs")) o.hopt.cor3.nofcs = 1;
else if (! strcasecmp (opt, "+fcs")) o.hopt.cor3.nofcs = 0;
else if (! strcasecmp (opt, "fcs-crc-16")) o.hopt.cor3.fcspre = 1;
else if (! strcasecmp (opt, "fcs-v.41")) o.hopt.cor3.fcspre = 0;
else if (! strcasecmp (opt, "syn=0xaa")) o.hopt.cor3.syncpat = 1;
else if (! strcasecmp (opt, "syn=0x00")) o.hopt.cor3.syncpat = 0;
else if (! strcasecmp (opt, "-syn")) o.hopt.cor3.sndpad = 0;
else if (! strcasecmp (opt, "+syn")) o.hopt.cor3.sndpad = 1;
else if (! strncasecmp (opt, "rfar1=", 6)) o.hopt.rfar1 = atoi (opt + 6);
else if (! strncasecmp (opt, "rfar2=", 6)) o.hopt.rfar2 = atoi (opt + 6);
else if (! strncasecmp (opt, "rfar3=", 6)) o.hopt.rfar3 = atoi (opt + 6);
else if (! strncasecmp (opt, "rfar4=", 6)) o.hopt.rfar4 = atoi (opt + 6);
else if (! strcasecmp (opt, "crc-16")) o.hopt.cpsr = 1;
else if (! strcasecmp (opt, "crc-v.41")) o.hopt.cpsr = 0;
else usage ();
}
void set_bisync_opt (char *opt)
{
usage ();
}
void set_x21_opt (char *opt)
{
usage ();
}
int main (int argc, char **argv)
{
int channel;
for (--argc, ++argv; argc>0 && **argv=='-'; --argc, ++argv)
if (! strcasecmp (*argv, "-a"))
++aflag;
else
usage ();
if (argc <= 0) {
printall ();
return (0);
}
if (argv[0][0]=='c' && argv[0][1]=='x')
*argv += 2;
if (**argv<'0' || **argv>'9')
usage ();
channel = atoi (*argv);
--argc, ++argv;
getchan (channel);
if (argc <= 0) {
printchan (channel);
return (0);
}
for (; argc>0; --argc, ++argv)
if (**argv == '(')
continue;
else if (! strncasecmp (*argv, "ispeed=", 7))
o.rxbaud = atoi (*argv+7);
else if (! strncasecmp (*argv, "ospeed=", 7))
o.txbaud = atoi (*argv+7);
else if (! strcasecmp (*argv, "async"))
o.mode = M_ASYNC;
else if (! strcasecmp (*argv, "hdlc"))
o.mode = M_HDLC;
else if (! strcasecmp (*argv, "bisync") ||
! strcasecmp (*argv, "bsc"))
o.mode = M_BISYNC;
else if (! strcasecmp (*argv, "x.21") ||
! strcasecmp (*argv, "x21"))
o.mode = M_X21;
else if (**argv>='0' && **argv<='9')
o.txbaud = o.rxbaud = atoi (*argv);
else if (! strcasecmp (*argv, "cisco")) {
o.sopt.cisco = 1;
o.sopt.ext = 0;
} else if (! strcasecmp (*argv, "ppp")) {
o.sopt.cisco = 0;
o.sopt.ext = 0;
} else if (! strcasecmp (*argv, "ext"))
o.sopt.ext = 1;
else if (! strcasecmp (*argv, "+keepalive"))
o.sopt.keepalive = 1;
else if (! strcasecmp (*argv, "-keepalive"))
o.sopt.keepalive = 0;
else if (! strcasecmp (*argv, "+autorts"))
o.sopt.norts = 0;
else if (! strcasecmp (*argv, "-autorts"))
o.sopt.norts = 1;
else if (! strcasecmp (*argv, "port=rs232") ||
! strcasecmp (*argv, "port=rs449") ||
! strcasecmp (*argv, "port=v35"))
set_interface_type (*argv);
/*
* Common channel options
*/
/* channel option register 4 */
else if (! strcasecmp (*argv, "-ctsdown"))
o.opt.cor4.cts_zd = 0;
else if (! strcasecmp (*argv, "+ctsdown"))
o.opt.cor4.cts_zd = 1;
else if (! strcasecmp (*argv, "-cddown"))
o.opt.cor4.cd_zd = 0;
else if (! strcasecmp (*argv, "+cddown"))
o.opt.cor4.cd_zd = 1;
else if (! strcasecmp (*argv, "-dsrdown"))
o.opt.cor4.dsr_zd = 0;
else if (! strcasecmp (*argv, "+dsrdown"))
o.opt.cor4.dsr_zd = 1;
else if (! strncasecmp (*argv, "fifo=", 5))
o.opt.cor4.thr = atoi (*argv + 5);
/* channel option register 5 */
else if (! strcasecmp (*argv, "-ctsup"))
o.opt.cor5.cts_od = 0;
else if (! strcasecmp (*argv, "+ctsup"))
o.opt.cor5.cts_od = 1;
else if (! strcasecmp (*argv, "-cdup"))
o.opt.cor5.cd_od = 0;
else if (! strcasecmp (*argv, "+cdup"))
o.opt.cor5.cd_od = 1;
else if (! strcasecmp (*argv, "-dsrup"))
o.opt.cor5.dsr_od = 0;
else if (! strcasecmp (*argv, "+dsrup"))
o.opt.cor5.dsr_od = 1;
else if (! strncasecmp (*argv, "rfifo=", 6))
o.opt.cor5.rx_thr = atoi (*argv + 6);
/* receive clock option register */
else if (! strcasecmp (*argv, "nrz"))
o.opt.rcor.encod = ENCOD_NRZ;
else if (! strcasecmp (*argv, "nrzi"))
o.opt.rcor.encod = ENCOD_NRZI;
else if (! strcasecmp (*argv, "manchester"))
o.opt.rcor.encod = ENCOD_MANCHESTER;
else if (! strcasecmp (*argv, "-dpll"))
o.opt.rcor.dpll = 0;
else if (! strcasecmp (*argv, "+dpll"))
o.opt.rcor.dpll = 1;
/* transmit clock option register */
else if (! strcasecmp (*argv, "-lloop"))
o.opt.tcor.llm = 0;
else if (! strcasecmp (*argv, "+lloop"))
o.opt.tcor.llm = 1;
else if (! strcasecmp (*argv, "-extclock"))
o.opt.tcor.ext1x = 0;
else if (! strcasecmp (*argv, "+extclock"))
o.opt.tcor.ext1x = 1;
/*
* Mode dependent channel options
*/
else switch (o.mode) {
case M_ASYNC: set_async_opt (*argv); break;
case M_HDLC: set_hdlc_opt (*argv); break;
case M_BISYNC: set_bisync_opt (*argv); break;
case M_X21: set_x21_opt (*argv); break;
}
setchan (channel);
return (0);
}

View File

@ -0,0 +1,239 @@
.TH Cronyx-Sigma 1
.rm ES
.rm EE
.de ES
.PP
.nf
.in +0.5i
..
.de EE
.in -0.5i
.fi
..
.na
.SH NAME
.B cx
\- asynchronous Cronyx-Sigma adapter driver
.br
.B if_cx
\- synchronous Cronyx-Sigma adapter driver
.SH CONFIGURATION
.B
device cx0 at isa? port 0x240 irq 15 drq 7
.br
.B
device cx1 at isa? port 0x260 irq 12 drq 6
.br
.B
pseudo-device sppp
.P
The base i/o port address should be set by jumpers on the board.
The DMA i/o channel and interrupt request numbers are configured
by software at adapter initialization. Legal values are:
.IP Port
0x240, 0x260, 0x280, 0x300, 0x320, 0x380
.IP IRQ
3, 5, 7, 10, 11, 12, 15
.IP DMA
5, 6, 7
.SH DESCRIPTION
.PP
The Cronyx-Sigma driver supports the adapters of models 100,
400, 500, 401, 404, 410, 440, 703, 801, 810, 840. Different models have
different set of channels:
.ES
Model Channels
----------------------------------------------
Cronyx-Sigma-100 0
Cronyx-Sigma-400 4, 5, 6, 7
Cronyx-Sigma-500 0, 4, 5, 6, 7
Cronyx-Sigma-401 0, 1, 2, 3
Cronyx-Sigma-404 0, 1, 2, 3
Cronyx-Sigma-410 0, 1, 2, 3
Cronyx-Sigma-440 0, 1, 2, 3
Cronyx-Sigma-703 0, 1, 2, 4, 5, 6, 7
Cronyx-Sigma-801 0, 1, 2, 3, 4, 5, 6, 7
Cronyx-Sigma-810 0, 1, 2, 3, 4, 5, 6, 7
Cronyx-Sigma-840 0, 1, 2, 3, 4, 5, 6, 7
.EE
.PP
A pair of two adapters can be united together by the special
short inter-board cable. Two united adapters use the same
IRQ and DMA channels and from the point of driver works
as the single 16-channel multiplexer. One of the united
boards is ``master'' and the other is ``slave''.
.PP
The channels of the slave united board are numbered by the driver
beginning with 8, for example, the united adapter of the model 100/500
has channels 0, 8, 12, 13, 14, 15.
.PP
The channels which have the RS-232 interface can be used
both in synchronous and asynchronous modes (software selectable
by cxconfig utility) and hence are called ``universal'' channels.
.PP
The special device files (/dev/*) for the adapter Cronyx-Sigma
are created by the command file ``/dev/MAKEDEV.cx''.
An example:
.ES
cd /dev
sh MAKEDEV.cx cronyx ttyx0 ttyx1 ttyy0
.EE
.SH "Asynchronous driver"
.PP
The asynchronous channel device files have the names:
/dev/ttyx# - for adapter cx0, /dev/ttyy# - for adapter cx1,
/dev/ttyz# - for cx2.
Here\ # is the channel number in hexadecimal form, 0-9-a-f.
.PP
The driver fulfills the following standard ioctl requests (see ioctl(2)):
.IP TIOCSBRK
Start sending BREAK.
.IP TIOCCBRK
Stop sending BREAK.
.IP TIOCSDTR
Set DTR signal (DTR := 1). The DTR signal is always set
on the first open(2) and could be changed by
TIOCCDTR, TIOCSDTR, TIOCMSET, TIOCMBIS, TIOCMBIC ioctl calls.
.IP TIOCCDTR
Clear DTR signal (DTR := 0).
.IP TIOCMSET
Set the given values of DTR and RTS signals (<DTR:RTS> := data).
The signals DTR and RTS are controlled by TIOCM_DTR and TIOCM_RTS
bits of the data argument of the ioctl system call.
.IP TIOCMBIS
Set DTR and RTS signals (<DTR:RTS> |= data).
The signals DTR and RTS are controlled by TIOCM_DTR and TIOCM_RTS
bits of the data argument of the ioctl system call.
.IP TIOCMBIC
Clear DTR and RTS signals (<DTR:RTS> &= ~data).
The signals DTR and RTS are controlled by TIOCM_DTR and TIOCM_RTS
bits of the data argument of the ioctl system call.
.IP TIOCMGET
Determine the state of the modem signals of the line.
After the call the data argument contains the following bits:
.ES
TIOCM_LE - always set (Line Enabled)
TIOCM_DSR - Data Set Ready signal received
TIOCM_CTS - Clear To Send signal received
TIOCM_CD - Data Carrier Detect signal received
TIOCM_DTR - Data Terminal Ready signal transmitted
TIOCM_RTS - Request To Send signal transmitted
.EE
.SH "Synchronous driver"
.PP
The synchronous channels and universal channels, turned to the synchronous
mode by the cxconfig(8) utility, are accessible as network
interfaces named ``cx#'' where\ # is the channel number, 0..47.
All standard network interface parameters could be set by ifconfig(8) utility.
The cxconfig(8) command is used to change some extended channel
options, and also for setting the high-level software protocol
(e.g. PPP or Cisco HDLC).
.PP
The universal channels could be used both in asynchronous and synchronous modes.
By default the asynchronous mode is set.
The mode could be changed by cxconfig(8) utility.
The mode is blocked while the channel is busy (an asynchronous channel
in open state or the network interface is up).
.SH "Synchronous Point-to-Point protocol"
.PP
The Cronyx-Sigma driver uses the built-in implementation of the synchronous
Point-to-Point protocol (sppp). It includes the support for such
protocols as PPP/HDLC and Cisco/HDLC, and also the automatic
connection loss test (via keepalive packets).
The sppp protocol set is implemented as an independent module
and could be used by other drivers of synchronous serial channels.
The version of the driver for BSD/386 (BSDI) operating system
also supports the usage of the general set of synchronous
protocols, implemented inside the OS.
The external protocol set could be selected by ``cxconfig ext'' command
(see cxconfig(8)).
.SH "Channel Options Management"
.PP
The cxconfig(8) utility is used for setting the channels options.
The channel options are generally set at the start of the operating
system (for example, from the file /etc/rc).
Note, that not all options have a sense for every particular
case, and an attempt to set some of them can hang up the channel or
the whole adapter.
.PP
The actual channel options control functions are implemented via
the ioctl-s on the special device file /dev/cronyx.
There are the following ioctl-s available:
.IP CXIOCGETMODE
Get the channel option values.
.IP CXIOCSETMODE
Set the channel option values.
.PP
The data argument of the ioctl call has an address of the options structure:
.ES
typedef struct {
unsigned char board; /* adapter number, 0..2 */
unsigned char channel; /* channel number, 0..15 */
unsigned char type; /* channel type (read only) */
unsigned char iftype; /* chan0 interface */
unsigned long rxbaud; /* receiver speed */
unsigned long txbaud; /* transmitter speed */
cx_chan_mode_t mode; /* channel mode */
cx_chan_opt_t opt; /* common channel options */
cx_opt_async_t aopt; /* async mode options */
cx_opt_hdlc_t hopt; /* hdlc mode options */
cx_opt_bisync_t bopt; /* bisync mode options */
cx_opt_x21_t xopt; /* x.21 mode options */
cx_soft_opt_t sopt; /* software options and state flags */
} cx_options_t; /* user settable options */
.EE
.IP board
The adapter number, 0..2.
.IP channel
The channel number, 0..15.
.IP type
The type of the channel (read-only argument).
.IP iftype
The interface type of the zero (and also the eight) channel: 0 - RS-232,
1 - RS-449/V.35.
.IP rxbaud
The receiver data baud rate.
.IP txbaud
The transmitter data baud rate.
.IP mode
The channel mode: asynchronous/HDLC/Bisync/X.21.
.IP opt
The general channel options.
.IP aopt
The asynchronous mode options.
.IP hopt
The HDLC mode options.
.IP bopt
The Bisync mode options.
.IP xopt
The X.21 mode options.
.IP sopt
The software protocol options.
.SH FILES
.PP
/dev/cx??
.IP
Asynchronous channels.
.PP
/dev/cronyx
.IP
The special device file for the channel options management.
.PP
/sys/i386/isa/cronyx.c
.br
/sys/i386/isa/cx.c
.br
/sys/i386/isa/if_cx.c
.br
/sys/i386/isa/cronyx.h
.br
/sys/i386/isa/cxreg.h
.br
/sys/net/if_spppsubr.c
.br
/sys/net/if_sppp.h
.IP
The sources of the driver.
.SH SEE ALSO
.PP
cxconfig(8)

475
sys/i386/include/cronyx.h Normal file
View File

@ -0,0 +1,475 @@
/*
* Defines for Cronyx-Sigma adapter driver.
*
* Copyright (C) 1994 Cronyx Ltd.
* Author: Serge Vakulenko, <vak@zebub.msk.su>
*
* This software is distributed with NO WARRANTIES, not even the implied
* warranties for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*
* Authors grant any other persons or organisations permission to use
* or modify this software as long as this message is kept with the software,
* all derivative works or modified versions.
*
* Version 1.1, Wed Oct 26 16:09:46 MSK 1994
*/
/*
* Asynchronous channel mode -------------------------------------------------
*/
/* Parity */
#define PAR_EVEN 0 /* even parity */
#define PAR_ODD 1 /* odd parity */
/* Parity mode */
#define PARM_NOPAR 0 /* no parity */
#define PARM_FORCE 1 /* force parity (odd = force 1, even = 0) */
#define PARM_NORMAL 2 /* normal parity */
/* Flow control transparency mode */
#define FLOWCC_PASS 0 /* pass flow ctl chars as exceptions */
#define FLOWCC_NOTPASS 1 /* don't pass flow ctl chars to the host */
/* Stop bit length */
#define STOPB_1 2 /* 1 stop bit */
#define STOPB_15 3 /* 1.5 stop bits */
#define STOPB_2 4 /* 2 stop bits */
/* Action on break condition */
#define BRK_INTR 0 /* generate an exception interrupt */
#define BRK_NULL 1 /* translate to a NULL character */
#define BRK_RESERVED 2 /* reserved */
#define BRK_DISCARD 3 /* discard character */
/* Parity/framing error actions */
#define PERR_INTR 0 /* generate an exception interrupt */
#define PERR_NULL 1 /* translate to a NULL character */
#define PERR_IGNORE 2 /* ignore error; char passed as good data */
#define PERR_DISCARD 3 /* discard error character */
#define PERR_FFNULL 5 /* translate to FF NULL char */
typedef struct { /* async channel option register 1 */
unsigned charlen : 4; /* character length, 5..8 */
unsigned ignpar : 1; /* ignore parity */
unsigned parmode : 2; /* parity mode */
unsigned parity : 1; /* parity */
} cx_cor1_async_t;
typedef struct { /* async channel option register 2 */
unsigned dsrae : 1; /* DSR automatic enable */
unsigned ctsae : 1; /* CTS automatic enable */
unsigned rtsao : 1; /* RTS automatic output enable */
unsigned rlm : 1; /* remote loopback mode enable */
unsigned zero : 1;
unsigned etc : 1; /* embedded transmitter cmd enable */
unsigned ixon : 1; /* in-band XON/XOFF enable */
unsigned ixany : 1; /* XON on any character */
} cx_cor2_async_t;
typedef struct { /* async channel option register 3 */
unsigned stopb : 3; /* stop bit length */
unsigned zero : 1;
unsigned scde : 1; /* special char detection enable */
unsigned flowct : 1; /* flow control transparency mode */
unsigned rngde : 1; /* range detect enable */
unsigned escde : 1; /* extended spec. char detect enable */
} cx_cor3_async_t;
typedef struct { /* async channel option register 6 */
unsigned parerr : 3; /* parity/framing error actions */
unsigned brk : 2; /* action on break condition */
unsigned inlcr : 1; /* translate NL to CR on input */
unsigned icrnl : 1; /* translate CR to NL on input */
unsigned igncr : 1; /* discard CR on input */
} cx_cor6_async_t;
typedef struct { /* async channel option register 7 */
unsigned ocrnl : 1; /* translate CR to NL on output */
unsigned onlcr : 1; /* translate NL to CR on output */
unsigned zero : 3;
unsigned fcerr : 1; /* process flow ctl err chars enable */
unsigned lnext : 1; /* LNext option enable */
unsigned istrip : 1; /* strip 8-bit on input */
} cx_cor7_async_t;
typedef struct { /* async channel options */
cx_cor1_async_t cor1; /* channel option register 1 */
cx_cor2_async_t cor2; /* channel option register 2 */
cx_cor3_async_t cor3; /* option register 3 */
cx_cor6_async_t cor6; /* channel option register 6 */
cx_cor7_async_t cor7; /* channel option register 7 */
unsigned char schr1; /* special character register 1 (XON) */
unsigned char schr2; /* special character register 2 (XOFF) */
unsigned char schr3; /* special character register 3 */
unsigned char schr4; /* special character register 4 */
unsigned char scrl; /* special character range low */
unsigned char scrh; /* special character range high */
unsigned char lnxt; /* LNext character */
} cx_opt_async_t;
/*
* HDLC channel mode ---------------------------------------------------------
*/
/* Address field length option */
#define AFLO_1OCT 0 /* address field is 1 octet in length */
#define AFLO_2OCT 1 /* address field is 2 octet in length */
/* Clear detect for X.21 data transfer phase */
#define CLRDET_DISABLE 0 /* clear detect disabled */
#define CLRDET_ENABLE 1 /* clear detect enabled */
/* Addressing mode */
#define ADMODE_NOADDR 0 /* no address */
#define ADMODE_4_1 1 /* 4 * 1 byte */
#define ADMODE_2_2 2 /* 2 * 2 byte */
/* FCS append */
#define FCS_NOTPASS 0 /* receive CRC is not passed to the host */
#define FCS_PASS 1 /* receive CRC is passed to the host */
/* CRC modes */
#define CRC_INVERT 0 /* CRC is transmitted inverted (CRC V.41) */
#define CRC_DONT_INVERT 1 /* CRC is not transmitted inverted (CRC-16) */
/* Send sync pattern */
#define SYNC_00 0 /* send 00h as pad char (NRZI encoding) */
#define SYNC_AA 1 /* send AAh (Manchester/NRZ encoding) */
/* FCS preset */
#define FCSP_ONES 0 /* FCS is preset to all ones (CRC V.41) */
#define FCSP_ZEROS 1 /* FCS is preset to all zeros (CRC-16) */
/* idle mode */
#define IDLE_FLAG 0 /* idle in flag */
#define IDLE_MARK 1 /* idle in mark */
/* CRC polynomial select */
#define POLY_V41 0 /* x^16+x^12+x^5+1 (HDLC, preset to 1) */
#define POLY_16 1 /* x^16+x^15+x^2+1 (bisync, preset to 0) */
typedef struct { /* hdlc channel option register 1 */
unsigned ifflags : 4; /* number of inter-frame flags sent */
unsigned admode : 2; /* addressing mode */
unsigned clrdet : 1; /* clear detect for X.21 data transfer phase */
unsigned aflo : 1; /* address field length option */
} cx_cor1_hdlc_t;
typedef struct { /* hdlc channel option register 2 */
unsigned dsrae : 1; /* DSR automatic enable */
unsigned ctsae : 1; /* CTS automatic enable */
unsigned rtsao : 1; /* RTS automatic output enable */
unsigned zero1 : 1;
unsigned crcninv : 1; /* CRC invertion option */
unsigned zero2 : 1;
unsigned fcsapd : 1; /* FCS append */
unsigned zero3 : 1;
} cx_cor2_hdlc_t;
typedef struct { /* hdlc channel option register 3 */
unsigned padcnt : 3; /* pad character count */
unsigned idle : 1; /* idle mode */
unsigned nofcs : 1; /* FCS disable */
unsigned fcspre : 1; /* FCS preset */
unsigned syncpat : 1; /* send sync pattern */
unsigned sndpad : 1; /* send pad characters before flag enable */
} cx_cor3_hdlc_t;
typedef struct { /* hdlc channel options */
cx_cor1_hdlc_t cor1; /* hdlc channel option register 1 */
cx_cor2_hdlc_t cor2; /* hdlc channel option register 2 */
cx_cor3_hdlc_t cor3; /* hdlc channel option register 3 */
unsigned char rfar1; /* receive frame address register 1 */
unsigned char rfar2; /* receive frame address register 2 */
unsigned char rfar3; /* receive frame address register 3 */
unsigned char rfar4; /* receive frame address register 4 */
unsigned char cpsr; /* CRC polynomial select */
} cx_opt_hdlc_t;
/*
* BISYNC channel mode -------------------------------------------------------
*/
/* Longitudinal redundancy check */
#define BCC_CRC16 0 /* CRC16 is used for BCC */
#define BCC_LRC 1 /* LRC is used for BCC */
/* Send pad pattern */
#define PAD_AA 0 /* send AAh as pad character */
#define PAD_55 1 /* send 55h as pad character */
typedef struct { /* channel option register 1 */
unsigned charlen : 4; /* character length, 5..8 */
unsigned ignpar : 1; /* ignore parity */
unsigned parmode : 2; /* parity mode */
unsigned parity : 1; /* parity */
} cx_cor1_bisync_t;
typedef struct { /* channel option register 2 */
unsigned syns : 4; /* number of extra SYN chars before a frame */
unsigned crcninv : 1; /* CRC invertion option */
unsigned ebcdic : 1; /* use EBCDIC as char set (instead of ASCII) */
unsigned bcc : 1; /* BCC append enable */
unsigned lrc : 1; /* longitudinal redundancy check */
} cx_cor2_bisync_t;
typedef struct { /* channel option register 3 */
unsigned padcnt : 3; /* pad character count */
unsigned idle : 1; /* idle mode */
unsigned nofcs : 1; /* FCS disable */
unsigned fcspre : 1; /* FCS preset */
unsigned padpat : 1; /* send pad pattern */
unsigned sndpad : 1; /* send pad characters before SYN enable */
} cx_cor3_bisync_t;
typedef struct { /* channel option register 6 */
unsigned char specterm; /* special termination character */
} cx_cor6_bisync_t;
typedef struct { /* bisync channel options */
cx_cor1_bisync_t cor1; /* channel option register 1 */
cx_cor2_bisync_t cor2; /* channel option register 2 */
cx_cor3_bisync_t cor3; /* channel option register 3 */
cx_cor6_bisync_t cor6; /* channel option register 6 */
unsigned char cpsr; /* CRC polynomial select */
} cx_opt_bisync_t;
/*
* X.21 channel mode ---------------------------------------------------------
*/
/* The number of SYN chars on receive */
#define X21SYN_2 0 /* two SYN characters are required */
#define X21SYN_1 1 /* one SYN character is required */
typedef struct { /* channel option register 1 */
unsigned charlen : 4; /* character length, 5..8 */
unsigned ignpar : 1; /* ignore parity */
unsigned parmode : 2; /* parity mode */
unsigned parity : 1; /* parity */
} cx_cor1_x21_t;
typedef struct { /* channel option register 2 */
unsigned zero1 : 5;
unsigned etc : 1; /* embedded transmitter command enable */
unsigned zero2 : 2;
} cx_cor2_x21_t;
typedef struct { /* channel option register 3 */
unsigned zero : 4;
unsigned scde : 1; /* special character detect enable */
unsigned stripsyn : 1; /* treat SYN chars as special condition */
unsigned ssde : 1; /* steady state detect enable */
unsigned syn : 1; /* the number of SYN chars on receive */
} cx_cor3_x21_t;
typedef struct { /* channel option register 6 */
unsigned char synchar; /* syn character */
} cx_cor6_x21_t;
typedef struct { /* x21 channel options */
cx_cor1_x21_t cor1; /* channel option register 1 */
cx_cor2_x21_t cor2; /* channel option register 2 */
cx_cor3_x21_t cor3; /* channel option register 3 */
cx_cor6_x21_t cor6; /* channel option register 6 */
unsigned char schr1; /* special character register 1 */
unsigned char schr2; /* special character register 2 */
unsigned char schr3; /* special character register 3 */
} cx_opt_x21_t;
/*
* CD2400 channel state structure --------------------------------------------
*/
/* Signal encoding */
#define ENCOD_NRZ 0 /* NRZ mode */
#define ENCOD_NRZI 1 /* NRZI mode */
#define ENCOD_MANCHESTER 2 /* Manchester mode */
/* Clock source */
#define CLK_0 0 /* clock 0 */
#define CLK_1 1 /* clock 1 */
#define CLK_2 2 /* clock 2 */
#define CLK_3 3 /* clock 3 */
#define CLK_4 4 /* clock 4 */
#define CLK_EXT 6 /* external clock */
#define CLK_RCV 7 /* receive clock */
/* Channel type */
#define T_NONE 0 /* no channel */
#define T_ASYNC 1 /* pure asynchronous RS-232 channel */
#define T_SYNC_RS232 2 /* pure synchronous RS-232 channel */
#define T_SYNC_V35 3 /* pure synchronous V.35 channel */
#define T_SYNC_RS449 4 /* pure synchronous RS-449 channel */
#define T_UNIV_RS232 5 /* sync/async RS-232 channel */
#define T_UNIV_RS449 6 /* sync/async RS-232/RS-449 channel */
#define T_UNIV_V35 7 /* sync/async RS-232/V.35 channel */
typedef enum { /* channel mode */
M_ASYNC, /* asynchronous mode */
M_HDLC, /* HDLC mode */
M_BISYNC, /* BISYNC mode */
M_X21, /* X.21 mode */
} cx_chan_mode_t;
typedef struct { /* channel option register 4 */
unsigned thr : 4; /* FIFO threshold */
unsigned zero : 1;
unsigned cts_zd : 1; /* detect 1 to 0 transition on the CTS */
unsigned cd_zd : 1; /* detect 1 to 0 transition on the CD */
unsigned dsr_zd : 1; /* detect 1 to 0 transition on the DSR */
} cx_cor4_t;
typedef struct { /* channel option register 5 */
unsigned rx_thr : 4; /* receive flow control FIFO threshold */
unsigned zero : 1;
unsigned cts_od : 1; /* detect 0 to 1 transition on the CTS */
unsigned cd_od : 1; /* detect 0 to 1 transition on the CD */
unsigned dsr_od : 1; /* detect 0 to 1 transition on the DSR */
} cx_cor5_t;
typedef struct { /* receive clock option register */
unsigned clk : 3; /* receive clock source */
unsigned encod : 2; /* signal encoding NRZ/NRZI/Manchester */
unsigned dpll : 1; /* DPLL enable */
unsigned zero : 1;
unsigned tlval : 1; /* transmit line value */
} cx_rcor_t;
typedef struct { /* transmit clock option register */
unsigned zero1 : 1;
unsigned llm : 1; /* local loopback mode */
unsigned zero2 : 1;
unsigned ext1x : 1; /* external 1x clock mode */
unsigned zero3 : 1;
unsigned clk : 3; /* transmit clock source */
} cx_tcor_t;
typedef struct {
cx_cor4_t cor4; /* channel option register 4 */
cx_cor5_t cor5; /* channel option register 5 */
cx_rcor_t rcor; /* receive clock option register */
cx_tcor_t tcor; /* transmit clock option register */
} cx_chan_opt_t;
typedef enum { /* line break mode */
BRK_IDLE, /* normal line mode */
BRK_SEND, /* start sending break */
BRK_STOP, /* stop sending break */
} cx_break_t;
typedef struct {
unsigned cisco : 1; /* cisco mode */
unsigned keepalive : 1; /* keepalive enable */
unsigned ext : 1; /* use external ppp implementation */
unsigned lock : 1; /* channel locked for use by driver */
unsigned norts : 1; /* disable automatic RTS control */
} cx_soft_opt_t;
#define NCHIP 4 /* the number of controllers per board */
#define NCHAN 16 /* the number of channels on the board */
typedef struct {
unsigned char board; /* adapter number, 0..2 */
unsigned char channel; /* channel number, 0..15 */
unsigned char type; /* channel type (read only) */
unsigned char iftype; /* chan0 interface RS-232/RS-449/V.35 */
unsigned long rxbaud; /* receiver speed */
unsigned long txbaud; /* transmitter speed */
cx_chan_mode_t mode; /* channel mode */
cx_chan_opt_t opt; /* common channel options */
cx_opt_async_t aopt; /* async mode options */
cx_opt_hdlc_t hopt; /* hdlc mode options */
cx_opt_bisync_t bopt; /* bisync mode options */
cx_opt_x21_t xopt; /* x.21 mode options */
cx_soft_opt_t sopt; /* software options and state flags */
} cx_options_t; /* user settable options */
typedef struct _chan_t {
unsigned char type; /* channel type */
unsigned char num; /* channel number, 0..15 */
struct _board_t *board; /* board pointer */
struct _chip_t *chip; /* controller pointer */
unsigned long rxbaud; /* receiver speed */
unsigned long txbaud; /* transmitter speed */
cx_chan_mode_t mode; /* channel mode */
cx_chan_opt_t opt; /* common channel options */
cx_opt_async_t aopt; /* async mode options */
cx_opt_hdlc_t hopt; /* hdlc mode options */
cx_opt_bisync_t bopt; /* bisync mode options */
cx_opt_x21_t xopt; /* x.21 mode options */
unsigned char *arbuf; /* receiver A dma buffer */
unsigned char *brbuf; /* receiver B dma buffer */
unsigned char *atbuf; /* transmitter A dma buffer */
unsigned char *btbuf; /* transmitter B dma buffer */
unsigned long arphys; /* receiver A phys address */
unsigned long brphys; /* receiver B phys address */
unsigned long atphys; /* transmitter A phys address */
unsigned long btphys; /* transmitter B phys address */
unsigned char dtr; /* DTR signal value */
unsigned char rts; /* RTS signal value */
#ifdef KERNEL
struct tty *ttyp; /* tty structure pointer */
struct ifnet *ifp; /* network interface data */
caddr_t bpf; /* packet filter data */
cx_soft_opt_t sopt; /* software options and state flags */
cx_break_t brk; /* line break mode */
#ifdef __bsdi__
struct ttydevice_tmp *ttydev; /* tty statistics structure */
#endif
#endif
} cx_chan_t;
typedef struct _chip_t {
unsigned short port; /* base port address, or 0 if no chip */
unsigned char num; /* controller number, 0..3 */
struct _board_t *board; /* board pointer */
unsigned long oscfreq; /* oscillator frequency in Hz */
} cx_chip_t;
typedef struct _board_t {
unsigned short port; /* base board port, 0..3f0 */
unsigned short num; /* board number, 0..2 */
unsigned char irq; /* intterupt request {3 5 7 10 11 12 15} */
unsigned char dma; /* DMA request {5 6 7} */
unsigned char if0type; /* chan0 interface RS-232/RS-449/V.35 */
unsigned char if8type; /* chan8 interface RS-232/RS-449/V.35 */
unsigned short bcr0; /* BCR0 image */
unsigned short bcr0b; /* BCR0b image */
unsigned short bcr1; /* BCR1 image */
unsigned short bcr1b; /* BCR1b image */
cx_chip_t chip[NCHIP]; /* controller structures */
cx_chan_t chan[NCHAN]; /* channel structures */
char name[16]; /* board version name */
unsigned char nuniv; /* number of universal channels */
unsigned char nsync; /* number of sync. channels */
unsigned char nasync; /* number of async. channels */
} cx_board_t;
#define CX_SPEED_DFLT 9600
extern long cx_rxbaud, cx_txbaud;
extern int cx_univ_mode, cx_sync_mode, cx_iftype;
extern cx_chan_opt_t chan_opt_dflt; /* default mode-independent options */
extern cx_opt_async_t opt_async_dflt; /* default async options */
extern cx_opt_hdlc_t opt_hdlc_dflt; /* default hdlc options */
extern cx_opt_bisync_t opt_bisync_dflt; /* default bisync options */
extern cx_opt_x21_t opt_x21_dflt; /* default x21 options */
int cx_probe_board (int port);
void cx_init (cx_board_t *b, int num, int port, int irq, int dma);
void cx_init_board (cx_board_t *b, int num, int port, int irq, int dma,
int chain, int rev, int osc, int rev2, int osc2);
void cx_setup_board (cx_board_t *b);
void cx_setup_chan (cx_chan_t *c);
void cx_chan_dtr (cx_chan_t *c, int on);
void cx_chan_rts (cx_chan_t *c, int on);
void cx_cmd (int base, int cmd);
void cx_disable_dma (cx_board_t *b);
void cx_reinit_board (cx_board_t *b);
int cx_chan_dsr (cx_chan_t *c);
int cx_chan_cd (cx_chan_t *c);
void cx_clock (long hz, long ba, int *clk, int *div);
#define CXIOCGETMODE _IOWR('x', 1, cx_options_t) /* get channel options */
#define CXIOCSETMODE _IOW('x', 2, cx_options_t) /* set channel options */

1041
sys/i386/isa/cronyx.c Normal file

File diff suppressed because it is too large Load Diff

898
sys/i386/isa/cx.c Normal file
View File

@ -0,0 +1,898 @@
/*
* Cronyx-Sigma adapter driver for FreeBSD.
* Supports PPP/HDLC protocol in synchronous mode,
* and asyncronous channels with full modem control.
*
* Copyright (C) 1994 Cronyx Ltd.
* Author: Serge Vakulenko, <vak@zebub.msk.su>
*
* This software is distributed with NO WARRANTIES, not even the implied
* warranties for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*
* Authors grant any other persons or organisations permission to use
* or modify this software as long as this message is kept with the software,
* all derivative works or modified versions.
*
* Version 1.2, Tue Nov 22 18:57:27 MSK 1994
*/
#undef DEBUG
#include "cx.h"
#if NCX > 0
#include <sys/param.h>
#include <systm.h>
#include <kernel.h>
#include <sys/mbuf.h>
#include <sys/ioctl.h>
#include <sys/file.h>
#include <sys/conf.h>
#include <sys/proc.h>
#include <sys/tty.h>
#include <sys/errno.h>
#include <sys/syslog.h>
#include <sys/socket.h>
#include <net/if.h>
#ifdef __FreeBSD__
# if __FreeBSD__ < 2
# include <i386/include/pio.h>
# define RB_GETC(q) getc(q)
# else /* BSD 4.4 Lite */
# include <i386/include/cpufunc.h>
# include <sys/devconf.h>
# endif
# define oproc_func_t void(*)(struct tty*)
#endif
#ifdef __bsdi__
# include <sys/ttystats.h>
# include <i386/include/inline.h>
# define tsleep(tp,pri,msg,x) ((tp)->t_state |= TS_WOPEN,\
ttysleep (tp, (caddr_t)&tp->t_rawq, pri, msg, x))
# define oproc_func_t int(*)()
# define timeout_func_t void(*)()
#endif
#if !defined (__FreeBSD__) || __FreeBSD__ >= 2
# define t_out t_outq
# define RB_LEN(q) ((q).c_cc)
# define RB_GETC(q) getc(&q)
# define TSA_CARR_ON(tp) tp
# define TSA_OLOWAT(q) ((caddr_t)&(q)->t_out)
#endif
#include <sys/cronyx.h>
#include <i386/isa/cxreg.h>
#ifdef DEBUG
# define print(s) printf s
#else
# define print(s) /*void*/
#endif
#define DMABUFSZ (6*256) /* buffer size */
#define BYTE *(unsigned char*)&
#define UNIT(u) ((u) & 077)
#define UNIT_CTL 077
extern cx_board_t cxboard [NCX]; /* adapter state structures */
extern cx_chan_t *cxchan [NCX*NCHAN]; /* unit to channel struct pointer */
#if __FreeBSD__ >= 2
extern struct kern_devconf kdc_cx [NCX];
struct tty cx_tty [NCX*NCHAN]; /* tty data */
#else
struct tty *cx_tty [NCX*NCHAN]; /* tty data */
#endif
void cxoproc (struct tty *tp);
int cxparam (struct tty *tp, struct termios *t);
void cxswitch (cx_chan_t *c, cx_soft_opt_t new);
int cxopen (dev_t dev, int flag, int mode, struct proc *p)
{
int unit = UNIT (dev);
cx_chan_t *c = cxchan[unit];
unsigned short port;
struct tty *tp;
int error = 0;
if (unit == UNIT_CTL) {
print (("cx: cxopen /dev/cronyx\n"));
return (0);
}
if (unit >= NCX*NCHAN || !c || c->type==T_NONE)
return (ENXIO);
port = c->chip->port;
print (("cx%d.%d: cxopen unit=%d\n", c->board->num, c->num, unit));
if (c->mode != M_ASYNC)
return (EBUSY);
if (! c->ttyp) {
#if __FreeBSD__ >= 2
c->ttyp = &cx_tty[unit];
#else
MALLOC (cx_tty[unit], struct tty*, sizeof (struct tty), M_DEVBUF, M_WAITOK);
bzero (cx_tty[unit], sizeof (*cx_tty[unit]));
c->ttyp = cx_tty[unit];
#endif
c->ttyp->t_oproc = (oproc_func_t) cxoproc;
c->ttyp->t_param = cxparam;
}
#ifdef __bsdi__
if (! c->ttydev) {
MALLOC (c->ttydev, struct ttydevice_tmp*,
sizeof (struct ttydevice_tmp), M_DEVBUF, M_WAITOK);
bzero (c->ttydev, sizeof (*c->ttydev));
strcpy (c->ttydev->tty_name, "cx");
c->ttydev->tty_unit = unit;
c->ttydev->tty_base = unit;
c->ttydev->tty_count = 1;
c->ttydev->tty_ttys = c->ttyp;
tty_attach (c->ttydev);
}
#endif
tp = c->ttyp;
tp->t_dev = dev;
if ((tp->t_state & TS_ISOPEN) && (tp->t_state & TS_XCLUDE) &&
p->p_ucred->cr_uid != 0)
return (EBUSY);
if (! (tp->t_state & TS_ISOPEN)) {
ttychars (tp);
if (tp->t_ispeed == 0) {
#ifdef __bsdi__
tp->t_termios = deftermios;
#else
tp->t_iflag = 0;
tp->t_oflag = 0;
tp->t_lflag = 0;
tp->t_cflag = CREAD | CS8 | HUPCL;
tp->t_ispeed = c->rxbaud;
tp->t_ospeed = c->txbaud;
#endif
}
cxparam (tp, &tp->t_termios);
ttsetwater (tp);
}
spltty ();
if (! (tp->t_state & TS_ISOPEN)) {
/*
* Compute optimal receiver buffer length.
* The best choice is rxbaud/400.
* Make it even, to avoid byte-wide DMA transfers.
* --------------------------
* Baud rate Buffer length
* --------------------------
* 300 4
* 1200 4
* 9600 24
* 19200 48
* 38400 96
* 57600 192
* 115200 288
* --------------------------
*/
int rbsz = (c->rxbaud + 800 - 1) / 800 * 2;
if (rbsz < 4)
rbsz = 4;
else if (rbsz > DMABUFSZ)
rbsz = DMABUFSZ;
/* Initialize channel, enable receiver. */
cx_cmd (port, CCR_INITCH | CCR_ENRX);
cx_cmd (port, CCR_INITCH | CCR_ENRX);
/* Start receiver. */
outw (ARBCNT(port), rbsz);
outw (BRBCNT(port), rbsz);
outw (ARBSTS(port), BSTS_OWN24);
outw (BRBSTS(port), BSTS_OWN24);
/* Enable interrupts. */
outb (IER(port), IER_RXD | IER_RET | IER_TXD | IER_MDM);
cx_chan_dtr (c, 1);
cx_chan_rts (c, 1);
}
if (cx_chan_cd (c))
tp->t_state |= TS_CARR_ON;
if (! (flag & O_NONBLOCK)) {
/* Lock the channel against cxconfig while we are
* waiting for carrier. */
c->sopt.lock = 1;
while (!(tp->t_cflag & CLOCAL) && !(tp->t_state & TS_CARR_ON))
if ((error = tsleep (TSA_CARR_ON(tp), TTIPRI | PCATCH,
"cxdcd", 0)))
break;
c->sopt.lock = 0; /* Unlock the channel. */
}
print (("cx%d.%d: cxopen done csr=%b\n", c->board->num, c->num,
inb(CSR(c->chip->port)), CSRA_BITS));
spl0 ();
if (error)
return (error);
#if __FreeBSD__ >= 2
error = (*linesw[tp->t_line].l_open) (dev, tp);
if (tp->t_state & TS_ISOPEN)
/* Mark the board busy on the first startup.
* Never goes idle. */
kdc_cx[c->board->num].kdc_state = DC_BUSY;
#else
error = (*linesw[tp->t_line].l_open) (dev, tp, 0);
#endif
return (error);
}
int cxclose (dev_t dev, int flag, int mode, struct proc *p)
{
int unit = UNIT (dev);
cx_chan_t *c = cxchan[unit];
struct tty *tp;
int s;
if (unit == UNIT_CTL)
return (0);
tp = c->ttyp;
(*linesw[tp->t_line].l_close) (tp, flag);
/* Disable receiver.
* Transmitter continues sending the queued data. */
s = spltty ();
outb (CAR(c->chip->port), c->num & 3);
outb (IER(c->chip->port), IER_TXD | IER_MDM);
cx_cmd (c->chip->port, CCR_DISRX);
/* Clear DTR and RTS. */
if ((tp->t_cflag & HUPCL) || ! (tp->t_state & TS_ISOPEN)) {
cx_chan_dtr (c, 0);
cx_chan_rts (c, 0);
}
/* Stop sending break. */
if (c->brk == BRK_SEND) {
c->brk = BRK_STOP;
if (! (tp->t_state & TS_BUSY))
cxoproc (tp);
}
splx (s);
ttyclose (tp);
return (0);
}
int cxread (dev_t dev, struct uio *uio, int flag)
{
int unit = UNIT (dev);
struct tty *tp;
if (unit == UNIT_CTL)
return (EIO);
tp = cxchan[unit]->ttyp;
return ((*linesw[tp->t_line].l_read) (tp, uio, flag));
}
int cxwrite (dev_t dev, struct uio *uio, int flag)
{
int unit = UNIT (dev);
struct tty *tp;
if (unit == UNIT_CTL)
return (EIO);
tp = cxchan[unit]->ttyp;
return ((*linesw[tp->t_line].l_write) (tp, uio, flag));
}
int cxioctl (dev_t dev, int cmd, caddr_t data, int flag, struct proc *p)
{
int unit = UNIT (dev);
cx_chan_t *c;
struct tty *tp;
int error, s;
unsigned char msv;
if (unit == UNIT_CTL) {
/* Process an ioctl request on /dev/cronyx */
cx_options_t *o = (cx_options_t*) data;
if (o->board >= NCX || o->channel >= NCHAN)
return (EINVAL);
c = &cxboard[o->board].chan[o->channel];
if (c->type == T_NONE)
return (ENXIO);
switch (cmd) {
default:
return (EINVAL);
case CXIOCSETMODE:
print (("cx%d.%d: CXIOCSETMODE\n", o->board, o->channel));
if (c->type == T_NONE)
return (EINVAL);
if (c->type == T_ASYNC && o->mode != M_ASYNC)
return (EINVAL);
if (o->mode == M_ASYNC)
switch (c->type) {
case T_SYNC_RS232:
case T_SYNC_V35:
case T_SYNC_RS449:
return (EINVAL);
}
/* Somebody is waiting for carrier? */
if (c->sopt.lock)
return (EBUSY);
/* /dev/ttyXX is already opened by someone? */
if (c->mode == M_ASYNC && c->ttyp &&
(c->ttyp->t_state & TS_ISOPEN))
return (EBUSY);
/* Network interface is up? */
if (c->mode != M_ASYNC && (c->ifp->if_flags & IFF_UP))
return (EBUSY);
c->mode = o->mode;
c->rxbaud = o->rxbaud;
c->txbaud = o->txbaud;
c->opt = o->opt;
c->aopt = o->aopt;
c->hopt = o->hopt;
c->bopt = o->bopt;
c->xopt = o->xopt;
switch (c->num) {
case 0: c->board->if0type = o->iftype; break;
case 8: c->board->if8type = o->iftype; break;
}
cxswitch (c, o->sopt);
s = spltty ();
cx_setup_chan (c);
outb (IER(c->chip->port), 0);
splx (s);
break;
case CXIOCGETMODE:
print (("cx%d.%d: CXIOCGETMODE\n", o->board, o->channel));
o->type = c->type;
o->mode = c->mode;
o->rxbaud = c->rxbaud;
o->txbaud = c->txbaud;
o->opt = c->opt;
o->aopt = c->aopt;
o->hopt = c->hopt;
o->bopt = c->bopt;
o->xopt = c->xopt;
o->sopt = c->sopt;
switch (c->num) {
case 0: o->iftype = c->board->if0type; break;
case 8: o->iftype = c->board->if8type; break;
}
break;
}
return (0);
}
c = cxchan[unit];
tp = c->ttyp;
if (! tp)
return (EINVAL);
#if __FreeBSD__ >= 2
error = (*linesw[tp->t_line].l_ioctl) (tp, cmd, data, flag, p);
#else
error = (*linesw[tp->t_line].l_ioctl) (tp, cmd, data, flag);
#endif
if (error >= 0)
return (error);
error = ttioctl (tp, cmd, data, flag);
if (error >= 0)
return (error);
s = spltty ();
switch (cmd) {
default:
splx (s);
return (ENOTTY);
case TIOCSBRK: /* Start sending line break */
c->brk = BRK_SEND;
if (! (tp->t_state & TS_BUSY))
cxoproc (tp);
break;
case TIOCCBRK: /* Stop sending line break */
c->brk = BRK_STOP;
if (! (tp->t_state & TS_BUSY))
cxoproc (tp);
break;
case TIOCSDTR: /* Set DTR */
cx_chan_dtr (c, 1);
break;
case TIOCCDTR: /* Clear DTR */
cx_chan_dtr (c, 0);
break;
case TIOCMSET: /* Set DTR/RTS */
cx_chan_dtr (c, (*(int*)data & TIOCM_DTR) ? 1 : 0);
cx_chan_rts (c, (*(int*)data & TIOCM_RTS) ? 1 : 0);
break;
case TIOCMBIS: /* Add DTR/RTS */
if (*(int*)data & TIOCM_DTR) cx_chan_dtr (c, 1);
if (*(int*)data & TIOCM_RTS) cx_chan_rts (c, 1);
break;
case TIOCMBIC: /* Clear DTR/RTS */
if (*(int*)data & TIOCM_DTR) cx_chan_dtr (c, 0);
if (*(int*)data & TIOCM_RTS) cx_chan_rts (c, 0);
break;
case TIOCMGET: /* Get modem status */
msv = inb (MSVR(c->chip->port));
*(int*)data = TIOCM_LE; /* always enabled while open */
if (msv & MSV_DSR) *(int*)data |= TIOCM_DSR;
if (msv & MSV_CTS) *(int*)data |= TIOCM_CTS;
if (msv & MSV_CD) *(int*)data |= TIOCM_CD;
if (c->dtr) *(int*)data |= TIOCM_DTR;
if (c->rts) *(int*)data |= TIOCM_RTS;
break;
}
splx (s);
return (0);
}
/*
* Fill transmitter buffer with data.
*/
void cxout (cx_chan_t *c, char b)
{
unsigned char *buf, *p, sym;
unsigned short port = c->chip->port, len = 0, cnt_port, sts_port;
struct tty *tp = c->ttyp;
int i;
if (! tp)
return;
/* Choose the buffer. */
if (b == 'A') {
buf = c->atbuf;
cnt_port = ATBCNT(port);
sts_port = ATBSTS(port);
} else {
buf = c->btbuf;
cnt_port = BTBCNT(port);
sts_port = BTBSTS(port);
}
/* Is it busy? */
if (inb (sts_port) & BSTS_OWN24) {
tp->t_state |= TS_BUSY;
return;
}
switch (c->brk) {
case BRK_SEND:
*buf++ = 0; /* extended transmit command */
*buf++ = 0x81; /* send break */
*buf++ = 0; /* extended transmit command */
*buf++ = 0x82; /* insert delay */
*buf++ = 250; /* 1/4 of second */
*buf++ = 0; /* extended transmit command */
*buf++ = 0x82; /* insert delay */
*buf++ = 250; /* + 1/4 of second */
len = 8;
c->brk = BRK_IDLE;
break;
case BRK_STOP:
*buf++ = 0; /* extended transmit command */
*buf++ = 0x83; /* stop break */
len = 2;
c->brk = BRK_IDLE;
break;
case BRK_IDLE:
len = RB_LEN (tp->t_out);
if (tp->t_iflag & IXOFF)
for (i=0, p=buf; i<len && p<buf+DMABUFSZ-1; ++i) {
sym = RB_GETC (tp->t_out);
/* Send XON/XOFF out of band. */
if (sym == tp->t_cc[VSTOP]) {
outb (STCR(port), STC_SNDSPC|STC_SSPC_2);
continue;
}
if (sym == tp->t_cc[VSTART]) {
outb (STCR(port), STC_SNDSPC|STC_SSPC_1);
continue;
}
/* Duplicate NULLs in ETC mode. */
if (! sym)
*p++ = 0;
*p++ = sym;
}
else
for (i=0, p=buf; i<len && p<buf+DMABUFSZ-1; ++i) {
sym = RB_GETC (tp->t_out);
/* Duplicate NULLs in ETC mode. */
if (! sym)
*p++ = 0;
*p++ = sym;
}
len = p - buf;
break;
}
/* Start transmitter. */
if (len) {
outw (cnt_port, len);
outb (sts_port, BSTS_INTR | BSTS_OWN24);
tp->t_state |= TS_BUSY;
print (("cx%d.%d: out %d bytes to %c\n",
c->board->num, c->num, len, b));
}
}
void cxoproc (struct tty *tp)
{
int unit = UNIT (tp->t_dev);
cx_chan_t *c = cxchan[unit];
unsigned short port = c->chip->port;
int s = spltty ();
/* Set current channel number */
outb (CAR(port), c->num & 3);
if (! (tp->t_state & (TS_TIMEOUT | TS_TTSTOP))) {
/* Start transmitter. */
if (! (inb (CSR(port)) & CSRA_TXEN))
cx_cmd (port, CCR_ENTX);
/* Determine the buffer order. */
if (inb (DMABSTS(port)) & DMABSTS_NTBUF) {
cxout (c, 'B');
cxout (c, 'A');
} else {
cxout (c, 'A');
cxout (c, 'B');
}
}
#if defined (__FreeBSD__) && __FreeBSD__ < 2
if (tp->t_state & (TS_SO_OCOMPLETE | TS_SO_OLOWAT) || tp->t_wsel)
ttwwakeup (tp);
#else /* FreeBSD 2.x and BSDI */
if (RB_LEN (tp->t_out) <= tp->t_lowat) {
if (tp->t_state & TS_ASLEEP) {
tp->t_state &= ~TS_ASLEEP;
wakeup(TSA_OLOWAT(tp));
}
selwakeup(&tp->t_wsel);
}
#endif
/*
* Enable TXMPTY interrupt,
* to catch the case when the second buffer is empty.
*/
if ((inb (ATBSTS(port)) & BSTS_OWN24) &&
(inb (BTBSTS(port)) & BSTS_OWN24)) {
outb (IER(port), IER_RXD|IER_RET|IER_TXD|IER_TXMPTY|IER_MDM);
} else
outb (IER(port), IER_RXD|IER_RET|IER_TXD|IER_MDM);
splx (s);
}
int cxparam (struct tty *tp, struct termios *t)
{
int unit = UNIT (tp->t_dev);
cx_chan_t *c = cxchan[unit];
unsigned short port = c->chip->port;
int clock, period, s;
cx_cor1_async_t cor1;
if (t->c_ospeed == 0) {
/* Clear DTR and RTS. */
s = spltty ();
cx_chan_dtr (c, 0);
cx_chan_rts (c, 0);
splx (s);
print (("cx%d.%d: cxparam (hangup)\n", c->board->num, c->num));
return (0);
}
print (("cx%d.%d: cxparam\n", c->board->num, c->num));
/* Check requested parameters. */
if (t->c_ospeed < 300 || t->c_ospeed > 256*1024)
return(EINVAL);
if (t->c_ispeed && (t->c_ispeed < 300 || t->c_ispeed > 256*1024))
return(EINVAL);
#ifdef __bsdi__
/* CLOCAL flag set -- wakeup everybody who waits for CD. */
/* FreeBSD does this themselves. */
if (! (tp->t_cflag & CLOCAL) && (t->c_cflag & CLOCAL))
wakeup ((caddr_t) &tp->t_rawq);
#endif
/* And copy them to tty and channel structures. */
c->rxbaud = tp->t_ispeed = t->c_ispeed;
c->txbaud = tp->t_ospeed = t->c_ospeed;
tp->t_cflag = t->c_cflag;
/* Set character length and parity mode. */
BYTE cor1 = 0;
switch (t->c_cflag & CSIZE) {
default:
case CS8: cor1.charlen = 7; break;
case CS7: cor1.charlen = 6; break;
case CS6: cor1.charlen = 5; break;
case CS5: cor1.charlen = 4; break;
}
if (t->c_cflag & PARENB) {
cor1.parmode = PARM_NORMAL;
cor1.ignpar = 0;
cor1.parity = (t->c_cflag & PARODD) ? PAR_ODD : PAR_EVEN;
} else {
cor1.parmode = PARM_NOPAR;
cor1.ignpar = 1;
}
/* Enable/disable hardware CTS. */
c->aopt.cor2.ctsae = (t->c_cflag & CRTSCTS) ? 1 : 0;
/* Handle DSR as CTS. */
c->aopt.cor2.dsrae = (t->c_cflag & CRTSCTS) ? 1 : 0;
/* Enable extended transmit command mode.
* Unfortunately, there is no other method for sending break. */
c->aopt.cor2.etc = 1;
/* Enable/disable hardware XON/XOFF. */
c->aopt.cor2.ixon = (t->c_iflag & IXON) ? 1 : 0;
c->aopt.cor2.ixany = (t->c_iflag & IXANY) ? 1 : 0;
/* Set the number of stop bits. */
if (t->c_cflag & CSTOPB)
c->aopt.cor3.stopb = STOPB_2;
else
c->aopt.cor3.stopb = STOPB_1;
/* Disable/enable passing XON/XOFF chars to the host. */
c->aopt.cor3.scde = (t->c_iflag & IXON) ? 1 : 0;
c->aopt.cor3.flowct = (t->c_iflag & IXON) ? FLOWCC_NOTPASS : FLOWCC_PASS;
c->aopt.schr1 = t->c_cc[VSTART]; /* XON */
c->aopt.schr2 = t->c_cc[VSTOP]; /* XOFF */
/* Set current channel number. */
s = spltty ();
outb (CAR(port), c->num & 3);
/* Set up receiver clock values. */
cx_clock (c->chip->oscfreq, c->rxbaud, &clock, &period);
c->opt.rcor.clk = clock;
outb (RCOR(port), BYTE c->opt.rcor);
outb (RBPR(port), period);
/* Set up transmitter clock values. */
cx_clock (c->chip->oscfreq, c->txbaud, &clock, &period);
c->opt.tcor.clk = clock;
c->opt.tcor.ext1x = 0;
outb (TCOR(port), BYTE c->opt.tcor);
outb (TBPR(port), period);
outb (COR2(port), BYTE c->aopt.cor2);
outb (COR3(port), BYTE c->aopt.cor3);
outb (SCHR1(port), c->aopt.schr1);
outb (SCHR2(port), c->aopt.schr2);
if (BYTE c->aopt.cor1 != BYTE cor1) {
BYTE c->aopt.cor1 = BYTE cor1;
outb (COR1(port), BYTE c->aopt.cor1);
/* Any change to COR1 require reinitialization. */
/* Unfortunately, it may cause transmitter glitches... */
cx_cmd (port, CCR_INITCH);
}
splx (s);
return (0);
}
int cxselect (dev_t dev, int flag, struct proc *p)
{
int unit = UNIT (dev);
if (unit == UNIT_CTL)
return (0);
#ifdef __FreeBSD__
return (ttselect (dev, flag, p));
#endif
#ifdef __bsdi__
return (ttyselect (cxchan[unit]->ttyp, flag, p));
#endif
}
/*
* Stop output on a line
*/
void cxstop (struct tty *tp, int flag)
{
cx_chan_t *c = cxchan[UNIT(tp->t_dev)];
unsigned short port = c->chip->port;
int s = spltty ();
if (tp->t_state & TS_BUSY) {
print (("cx%d.%d: cxstop\n", c->board->num, c->num));
/* Set current channel number */
outb (CAR(port), c->num & 3);
/* Stop transmitter */
cx_cmd (port, CCR_DISTX);
}
splx (s);
}
/*
* Handle receive interrupts, including receive errors and
* receive timeout interrupt.
*/
int cxrinta (cx_chan_t *c)
{
unsigned short port = c->chip->port;
unsigned short len = 0, risr = inw (RISR(port)), reoir = 0;
struct tty *tp = c->ttyp;
/* Compute optimal receiver buffer length. */
int rbsz = (c->rxbaud + 800 - 1) / 800 * 2;
if (rbsz < 4)
rbsz = 4;
else if (rbsz > DMABUFSZ)
rbsz = DMABUFSZ;
if (risr & RISA_TIMEOUT) {
unsigned long rcbadr = (unsigned short) inw (RCBADRL(port)) |
(long) inw (RCBADRU(port)) << 16;
unsigned char *buf = 0;
unsigned short cnt_port = 0, sts_port = 0;
if (rcbadr >= c->brphys && rcbadr < c->brphys+DMABUFSZ) {
buf = c->brbuf;
len = rcbadr - c->brphys;
cnt_port = BRBCNT(port);
sts_port = BRBSTS(port);
} else if (rcbadr >= c->arphys && rcbadr < c->arphys+DMABUFSZ) {
buf = c->arbuf;
len = rcbadr - c->arphys;
cnt_port = ARBCNT(port);
sts_port = ARBSTS(port);
} else
printf ("cx%d.%d: timeout: invalid buffer address\n",
c->board->num, c->num);
if (len) {
print (("cx%d.%d: async receive timeout (%d bytes), risr=%b, arbsts=%b, brbsts=%b\n",
c->board->num, c->num, len, risr, RISA_BITS,
inb (ARBSTS(port)), BSTS_BITS, inb (BRBSTS(port)), BSTS_BITS));
if (tp && (tp->t_state & TS_ISOPEN)) {
int i;
void (*rint)() = (void(*)())
linesw[tp->t_line].l_rint;
for (i=0; i<len; ++i)
(*rint) (buf[i], tp);
}
/* Restart receiver. */
outw (cnt_port, rbsz);
outb (sts_port, BSTS_OWN24);
}
return (REOI_TERMBUFF);
}
print (("cx%d.%d: async receive interrupt, risr=%b, arbsts=%b, brbsts=%b\n",
c->board->num, c->num, risr, RISA_BITS,
inb (ARBSTS(port)), BSTS_BITS, inb (BRBSTS(port)), BSTS_BITS));
if (risr & RIS_BUSERR)
printf ("cx%d.%d: receive bus error\n", c->board->num, c->num);
if (risr & (RIS_OVERRUN | RISA_PARERR | RISA_FRERR)) {
print (("cx%d.%d: receive error\n", c->board->num, c->num));
if (tp && (tp->t_state & TS_ISOPEN))
(*linesw[tp->t_line].l_rint) (' ' |
(risr & RISA_FRERR) ? TTY_FE : TTY_PE, tp);
}
/* Handle line break condition. */
if ((risr & RISA_BREAK) && tp && (tp->t_state & TS_ISOPEN))
(*linesw[tp->t_line].l_rint) (TTY_FE, tp);
/* Discard exception characters. */
if ((risr & RISA_SCMASK) && (tp->t_iflag & IXON))
reoir |= REOI_DISCEXC;
/* Handle received data. */
if ((risr & RIS_EOBUF) && tp && (tp->t_state & TS_ISOPEN)) {
void (*rint)() = (void(*)()) linesw[tp->t_line].l_rint;
unsigned char *buf;
int i;
len = (risr & RIS_BB) ? inw(BRBCNT(port)) : inw(ARBCNT(port));
print (("cx%d.%d: async: %d bytes received\n",
c->board->num, c->num, len));
buf = (risr & RIS_BB) ? c->brbuf : c->arbuf;
for (i=0; i<len; ++i)
(*rint) (buf[i], tp);
}
/* Restart receiver. */
if (! (inb (ARBSTS(port)) & BSTS_OWN24)) {
outw (ARBCNT(port), rbsz);
outb (ARBSTS(port), BSTS_OWN24);
}
if (! (inb (BRBSTS(port)) & BSTS_OWN24)) {
outw (BRBCNT(port), rbsz);
outb (BRBSTS(port), BSTS_OWN24);
}
return (reoir);
}
/*
* Handle transmit interrupt.
*/
void cxtinta (cx_chan_t *c)
{
struct tty *tp = c->ttyp;
unsigned short port = c->chip->port;
unsigned char tisr = inb (TISR(port));
print (("cx%d.%d: async transmit interrupt, tisr=%b, atbsts=%b, btbsts=%b\n",
c->board->num, c->num, tisr, TIS_BITS,
inb (ATBSTS(port)), BSTS_BITS, inb (BTBSTS(port)), BSTS_BITS));
if (tisr & TIS_BUSERR)
printf ("cx%d.%d: transmit bus error\n",
c->board->num, c->num);
else if (tisr & TIS_UNDERRUN)
printf ("cx%d.%d: transmit underrun error\n",
c->board->num, c->num);
if (tp) {
tp->t_state &= ~(TS_BUSY | TS_FLUSH);
if (tp->t_line)
(*linesw[tp->t_line].l_start) (tp);
else
cxoproc (tp);
}
}
/*
* Handle modem interrupt.
*/
void cxmint (cx_chan_t *c)
{
unsigned short port = c->chip->port;
unsigned char misr = inb (MISR(port));
unsigned char msvr = inb (MSVR(port));
struct tty *tp = c->ttyp;
if (c->mode != M_ASYNC) {
printf ("cx%d.%d: unexpected modem interrupt, misr=%b, msvr=%b\n",
c->board->num, c->num, misr, MIS_BITS, msvr, MSV_BITS);
return;
}
print (("cx%d.%d: modem interrupt, misr=%b, msvr=%b\n",
c->board->num, c->num, misr, MIS_BITS, msvr, MSV_BITS));
/* Ignore DSR events. */
/* Ignore RTC/CTS events, handled by hardware. */
/* Handle carrier detect/loss. */
if (tp && (misr & MIS_CCD))
(*linesw[tp->t_line].l_modem) (tp, (msvr & MSV_CD) != 0);
}
/*
* Recover after lost transmit interrupts.
*/
void cxtimeout (caddr_t a)
{
cx_board_t *b;
cx_chan_t *c;
struct tty *tp;
int s;
for (b=cxboard; b<cxboard+NCX; ++b)
for (c=b->chan; c<b->chan+NCHAN; ++c) {
tp = c->ttyp;
if (c->type==T_NONE || c->mode!=M_ASYNC || !tp)
continue;
s = spltty ();
if (tp->t_state & TS_BUSY) {
tp->t_state &= ~TS_BUSY;
if (tp->t_line)
(*linesw[tp->t_line].l_start) (tp);
else
cxoproc (tp);
}
splx (s);
}
timeout ((timeout_func_t) cxtimeout, 0, hz*5);
}
#endif /* NCX */

429
sys/i386/isa/cxreg.h Normal file
View File

@ -0,0 +1,429 @@
/*
* Defines for Cronyx-Sigma adapter, based on Cirrus Logic multiprotocol
* controller RISC processor CL-CD2400/2401.
*
* Copyright (C) 1994 Cronyx Ltd.
* Author: Serge Vakulenko, <vak@zebub.msk.su>
*
* This software is distributed with NO WARRANTIES, not even the implied
* warranties for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*
* Authors grant any other persons or organisations permission to use
* or modify this software as long as this message is kept with the software,
* all derivative works or modified versions.
*
* Version 1.0, Fri Oct 7 19:34:06 MSD 1994
*/
#define NBRD 3 /* the maximum number of installed boards */
#define NPORT 16 /* the number of i/o ports per board */
#define REVCL_MIN 7 /* CD2400 min. revision number G */
#define REVCL_MAX 11 /* CD2400 max. revision number K */
#define BRD_INTR_LEVEL 0x5a /* interrupt level (arbitrary PILR value) */
#define CS0(p) ((p) | 0x8000) /* chip select 0 */
#define CS1(p) ((p) | 0xc000) /* chip select 1 */
#define BSR(p) (p) /* board status register, read only */
#define BCR0(p) (p) /* board command register 0, write only */
#define BCR1(p) ((p) | 0x2000) /* board command register 1, write only */
/*
* Chip register address, B is chip base port, R is chip register number.
*/
#define R(b,r) ((b) | (((r)<<6 & 0x3c00) | ((r) & 0xf)))
/*
* Interrupt acknowledge register, P is board port, L is interrupt level,
* as prodrammed in PILR.
*/
#define IACK(p,l) (R(p,l) | 0x4000)
/*
* Global registers.
*/
#define GFRCR(b) R(b,0x82) /* global firmware revision code register */
#define CAR(b) R(b,0xec) /* channel access register */
/*
* Option registers.
*/
#define CMR(b) R(b,0x18) /* channel mode register */
#define COR1(b) R(b,0x13) /* channel option register 1 */
#define COR2(b) R(b,0x14) /* channel option register 2 */
#define COR3(b) R(b,0x15) /* channel option register 3 */
#define COR4(b) R(b,0x16) /* channel option register 4 */
#define COR5(b) R(b,0x17) /* channel option register 5 */
#define COR6(b) R(b,0x1b) /* channel option register 6 */
#define COR7(b) R(b,0x04) /* channel option register 7 */
#define SCHR1(b) R(b,0x1c) /* special character register 1 */
#define SCHR2(b) R(b,0x1d) /* special character register 2 */
#define SCHR3(b) R(b,0x1e) /* special character register 3 */
#define SCHR4(b) R(b,0x1f) /* special character register 4 */
#define SCRL(b) R(b,0x20) /* special character range low */
#define SCRH(b) R(b,0x21) /* special character range high */
#define LNXT(b) R(b,0x2d) /* LNext character */
#define RFAR1(b) R(b,0x1c) /* receive frame address register 1 */
#define RFAR2(b) R(b,0x1d) /* receive frame address register 2 */
#define RFAR3(b) R(b,0x1e) /* receive frame address register 3 */
#define RFAR4(b) R(b,0x1f) /* receive frame address register 4 */
#define CPSR(b) R(b,0xd4) /* CRC polynomial select register */
/*
* Bit rate and clock option registers.
*/
#define RBPR(b) R(b,0xc9) /* receive baud rate period register */
#define RCOR(b) R(b,0xca) /* receive clock option register */
#define TBPR(b) R(b,0xc1) /* transmit baud rate period register */
#define TCOR(b) R(b,0xc2) /* receive clock option register */
/*
* Channel command and status registers.
*/
#define CCR(b) R(b,0x10) /* channel command register */
#define STCR(b) R(b,0x11) /* special transmit command register */
#define CSR(b) R(b,0x19) /* channel status register */
#define MSVR(b) R(b,0xdc) /* modem signal value register */
#define MSVR_RTS(b) R(b,0xdc) /* modem RTS setup register */
#define MSVR_DTR(b) R(b,0xdd) /* modem DTR setup register */
/*
* Interrupt registers.
*/
#define LIVR(b) R(b,0x0a) /* local interrupt vector register */
#define IER(b) R(b,0x12) /* interrupt enable register */
#define LICR(b) R(b,0x25) /* local interrupting channel register */
#define STK(b) R(b,0xe0) /* stack register */
/*
* Receive interrupt registers.
*/
#define RPILR(b) R(b,0xe3) /* receive priority interrupt level register */
#define RIR(b) R(b,0xef) /* receive interrupt register */
#define RISR(b) R(b,0x8a) /* receive interrupt status register */
#define RISRL(b) R(b,0x8a) /* receive interrupt status register low */
#define RISRH(b) R(b,0x8b) /* receive interrupt status register high */
#define RFOC(b) R(b,0x33) /* receive FIFO output count */
#define RDR(b) R(b,0xf8) /* receive data register */
#define REOIR(b) R(b,0x87) /* receive end of interrupt register */
/*
* Transmit interrupt registers.
*/
#define TPILR(b) R(b,0xe2) /* transmit priority interrupt level reg */
#define TIR(b) R(b,0xee) /* transmit interrupt register */
#define TISR(b) R(b,0x89) /* transmit interrupt status register */
#define TFTC(b) R(b,0x83) /* transmit FIFO transfer count */
#define TDR(b) R(b,0xf8) /* transmit data register */
#define TEOIR(b) R(b,0x86) /* transmit end of interrupt register */
/*
* Modem interrupt registers.
*/
#define MPILR(b) R(b,0xe1) /* modem priority interrupt level register */
#define MIR(b) R(b,0xed) /* modem interrupt register */
#define MISR(b) R(b,0x88) /* modem/timer interrupt status register */
#define MEOIR(b) R(b,0x85) /* modem end of interrupt register */
/*
* DMA registers.
*/
#define DMR(b) R(b,0xf4) /* DMA mode register */
#define BERCNT(b) R(b,0x8d) /* bus error retry count */
#define DMABSTS(b) R(b,0x1a) /* DMA buffer status */
/*
* DMA receive registers.
*/
#define ARBADRL(b) R(b,0x40) /* A receive buffer address lower */
#define ARBADRU(b) R(b,0x42) /* A receive buffer address upper */
#define BRBADRL(b) R(b,0x44) /* B receive buffer address lower */
#define BRBADRU(b) R(b,0x46) /* B receive buffer address upper */
#define ARBCNT(b) R(b,0x48) /* A receive buffer byte count */
#define BRBCNT(b) R(b,0x4a) /* B receive buffer byte count */
#define ARBSTS(b) R(b,0x4c) /* A receive buffer status */
#define BRBSTS(b) R(b,0x4d) /* B receive buffer status */
#define RCBADRL(b) R(b,0x3c) /* receive current buffer address lower */
#define RCBADRU(b) R(b,0x3e) /* receive current buffer address upper */
/*
* DMA transmit registers.
*/
#define ATBADRL(b) R(b,0x50) /* A transmit buffer address lower */
#define ATBADRU(b) R(b,0x52) /* A transmit buffer address upper */
#define BTBADRL(b) R(b,0x54) /* B transmit buffer address lower */
#define BTBADRU(b) R(b,0x56) /* B transmit buffer address upper */
#define ATBCNT(b) R(b,0x58) /* A transmit buffer byte count */
#define BTBCNT(b) R(b,0x5a) /* B transmit buffer byte count */
#define ATBSTS(b) R(b,0x5c) /* A transmit buffer status */
#define BTBSTS(b) R(b,0x5d) /* B transmit buffer status */
#define TCBADRL(b) R(b,0x38) /* transmit current buffer address lower */
#define TCBADRU(b) R(b,0x3a) /* transmit current buffer address upper */
/*
* Timer registers.
*/
#define TPR(b) R(b,0xd8) /* timer period register */
#define RTPR(b) R(b,0x26) /* receive timeout period register */
#define RTPRL(b) R(b,0x26) /* receive timeout period register low */
#define RTPTH(b) R(b,0x27) /* receive timeout period register high */
#define GT1(b) R(b,0x28) /* general timer 1 */
#define GT1L(b) R(b,0x28) /* general timer 1 low */
#define GT1H(b) R(b,0x29) /* general timer 1 high */
#define GT2(b) R(b,0x2a) /* general timer 2 */
#define TTR(b) R(b,0x2a) /* transmit timer register */
/*
* Board status register bits.
*/
#define BSR_NOINTR 0x01 /* no interrupt pending flag */
#define BSR_VAR_MASK 0x66 /* adapter variant mask */
#define BSR_OSC_MASK 0x18 /* oscillator frequency mask */
#define BSR_OSC_20 0x18 /* 20 MHz */
#define BSR_OSC_18432 0x10 /* 18.432 MHz */
#define BSR_NOCHAIN 0x80 /* no daisy chained board */
#define BSR_NODSR(n) (0x100 << (n)) /* DSR from channels 0-3, inverted */
#define BSR_NOCD(n) (0x1000 << (n)) /* CD from channels 0-3, inverted */
/*
* Board revision mask.
*/
#define BSR_REV_MASK (BSR_OSC_MASK|BSR_VAR_MASK|BSR_NOCHAIN)
/*
* Board control register 0 bits.
*/
#define BCR0_IRQ_DIS 0x00 /* no interrupt generated */
#define BCR0_IRQ_3 0x01 /* select IRQ number 3 */
#define BCR0_IRQ_5 0x02 /* select IRQ number 5 */
#define BCR0_IRQ_7 0x03 /* select IRQ number 7 */
#define BCR0_IRQ_10 0x04 /* select IRQ number 10 */
#define BCR0_IRQ_11 0x05 /* select IRQ number 11 */
#define BCR0_IRQ_12 0x06 /* select IRQ number 12 */
#define BCR0_IRQ_15 0x07 /* select IRQ number 15 */
#define BCR0_NORESET 0x08 /* CD2400 reset flag (inverted) */
#define BCR0_DMA_DIS 0x00 /* no interrupt generated */
#define BCR0_DMA_5 0x10 /* select DMA channel 5 */
#define BCR0_DMA_6 0x20 /* select DMA channel 6 */
#define BCR0_DMA_7 0x30 /* select DMA channel 7 */
#define BCR0_UM_ASYNC 0x00 /* channel 0 mode - async */
#define BCR0_UM_SYNC 0x80 /* channel 0 mode - sync */
#define BCR0_UI_RS232 0x00 /* channel 0 interface - RS-232 */
#define BCR0_UI_RS449 0x40 /* channel 0 interface - RS-449/V.35 */
#define BCR0_UMASK 0xc0 /* channel 0 interface mask */
/*
* Board control register 1 bits.
*/
#define BCR1_DTR(n) (0x100 << (n)) /* DTR for channels 0-3 sync */
/*
* Cronyx board variants.
*/
#define CRONYX_100 0x64
#define CRONYX_400 0x62
#define CRONYX_500 0x60
#define CRONYX_410 0x24
#define CRONYX_810 0x20
#define CRONYX_410s 0x04
#define CRONYX_810s 0x00
#define CRONYX_440 0x44
#define CRONYX_840 0x40
#define CRONYX_401 0x26
#define CRONYX_801 0x22
#define CRONYX_401s 0x06
#define CRONYX_801s 0x02
#define CRONYX_404 0x46
#define CRONYX_703 0x42
/*
* Channel commands (CCR).
*/
#define CCR_CLRCH 0x40 /* clear channel */
#define CCR_INITCH 0x20 /* initialize channel */
#define CCR_RSTALL 0x10 /* reset all channels */
#define CCR_ENTX 0x08 /* enable transmitter */
#define CCR_DISTX 0x04 /* disable transmitter */
#define CCR_ENRX 0x02 /* enable receiver */
#define CCR_DISRX 0x01 /* disable receiver */
#define CCR_CLRT1 0xc0 /* clear timer 1 */
#define CCR_CLRT2 0xa0 /* clear timer 2 */
#define CCR_CLRRCV 0x90 /* clear receiver */
/*
* Interrupt enable register (IER) bits.
*/
#define IER_MDM 0x80 /* modem status changed */
#define IER_RET 0x20 /* receive exception timeout */
#define IER_RXD 0x08 /* data received */
#define IER_TIMER 0x04 /* timer expired */
#define IER_TXMPTY 0x02 /* transmitter empty */
#define IER_TXD 0x01 /* data transmitted */
/*
* Modem signal values register bits (MSVR).
*/
#define MSV_DSR 0x80 /* state of Data Set Ready input */
#define MSV_CD 0x40 /* state of Carrier Detect input */
#define MSV_CTS 0x20 /* state of Clear to Send input */
#define MSV_TXCOUT 0x10 /* TXCout/DTR pin output flag */
#define MSV_PORTID 0x04 /* device is CL-CD2401 (not 2400) */
#define MSV_DTR 0x02 /* state of Data Terminal Ready output */
#define MSV_RTS 0x01 /* state of Request to Send output */
#define MSV_BITS "\20\1rts\2dtr\3cd2400\5txcout\6cts\7cd\10dsr"
/*
* DMA buffer status register bits (DMABSTS).
*/
#define DMABSTS_TDALIGN 0x80 /* internal data alignment in transmit FIFO */
#define DMABSTS_RSTAPD 0x40 /* reset append mode */
#define DMABSTS_CRTTBUF 0x20 /* internal current transmit buffer in use */
#define DMABSTS_APPEND 0x10 /* append buffer is in use */
#define DMABSTS_NTBUF 0x08 /* next transmit buffer is B (not A) */
#define DMABSTS_TBUSY 0x04 /* current transmit buffer is in use */
#define DMABSTS_NRBUF 0x02 /* next receive buffer is B (not A) */
#define DMABSTS_RBUSY 0x01 /* current receive buffer is in use */
/*
* Buffer status register bits ([AB][RT]BSTS).
*/
#define BSTS_BUSERR 0x80 /* bus error */
#define BSTS_EOFR 0x40 /* end of frame */
#define BSTS_EOBUF 0x20 /* end of buffer */
#define BSTS_APPEND 0x08 /* append mode */
#define BSTS_INTR 0x02 /* interrupt required */
#define BSTS_OWN24 0x01 /* buffer is (free to be) used by CD2400 */
#define BSTS_BITS "\20\1own24\2intr\4append\6eobuf\7eofr\10buserr"
/*
* Receive interrupt status register (RISR) bits.
*/
#define RIS_OVERRUN 0x0008 /* overrun error */
#define RIS_BB 0x0800 /* buffer B status (not A) */
#define RIS_EOBUF 0x2000 /* end of buffer reached */
#define RIS_EOFR 0x4000 /* frame reception complete */
#define RIS_BUSERR 0x8000 /* bus error */
#define RISH_CLRDCT 0x0001 /* X.21 clear detect */
#define RISH_RESIND 0x0004 /* residual indication */
#define RISH_CRCERR 0x0010 /* CRC error */
#define RISH_RXABORT 0x0020 /* abort sequence received */
#define RISH_EOFR 0x0040 /* complete frame received */
#define RISH_BITS "\20\1clrdct\3resind\4overrun\5crcerr\6rxabort\7eofr\14bb\16eobuf\17eofr\20buserr"
#define RISA_BREAK 0x0001 /* break signal detected */
#define RISA_FRERR 0x0002 /* frame error (bad stop bits) */
#define RISA_PARERR 0x0004 /* parity error */
#define RISA_SCMASK 0x0070 /* special character detect mask */
#define RISA_SCHR1 0x0010 /* special character 1 detected */
#define RISA_SCHR2 0x0020 /* special character 2 detected */
#define RISA_SCHR3 0x0030 /* special character 3 detected */
#define RISA_SCHR4 0x0040 /* special character 4 detected */
#define RISA_SCRANGE 0x0070 /* special character in range detected */
#define RISA_TIMEOUT 0x0080 /* receive timeout, no data */
#define RISA_BITS "\20\1break\2frerr\3parerr\4overrun\5schr1\6schr2\7schr4\10timeout\14bb\16eobuf\17eofr\20buserr"
#define RISB_CRCERR 0x0010 /* CRC error */
#define RISB_RXABORT 0x0020 /* abort sequence received */
#define RISB_EOFR 0x0040 /* complete frame received */
#define RISX_LEADCHG 0x0001 /* CTS lead change */
#define RISX_PARERR 0x0004 /* parity error */
#define RISX_SCMASK 0x0070 /* special character detect mask */
#define RISX_SCHR1 0x0010 /* special character 1 detected */
#define RISX_SCHR2 0x0020 /* special character 2 detected */
#define RISX_SCHR3 0x0030 /* special character 3 detected */
#define RISX_ALLZERO 0x0040 /* all 0 condition detected */
#define RISX_ALLONE 0x0050 /* all 1 condition detected */
#define RISX_ALTOZ 0x0060 /* alternating 1 0 condition detected */
#define RISX_SYN 0x0070 /* SYN detected */
#define RISX_LEAD 0x0080 /* leading value */
/*
* Channel mode register (CMR) bits.
*/
#define CMR_RXDMA 0x80 /* DMA receive transfer mode */
#define CMR_TXDMA 0x40 /* DMA transmit transfer mode */
#define CMR_HDLC 0x00 /* HDLC protocol mode */
#define CMR_BISYNC 0x01 /* BISYNC protocol mode */
#define CMR_ASYNC 0x02 /* ASYNC protocol mode */
#define CMR_X21 0x03 /* X.21 protocol mode */
/*
* Modem interrupt status register (MISR) bits.
*/
#define MIS_CDSR 0x80 /* DSR changed */
#define MIS_CCD 0x40 /* CD changed */
#define MIS_CCTS 0x20 /* CTS changed */
#define MIS_CGT2 0x02 /* GT2 timer expired */
#define MIS_CGT1 0x01 /* GT1 timer expired */
#define MIS_BITS "\20\1gt1\2gt2\6ccts\7ccd\10cdsr"
/*
* Transmit interrupt status register (TISR) bits.
*/
#define TIS_BUSERR 0x80 /* Bus error */
#define TIS_EOFR 0x40 /* End of frame */
#define TIS_EOBUF 0x20 /* end of transmit buffer reached */
#define TIS_UNDERRUN 0x10 /* transmit underrun */
#define TIS_BB 0x08 /* buffer B status (not A) */
#define TIS_TXEMPTY 0x02 /* transmitter empty */
#define TIS_TXDATA 0x01 /* transmit data below threshold */
#define TIS_BITS "\20\1txdata\2txempty\4bb\5underrun\6eobuf\7eofr\10buserr"
/*
* Local interrupt vector register (LIVR) bits.
*/
#define LIV_EXCEP 0
#define LIV_MODEM 1
#define LIV_TXDATA 2
#define LIV_RXDATA 3
/*
* Transmit end of interrupt registers (TEOIR) bits.
*/
#define TEOI_TERMBUFF 0x80 /* force current buffer to be discarded */
#define TEOI_EOFR 0x40 /* end of frame in interrupt mode */
#define TEOI_SETTM2 0x20 /* set general timer 2 in sync mode */
#define TEOI_SETTM1 0x10 /* set general timer 1 in sync mode */
#define TEOI_NOTRANSF 0x08 /* no transfer of data on this interrupt */
/*
* Receive end of interrupt registers (REOIR) bits.
*/
#define REOI_TERMBUFF 0x80 /* force current buffer to be terminated */
#define REOI_DISCEXC 0x40 /* discard exception character */
#define REOI_SETTM2 0x20 /* set general timer 2 */
#define REOI_SETTM1 0x10 /* set general timer 1 */
#define REOI_NOTRANSF 0x08 /* no transfer of data */
#define REOI_GAP_MASK 0x07 /* optional gap size to leave in buffer */
/*
* Special transmit command register (STCR) bits.
*/
#define STC_ABORTTX 0x40 /* abort transmission (HDLC mode) */
#define STC_APPDCMP 0x20 /* append complete (async DMA mode) */
#define STC_SNDSPC 0x08 /* send special characters (async mode) */
#define STC_SSPC_MASK 0x07 /* special character select */
#define STC_SSPC_1 0x01 /* send special character #1 */
#define STC_SSPC_2 0x02 /* send special character #2 */
#define STC_SSPC_3 0x03 /* send special character #3 */
#define STC_SSPC_4 0x04 /* send special character #4 */
/*
* Channel status register (CSR) bits, asynchronous mode.
*/
#define CSRA_RXEN 0x80 /* receiver enable */
#define CSRA_RXFLOFF 0x40 /* receiver flow off */
#define CSRA_RXFLON 0x20 /* receiver flow on */
#define CSRA_TXEN 0x08 /* transmitter enable */
#define CSRA_TXFLOFF 0x04 /* transmitter flow off */
#define CSRA_TXFLON 0x02 /* transmitter flow on */
#define CSRA_BITS "\20\2txflon\3txfloff\4txen\6rxflon\7rxfloff\10rxen"

818
sys/i386/isa/if_cx.c Normal file
View File

@ -0,0 +1,818 @@
/*
* Cronyx-Sigma adapter driver for FreeBSD.
* Supports PPP/HDLC and Cisco/HDLC protocol in synchronous mode,
* and asyncronous channels with full modem control.
* Keepalive protocol implemented in both Cisco and PPP modes.
*
* Copyright (C) 1994 Cronyx Ltd.
* Author: Serge Vakulenko, <vak@zebub.msk.su>
*
* This software is distributed with NO WARRANTIES, not even the implied
* warranties for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*
* Authors grant any other persons or organisations permission to use
* or modify this software as long as this message is kept with the software,
* all derivative works or modified versions.
*
* Version 1.2, Tue Nov 22 18:57:27 MSK 1994
*/
#undef DEBUG
#include "cx.h"
#if NCX > 0
#include <bpfilter.h>
#include <sys/param.h>
#include <systm.h>
#include <kernel.h>
#include <sys/mbuf.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/conf.h>
#include <sys/errno.h>
#include <net/if.h>
#include <net/if_types.h>
#if NBPFILTER > 0
#include <net/bpf.h>
#include <net/bpfdesc.h>
#endif
#ifdef __FreeBSD__
# include <i386/isa/isa_device.h>
# if __FreeBSD__ < 2
# include <i386/include/pio.h>
# else
# include <i386/include/cpufunc.h>
# include <sys/devconf.h>
# endif
# define init_func_t void(*)(int)
# define watchdog_func_t void(*)(int)
# define start_func_t void(*)(struct ifnet*)
#endif
#ifdef __bsdi__
# if INET
# include <netinet/in.h>
# include <netinet/in_systm.h>
# include <netinet/ip.h>
# endif
# include <sys/device.h>
# include <i386/isa/isavar.h>
# include <i386/isa/icu.h>
# include <i386/include/inline.h>
# include <net/if_slvar.h>
# include <net/if_p2p.h>
# define timeout_func_t void(*)()
# define init_func_t int(*)()
# define watchdog_func_t int(*)()
# define start_func_t int(*)()
struct cxsoftc {
struct device dev; /* base device */
struct isadev isadev; /* ISA device */
struct intrhand intr; /* interrupt vectoring */
};
#endif
#include <net/if_sppp.h>
#include <sys/cronyx.h>
#include <i386/isa/cxreg.h>
#ifdef DEBUG
# define print(s) printf s
#else
# define print(s) /*void*/
#endif
#define TXTIMEOUT 2 /* transmit timeout in seconds */
#define DMABUFSZ (6*256) /* buffer size */
#define PPP_HEADER_LEN 4 /* size of PPP header */
/*
* Under BSDI it's possible to use general p2p protocol scheme,
* as well as our own one. Switching is done via IFF_ALTPHYS flag.
* Our ifnet pointer holds the buffer large enough to contain
* any of sppp and p2p structures.
*/
#ifdef __bsdi__
# define SPPPSZ (sizeof (struct sppp))
# define P2PSZ (sizeof (struct p2pcom))
# define IFSTRUCTSZ (SPPPSZ>P2PSZ ? SPPPSZ : P2PSZ)
#else
# define IFSTRUCTSZ (sizeof (struct sppp))
#endif
#define IFNETSZ (sizeof (struct ifnet))
int cxoutput (struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst, struct rtentry *rt);
int cxsioctl (struct ifnet *ifp, int cmd, caddr_t data);
void cxinit (int unit);
void cxstart (struct ifnet *ifp);
void cxwatchdog (int unit);
void cxinput (cx_chan_t *c, void *buf, unsigned len);
int cxrinta (cx_chan_t *c);
void cxtinta (cx_chan_t *c);
void cxmint (cx_chan_t *c);
void cxtimeout (caddr_t a);
cx_board_t cxboard [NCX]; /* adapter state structures */
cx_chan_t *cxchan [NCX*NCHAN]; /* unit to channel struct pointer */
static unsigned short irq_valid_values [] = { 3, 5, 7, 10, 11, 12, 15, 0 };
static unsigned short drq_valid_values [] = { 5, 6, 7, 0 };
static unsigned short port_valid_values [] = {
0x240, 0x260, 0x280, 0x300, 0x320, 0x380, 0x3a0, 0,
};
#if __FreeBSD__ >= 2
static char cxdescription [80];
struct kern_devconf kdc_cx [NCX] = { {
0, 0, 0, "cx", 0, { MDDT_ISA, 0, "net" },
isa_generic_externalize, 0, 0, ISA_EXTERNALLEN, &kdc_isa0, 0,
DC_IDLE, cxdescription,
} };
#endif
/*
* Check that the value is contained in the list of correct values.
*/
static int valid (unsigned short value, unsigned short *list)
{
while (*list)
if (value == *list++)
return (1);
return (0);
}
/*
* Print the mbuf chain, for debug purposes only.
*/
static void printmbuf (struct mbuf *m)
{
printf ("mbuf:");
for (; m; m=m->m_next) {
if (m->m_flags & M_PKTHDR)
printf (" HDR %d:", m->m_pkthdr.len);
if (m->m_flags & M_EXT)
printf (" EXT:");
printf (" %d", m->m_len);
}
printf ("\n");
}
/*
* Make an mbuf from data.
*/
static struct mbuf *makembuf (void *buf, unsigned len)
{
struct mbuf *m, *o, *p;
MGETHDR (m, M_DONTWAIT, MT_DATA);
if (! m)
return (0);
if (len >= MINCLSIZE)
MCLGET (m, M_DONTWAIT);
m->m_pkthdr.len = len;
m->m_len = 0;
p = m;
while (len) {
unsigned n = M_TRAILINGSPACE (p);
if (n > len)
n = len;
if (! n) {
/* Allocate new mbuf. */
o = p;
MGET (p, M_DONTWAIT, MT_DATA);
if (! p) {
m_freem (m);
return (0);
}
if (len >= MINCLSIZE)
MCLGET (p, M_DONTWAIT);
p->m_len = 0;
o->m_next = p;
n = M_TRAILINGSPACE (p);
if (n > len)
n = len;
}
bcopy (buf, mtod (p, caddr_t) + p->m_len, n);
p->m_len += n;
buf += n;
len -= n;
}
return (m);
}
/*
* Test the presence of the adapter on the given i/o port.
*/
#ifdef __FreeBSD__
int cxprobe (struct isa_device *id)
{
int unit = id->id_unit;
int iobase = id->id_iobase;
int irq = id->id_irq;
int drq = id->id_drq;
int irqnum;
#endif
#ifdef __bsdi__
int cxprobe (struct device *parent, struct cfdata *cf, void *aux)
{
int unit = cf->cf_unit;
int iobase = ((struct isa_attach_args*)aux)->ia_iobase;
int irq = ((struct isa_attach_args*)aux)->ia_irq;
int drq = ((struct isa_attach_args*)aux)->ia_drq;
int irqnum, i;
for (i=0; i<NCX; ++i)
if (i != unit && cxboard[i].port == iobase)
return (0);
if (irq == IRQUNK) {
irq = isa_irqalloc (IRQ3|IRQ5|IRQ7|IRQ10|IRQ11|IRQ12|IRQ15);
if (! irq)
return (0);
((struct isa_attach_args*)aux)->ia_irq = irq;
}
#endif
irqnum = ffs (irq) - 1;
print (("cx%d: probe iobase=0x%x irq=%d drq=%d\n",
unit, iobase, irqnum, drq));
if (! valid (irqnum, irq_valid_values)) {
printf ("cx%d: Incorrect IRQ: %d\n", unit, irqnum);
return (0);
}
if (! valid (iobase, port_valid_values)) {
printf ("cx%d: Incorrect port address: 0x%x\n", unit, iobase);
return (0);
}
if (! valid (drq, drq_valid_values)) {
printf ("cx%d: Incorrect DMA channel: %d\n", unit, drq);
return (0);
}
if (! cx_probe_board (iobase))
return (0);
return (1);
}
/*
* The adapter is present, initialize the driver structures.
*/
#ifdef __FreeBSD__
int cxattach (struct isa_device *id)
{
int unit = id->id_unit;
int iobase = id->id_iobase;
int irq = id->id_irq;
int drq = id->id_drq;
#endif
#ifdef __bsdi__
void cxattach (struct device *parent, struct device *self, void *aux)
{
int unit = self->dv_unit;
int iobase = ((struct isa_attach_args*)aux)->ia_iobase;
int irq = ((struct isa_attach_args*)aux)->ia_irq;
int drq = ((struct isa_attach_args*)aux)->ia_drq;
struct cxsoftc *sc = (struct cxsoftc*) self;
void cxintr (cx_board_t *b);
#endif
cx_board_t *b = cxboard + unit;
int i;
/* Initialize the board structure. */
cx_init (b, unit, iobase, ffs(irq)-1, drq);
for (i=0; i<NCHAN; ++i) {
cx_chan_t *c = b->chan + i;
int u = b->num*NCHAN + i;
cxchan[u] = c;
if (c->type == T_NONE)
continue;
/* Allocate the buffer memory. */
c->arbuf = malloc (DMABUFSZ, M_DEVBUF, M_NOWAIT);
c->brbuf = malloc (DMABUFSZ, M_DEVBUF, M_NOWAIT);
c->atbuf = malloc (DMABUFSZ, M_DEVBUF, M_NOWAIT);
c->btbuf = malloc (DMABUFSZ, M_DEVBUF, M_NOWAIT);
/* All buffers should be located in lower 16M of memory! */
if (!c->arbuf || !c->brbuf || !c->atbuf || !c->btbuf) {
printf ("cx%d.%d: No memory for channel buffers\n",
c->board->num, c->num);
c->type = T_NONE;
}
switch (c->type) {
case T_SYNC_RS232:
case T_SYNC_V35:
case T_SYNC_RS449:
case T_UNIV_RS232:
case T_UNIV_RS449:
case T_UNIV_V35:
c->ifp = malloc (IFSTRUCTSZ, M_DEVBUF, M_NOWAIT);
if (! c->ifp) {
printf ("cx%d.%d: No memory for ifnet buffer\n",
c->board->num, c->num);
c->type = T_NONE;
continue;
}
c->ifp->if_unit = u;
c->ifp->if_name = "cx";
c->ifp->if_mtu = PP_MTU;
c->ifp->if_flags = IFF_POINTOPOINT|IFF_MULTICAST;
c->ifp->if_ioctl = cxsioctl;
c->ifp->if_start = (start_func_t) cxstart;
c->ifp->if_watchdog = (watchdog_func_t) cxwatchdog;
/* Init routine is never called by upper level? */
c->ifp->if_init = (init_func_t) cxinit;
sppp_attach (c->ifp);
if_attach (c->ifp);
#if NBPFILTER > 0
/* If BPF is in the kernel, call the attach for it. */
bpfattach (&c->bpf, c->ifp, DLT_PPP, PPP_HEADER_LEN);
#endif
}
}
/* Reset the adapter. */
cx_setup_board (b);
/* Activate the timeout routine. */
if (unit == 0)
timeout ((timeout_func_t) cxtimeout, 0, hz*5);
#if __FreeBSD__ >= 2
if (unit != 0)
kdc_cx[unit] = kdc_cx[0];
kdc_cx[unit].kdc_unit = unit;
kdc_cx[unit].kdc_isa = id;
sprintf (cxdescription, "Cronyx-Sigma-%s sync/async serial adapter",
b->name);
dev_attach (&kdc_cx[unit]);
#endif
#ifdef __FreeBSD__
printf ("cx%d: <Cronyx-%s>\n", unit, b->name);
return (1);
#endif
#ifdef __bsdi__
printf (": <Cronyx-%s>\n", b->name);
isa_establish (&sc->isadev, &sc->dev);
sc->intr.ih_fun = (int(*)()) cxintr;
sc->intr.ih_arg = (void*) b;
intr_establish (irq, &sc->intr, DV_NET);
#endif
}
#ifdef __FreeBSD__
struct isa_driver cxdriver = { cxprobe, cxattach, "cx" };
#endif
#ifdef __bsdi__
struct cfdriver cxcd = { 0, "cx", cxprobe, cxattach, sizeof (struct cxsoftc) };
#endif
/*
* Process an ioctl request.
*/
int cxsioctl (struct ifnet *ifp, int cmd, caddr_t data)
{
cx_chan_t *c = cxchan[ifp->if_unit];
int error, s;
if (c->type==T_NONE || c->mode==M_ASYNC)
return (EINVAL);
#ifdef __bsdi__
if (c->sopt.ext) {
/* Save RUNNING flag. */
int running = (ifp->if_flags & IFF_RUNNING);
error = p2p_ioctl (ifp, cmd, data);
ifp->if_flags &= ~IFF_RUNNING;
ifp->if_flags |= running;
} else
#endif
error = sppp_ioctl (ifp, cmd, data);
if (error)
return (error);
if (cmd != SIOCSIFFLAGS)
return (0);
s = splimp ();
if (! (ifp->if_flags & IFF_UP) && (ifp->if_flags & IFF_RUNNING))
/* Interface is down and running -- stop it. */
cxinit (ifp->if_unit);
else if ((ifp->if_flags & IFF_UP) && ! (ifp->if_flags & IFF_RUNNING))
/* Interface is up and not running -- start it. */
cxinit (ifp->if_unit);
splx (s);
return (0);
}
/*
* Initialization of interface.
*/
void cxinit (int unit)
{
cx_chan_t *c = cxchan[unit];
unsigned short port = c->chip->port;
int s;
print (("cx%d.%d: cxinit\n", c->board->num, c->num));
/* Disable interrupts */
s = splimp();
/* Reset the channel (for sync modes only) */
if (c->ifp->if_flags & IFF_OACTIVE) {
outb (CAR(port), c->num & 3);
outb (STCR(port), STC_ABORTTX | STC_SNDSPC);
}
cx_setup_chan (c);
c->ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
if (c->ifp->if_flags & IFF_UP) {
/* The interface is up, start it */
c->ifp->if_flags |= IFF_RUNNING;
#if __FreeBSD__ >= 2
/* Mark the board busy on the first startup.
* Never goes idle. */
kdc_cx[c->board->num].kdc_state = DC_BUSY;
#endif
/* Initialize channel, enable receiver and transmitter */
cx_cmd (port, CCR_INITCH | CCR_ENRX | CCR_ENTX);
/* Repeat the command, to avoid the rev.H bug */
cx_cmd (port, CCR_INITCH | CCR_ENRX | CCR_ENTX);
/* Start receiver */
outw (ARBCNT(port), DMABUFSZ);
outb (ARBSTS(port), BSTS_OWN24);
outw (BRBCNT(port), DMABUFSZ);
outb (BRBSTS(port), BSTS_OWN24);
/* Raise DTR and RTS */
cx_chan_dtr (c, 1);
cx_chan_rts (c, 1);
/* Enable interrupts */
outb (IER(port), IER_RXD | IER_TXD);
cxstart (c->ifp);
} else if (! c->sopt.ext)
/* Flush the interface output queue, if it is down */
sppp_flush (c->ifp);
splx (s);
}
/*
* Fill transmitter buffer with data.
*/
void cxput (cx_chan_t *c, char b)
{
struct mbuf *m;
unsigned char *buf;
unsigned short port = c->chip->port, len, cnt_port, sts_port;
/* Choose the buffer. */
if (b == 'A') {
buf = c->atbuf;
cnt_port = ATBCNT(port);
sts_port = ATBSTS(port);
} else {
buf = c->btbuf;
cnt_port = BTBCNT(port);
sts_port = BTBSTS(port);
}
/* Is it busy? */
if (inb (sts_port) & BSTS_OWN24) {
c->ifp->if_flags |= IFF_OACTIVE;
return;
}
/* Get the packet to send. */
#ifdef __bsdi__
if (c->sopt.ext) {
struct p2pcom *p = (struct p2pcom*) c->ifp;
int s = splimp ();
IF_DEQUEUE (&p->p2p_isnd, m)
if (! m)
IF_DEQUEUE (&c->ifp->if_snd, m)
splx (s);
} else
#endif
m = sppp_dequeue (c->ifp);
if (! m)
return;
len = m->m_pkthdr.len;
if (len >= DMABUFSZ) {
printf ("cx%d.%d: too long packet: %d bytes\n",
c->board->num, c->num, len);
printmbuf (m);
m_freem (m);
return;
}
m_copydata (m, 0, len, buf);
#if NBPFILTER > 0
if (c->bpf)
bpf_mtap (c->bpf, m);
#endif
m_freem (m);
/* Start transmitter. */
outw (cnt_port, len);
outb (sts_port, BSTS_EOFR | BSTS_INTR | BSTS_OWN24);
#ifdef DEBUG
if (c->ifp->if_flags & IFF_DEBUG)
printf ("cx%d.%d: enqueue %d bytes to %c\n",
c->board->num, c->num, len, buf==c->atbuf ? 'A' : 'B');
#endif
c->ifp->if_flags |= IFF_OACTIVE;
}
/*
* Start output on interface. Get another datagram to send
* off of the interface queue, and copy it to the interface
* before starting the output.
*/
void cxstart (struct ifnet *ifp)
{
cx_chan_t *c = cxchan[ifp->if_unit];
unsigned short port = c->chip->port;
/* No output if the interface is down. */
if (! (ifp->if_flags & IFF_RUNNING))
return;
/* Set the current channel number. */
outb (CAR(port), c->num & 3);
/* Determine the buffer order. */
if (inb (DMABSTS(port)) & DMABSTS_NTBUF) {
cxput (c, 'B');
cxput (c, 'A');
} else {
cxput (c, 'A');
cxput (c, 'B');
}
/* Set up transmit timeout. */
if (c->ifp->if_flags & IFF_OACTIVE)
c->ifp->if_timer = TXTIMEOUT;
/*
* Enable TXMPTY interrupt,
* to catch the case when the second buffer is empty.
*/
if ((inb (ATBSTS(port)) & BSTS_OWN24) &&
(inb (BTBSTS(port)) & BSTS_OWN24)) {
outb (IER(port), IER_RXD | IER_TXD | IER_TXMPTY);
} else
outb (IER(port), IER_RXD | IER_TXD);
}
/*
* Handle transmit timeouts.
* Recover after lost transmit interrupts.
*/
void cxwatchdog (int unit)
{
cx_chan_t *c = cxchan[unit];
if (c->ifp->if_flags & IFF_OACTIVE) {
c->ifp->if_flags &= ~IFF_OACTIVE;
cxstart (c->ifp);
}
}
/*
* Handle receive interrupts, including receive errors and
* receive timeout interrupt.
*/
void cxrinth (cx_chan_t *c)
{
unsigned short port = c->chip->port;
unsigned short len, risr = inw (RISR(port));
print (("cx%d.%d: hdlc receive interrupt, risr=%b, arbsts=%b, brbsts=%b\n",
c->board->num, c->num, risr, RISH_BITS,
inb (ARBSTS(port)), BSTS_BITS, inb (BRBSTS(port)), BSTS_BITS));
/* Receive errors. */
if (risr & (RIS_BUSERR | RIS_OVERRUN | RISH_CRCERR | RISH_RXABORT)) {
if (c->ifp->if_flags & IFF_DEBUG)
printf ("cx%d.%d: receive error, risr=%b\n",
c->board->num, c->num, risr, RISH_BITS);
++c->ifp->if_ierrors;
if (risr & RIS_OVERRUN)
++c->ifp->if_collisions;
} else if (risr & RIS_EOBUF) {
/* Handle received data. */
len = (risr & RIS_BB) ? inw(BRBCNT(port)) : inw(ARBCNT(port));
if (len > DMABUFSZ) {
/* Fatal error: actual DMA transfer size
* exceeds our buffer size. It could be caused
* by incorrectly programmed DMA register or
* hardware fault. Possibly, should panic here. */
printf ("cx%d.%d: panic! DMA buffer overflow: %d bytes\n",
c->board->num, c->num, len);
++c->ifp->if_ierrors;
} else if (! (risr & RIS_EOFR)) {
/* The received frame does not fit in the DMA buffer.
* It could be caused by serial lie noise,
* or if the peer has too big MTU. */
if (c->ifp->if_flags & IFF_DEBUG)
printf ("cx%d.%d: received frame length exceeds MTU, risr=%b\n",
c->board->num, c->num, risr, RISH_BITS);
++c->ifp->if_ierrors;
} else {
/* Valid frame received. */
print (("cx%d.%d: HDLC: %d bytes received\n",
c->board->num, c->num, len));
cxinput (c, (risr & RIS_BB) ? c->brbuf : c->arbuf, len);
++c->ifp->if_ipackets;
}
}
/* Restart receiver. */
if (! (inb (ARBSTS(port)) & BSTS_OWN24)) {
outw (ARBCNT(port), DMABUFSZ);
outb (ARBSTS(port), BSTS_OWN24);
}
if (! (inb (BRBSTS(port)) & BSTS_OWN24)) {
outw (BRBCNT(port), DMABUFSZ);
outb (BRBSTS(port), BSTS_OWN24);
}
}
/*
* Handle transmit interrupt.
*/
int cxtinth (cx_chan_t *c)
{
unsigned short port = c->chip->port;
unsigned char tisr = inb (TISR(port));
unsigned char teoir = 0;
print (("cx%d.%d: hdlc transmit interrupt, tisr=%b, atbsts=%b, btbsts=%b\n",
c->board->num, c->num, tisr, TIS_BITS,
inb (ATBSTS(port)), BSTS_BITS, inb (BTBSTS(port)), BSTS_BITS));
if (tisr & (TIS_BUSERR | TIS_UNDERRUN)) {
if (c->ifp->if_flags & IFF_DEBUG)
printf ("cx%d.%d: transmit error, tisr=%b\n",
c->board->num, c->num, tisr, TIS_BITS);
++c->ifp->if_oerrors;
/* Terminate the failed buffer. */
teoir |= TEOI_TERMBUFF;
} else if (tisr & (TIS_EOFR))
++c->ifp->if_opackets;
c->ifp->if_flags &= ~IFF_OACTIVE;
cxstart (c->ifp);
return (teoir);
}
#ifdef __FreeBSD__
void cxintr (int bnum)
{
cx_board_t *b = cxboard + bnum;
#endif
#ifdef __bsdi__
void cxintr (cx_board_t *b)
{
#endif
while (! (inw (BSR(b->port)) & BSR_NOINTR)) {
/* Acknowledge the interrupt to enter the interrupt context. */
/* Read the local interrupt vector register. */
unsigned char livr = inb (IACK(b->port, BRD_INTR_LEVEL));
cx_chan_t *c = b->chan + (livr>>2 & 0xf);
unsigned short port = c->chip->port;
unsigned short eoiport = REOIR(port);
unsigned char eoi = 0;
if (c->type == T_NONE) {
printf ("cx%d.%d: unexpected interrupt, livr=0x%x\n",
c->board->num, c->num, livr);
continue; /* incorrect channel number? */
}
/* print (("cx%d.%d: interrupt, livr=0x%x\n",
c->board->num, c->num, livr)); */
/* Clear RTS to stop receiver data flow while we are busy
* processing the interrupt, thus avoiding underruns. */
if (! c->sopt.norts) {
outb (MSVR_RTS(port), 0);
c->rts = 0;
}
switch (livr & 3) {
case LIV_EXCEP: /* receive exception */
case LIV_RXDATA: /* receive interrupt */
switch (c->mode) {
case M_ASYNC: eoi = cxrinta (c); break;
case M_HDLC: cxrinth (c); break;
default:; /* No bisync and X.21 yet */
}
break;
case LIV_TXDATA: /* transmit interrupt */
eoiport = TEOIR(port);
switch (c->mode) {
case M_ASYNC: cxtinta (c); break;
case M_HDLC: eoi = cxtinth (c); break;
default:; /* No bisync and X.21 yet */
}
break;
case LIV_MODEM: /* modem/timer interrupt */
eoiport = MEOIR(port);
cxmint (c);
break;
}
/* Raise RTS for this channel if and only if
* both receive buffers are empty. */
if (! c->sopt.norts && (inb (CSR(port)) & CSRA_RXEN) &&
(inb (ARBSTS(port)) & BSTS_OWN24) &&
(inb (BRBSTS(port)) & BSTS_OWN24)) {
outb (MSVR_RTS(port), MSV_RTS);
c->rts = 1;
}
/* Exit from interrupt context. */
outb (eoiport, eoi);
}
}
/*
* Process the received packet.
*/
void cxinput (cx_chan_t *c, void *buf, unsigned len)
{
/* Make an mbuf. */
struct mbuf *m = makembuf (buf, len);
if (! m) {
if (c->ifp->if_flags & IFF_DEBUG)
printf ("cx%d.%d: no memory for packet\n",
c->board->num, c->num);
++c->ifp->if_iqdrops;
return;
}
m->m_pkthdr.rcvif = c->ifp;
#ifdef DEBUG
printmbuf (m);
#endif
#if NBPFILTER > 0
/*
* Check if there's a BPF listener on this interface.
* If so, hand off the raw packet to bpf.
*/
if (c->bpf)
bpf_tap (c->bpf, buf, len);
#endif
#ifdef __bsdi__
if (c->sopt.ext) {
struct p2pcom *p = (struct p2pcom*) c->ifp;
(*p->p2p_input) (p, m);
} else
#endif
sppp_input (c->ifp, m);
}
void cxswitch (cx_chan_t *c, cx_soft_opt_t new)
{
#ifdef __bsdi__
if (new.ext && ! c->sopt.ext) {
/* Switch to external ppp implementation (BSDI) */
sppp_detach (c->ifp);
bzero ((void*) c->ifp + IFNETSZ, IFSTRUCTSZ-IFNETSZ);
} else if (! new.ext && c->sopt.ext) {
/* Switch to built-in ppp implementation */
bzero ((void*) c->ifp + IFNETSZ, IFSTRUCTSZ-IFNETSZ);
sppp_attach (c->ifp);
}
#else
new.ext = 0;
#endif
if (! new.ext) {
struct sppp *sp = (struct sppp*) c->ifp;
if (new.cisco)
sp->pp_flags |= PP_CISCO;
else
sp->pp_flags &= ~PP_CISCO;
if (new.keepalive)
sp->pp_flags |= PP_KEEPALIVE;
else
sp->pp_flags &= ~PP_KEEPALIVE;
}
c->sopt = new;
}
#endif /* NCX */

70
sys/net/if_sppp.h Normal file
View File

@ -0,0 +1,70 @@
/*
* Defines for synchronous PPP/Cisco link level subroutines.
*
* Copyright (C) 1994 Cronyx Ltd.
* Author: Serge Vakulenko, <vak@zebub.msk.su>
*
* This software is distributed with NO WARRANTIES, not even the implied
* warranties for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*
* Authors grant any other persons or organisations permission to use
* or modify this software as long as this message is kept with the software,
* all derivative works or modified versions.
*
* Version 1.1, Thu Oct 27 21:15:02 MSK 1994
*/
#ifndef _NET_IF_HDLC_H_
#define _NET_IF_HDLC_H_ 1
struct slcp {
u_short state; /* state machine */
u_long magic; /* local magic number */
u_long rmagic; /* remote magic number */
u_char lastid; /* id of last keepalive echo request */
};
struct sipcp {
u_short state; /* state machine */
};
struct sppp {
struct ifnet pp_if; /* network interface data */
struct ifqueue pp_fastq; /* fast output queue */
struct sppp *pp_next; /* next interface in keepalive list */
u_int pp_flags; /* use Cisco protocol instead of PPP */
u_short pp_alivecnt; /* keepalive packets counter */
u_short pp_loopcnt; /* loopback detection counter */
u_long pp_seq; /* local sequence number */
u_long pp_rseq; /* remote sequence number */
struct slcp lcp; /* LCP params */
struct sipcp ipcp; /* IPCP params */
};
#define PP_KEEPALIVE 0x01 /* use keepalive protocol */
#define PP_CISCO 0x02 /* use Cisco protocol instead of PPP */
#define PP_MTU 1500 /* max. transmit unit */
#define LCP_STATE_CLOSED 0 /* LCP state: closed (conf-req sent) */
#define LCP_STATE_ACK_RCVD 1 /* LCP state: conf-ack received */
#define LCP_STATE_ACK_SENT 2 /* LCP state: conf-ack sent */
#define LCP_STATE_OPENED 3 /* LCP state: opened */
#define IPCP_STATE_CLOSED 0 /* IPCP state: closed (conf-req sent) */
#define IPCP_STATE_ACK_RCVD 1 /* IPCP state: conf-ack received */
#define IPCP_STATE_ACK_SENT 2 /* IPCP state: conf-ack sent */
#define IPCP_STATE_OPENED 3 /* IPCP state: opened */
#ifdef KERNEL
void sppp_attach (struct ifnet *ifp);
void sppp_detach (struct ifnet *ifp);
void sppp_input (struct ifnet *ifp, struct mbuf *m);
int sppp_output (struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst,
struct rtentry *rt);
int sppp_ioctl (struct ifnet *ifp, int cmd, caddr_t data);
struct mbuf *sppp_dequeue (struct ifnet *ifp);
void sppp_flush (struct ifnet *ifp);
#endif
#endif /* _NET_IF_HDLC_H_ */

1219
sys/net/if_spppsubr.c Normal file

File diff suppressed because it is too large Load Diff