* Center for Seismic Studies
* 1300 N 17th Street, Suite 1450
* Arlington, Virginia 22209
* Some things done here could obviously be done in a better way,
* but they were done this way to minimize the number of files
* that had to be changed to accomodate this device.
* A lot of this code belongs in the tty driver.
* Pounded on heavily by Chris Torek (chris@mimsy.umd.edu, umcp-cs!chris).
* N.B.: this belongs in netinet, not vaxif, the way it stands now.
* Converted to 4.3BSD Beta by Chris Torek.
/* $Header: if_sl.c,v 1.12 85/12/20 21:54:55 chris Exp $ */
/* from if_sl.c,v 1.11 84/10/04 12:54:47 rick Exp */
#include "../net/netisr.h"
#include "../net/route.h"
#include "../netinet/in.h"
#include "../netinet/in_systm.h"
#include "../netinet/ip.h"
#include "../netinet/ip_var.h"
* N.B.: SLMTU is now a hard limit on input packet size. Some limit
* is required, lest we use up all mbufs in the case of deleterious data
* dribbling down the line.
struct ifnet sc_if
; /* network-visible interface */
short sc_flags
; /* see below */
short sc_ilen
; /* length of input-packet-so-far */
struct tty
*sc_ttyp
; /* pointer to tty structure */
char *sc_mp
; /* pointer to next available buf char */
char sc_buf
[SLMTU
]; /* input buffer */
#define SC_ESCAPED 0x0001 /* saw a FRAME_ESCAPE */
#define SC_OACTIVE 0x0002 /* output tty is active */
#define FRAME_END 0300 /* Frame End */
#define FRAME_ESCAPE 0333 /* Frame Esc */
#define TRANS_FRAME_END 0334 /* transposed frame end */
#define TRANS_FRAME_ESCAPE 0335 /* transposed frame esc */
int sloutput(), slioctl(), ttrstrt();
* Called from boot code to establish sl interfaces.
register struct sl_softc
*sc
;
for (sc
= sl_softc
; i
< NSL
; sc
++) {
sc
->sc_if
.if_name
= "sl";
sc
->sc_if
.if_mtu
= SLMTU
;
sc
->sc_if
.if_flags
= IFF_POINTOPOINT
;
sc
->sc_if
.if_ioctl
= slioctl
;
sc
->sc_if
.if_output
= sloutput
;
sc
->sc_if
.if_snd
.ifq_maxlen
= IFQ_MAXLEN
;
* Line specific open routine.
* Attach the given tty to the first available sl unit.
register struct sl_softc
*sc
;
for (nsl
= 0, sc
= sl_softc
; nsl
< NSL
; nsl
++, sc
++)
if (sc
->sc_ttyp
== NULL
) {
* Line specific close routine.
* Detach the tty from the sl unit.
* Mimics part of ttyclose().
register struct sl_softc
*sc
;
s
= splimp(); /* paranoid; splnet probably ok */
sc
= (struct sl_softc
*)tp
->t_sc
;
* Line specific (tty) ioctl routine.
* Provide a way to get the sl unit number.
sltioctl(tp
, cmd
, data
, flag
)
*(int *)data
= ((struct sl_softc
*)tp
->t_sc
)->sc_if
.if_unit
;
* Queue a packet. Start transmission if not active.
register struct ifnet
*ifp
;
register struct sl_softc
*sc
;
* `Cannot happen' (see slioctl). Someday we will extend
* the line protocol to support other address families.
if (dst
->sa_family
!= AF_INET
) {
printf("sl%d: af%d not supported\n", ifp
->if_unit
,
sc
= &sl_softc
[ifp
->if_unit
];
if (sc
->sc_ttyp
== NULL
) {
return (ENETDOWN
); /* sort of */
if (IF_QFULL(&ifp
->if_snd
)) {
sc
->sc_if
.if_collisions
++;
IF_ENQUEUE(&ifp
->if_snd
, m
);
if ((sc
->sc_flags
& SC_OACTIVE
) == 0) {
* Start output on interface. Get another datagram
* to send from the interface queue and map it to
* the interface before starting output.
register struct sl_softc
*sc
= (struct sl_softc
*)tp
->t_sc
;
* If there is more in the output queue, just send it now.
* We are being called in lieu of ttstart and must do what
if (tp
->t_outq
.c_cc
> 0) {
* This happens briefly when the line shuts down.
* Get a packet and map it to the interface.
IF_DEQUEUE(&sc
->sc_if
.if_snd
, m
);
sc
->sc_flags
&= ~SC_OACTIVE
;
flush
= !(sc
->sc_flags
& SC_OACTIVE
);
sc
->sc_flags
|= SC_OACTIVE
;
* The extra FRAME_END will start up a new packet, and thus
* will flush any accumulated garbage. We do this whenever
* the line may have been idle for some time.
(void) putc(FRAME_END
, &tp
->t_outq
);
if (c
== FRAME_ESCAPE
|| c
== FRAME_END
) {
if (putc(FRAME_ESCAPE
, &tp
->t_outq
))
c
= c
== FRAME_ESCAPE
? TRANS_FRAME_ESCAPE
:
if (putc(c
, &tp
->t_outq
)) {
(void) unputc(&tp
->t_outq
);
if (putc(c
, &tp
->t_outq
))
if (putc(FRAME_END
, &tp
->t_outq
)) {
* If you get many oerrors (more than one or two a day)
* you probably do not have enough clists and you should
* increase "nclist" in param.c.
(void) unputc(&tp
->t_outq
); /* make room */
putc(FRAME_END
, &tp
->t_outq
); /* end the packet */
* Start transmission. Note that slstart, not ttstart, will be
* called when the transmission completes, be that after a single
* piece of what we have mapped, or be it after the entire thing
* has been sent. That is why we need to check the output queue
* Copy data buffer to mbuf chain; add ifnet pointer ifp.
register struct mbuf
*m
, **mp
;
MGET(m
, M_DONTWAIT
, MT_DATA
);
count
= MIN(len
, MLEN
- sizeof(ifp
));
count
= MIN(len
, CLBYTES
);
m
->m_off
= (int)p
- (int)m
;
bcopy(addr
, mtod(m
, caddr_t
), count
);
*mtod(m
, struct ifnet
**) = ifp
;
* tty interface receiver interrupt.
register struct sl_softc
*sc
;
sc
= (struct sl_softc
*)tp
->t_sc
;
if (sc
->sc_flags
& SC_ESCAPED
) {
sc
->sc_flags
&= ~SC_ESCAPED
;
if (sc
->sc_ilen
== 0) /* ignore */
m
= sl_btom(sc
->sc_buf
, sc
->sc_ilen
, &sc
->sc_if
);
if (IF_QFULL(&ipintrq
)) {
sc
->sc_flags
|= SC_ESCAPED
;
if (++sc
->sc_ilen
>= SLMTU
) {
* Process an ioctl request.
register struct ifnet
*ifp
;
register struct ifaddr
*ifa
= (struct ifaddr
*)data
;
int s
= splimp(), error
= 0;
if (ifa
->ifa_addr
.sa_family
== AF_INET
)
if (ifa
->ifa_addr
.sa_family
!= AF_INET
)