-
Notifications
You must be signed in to change notification settings - Fork 9
/
asy.c
170 lines (158 loc) · 3.9 KB
/
asy.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
/* Generic serial line interface routines
* Copyright 1992 Phil Karn, KA9Q
*/
#include <stdio.h>
#include "global.h"
#include "proc.h"
#include "iface.h"
#include "netuser.h"
#include "slhc.h"
#include "n8250.h"
#include "asy.h"
#include "ax25.h"
#include "kiss.h"
#include "nrs.h"
#include "pktdrvr.h"
#include "slip.h"
#include "ppp.h"
#include "commands.h"
static int asy_detach(struct iface *ifp);
/* Attach a serial interface to the system
* argv[0]: hardware type, must be "asy"
* argv[1]: I/O address, e.g., "0x3f8"
* argv[2]: vector, e.g., "4", or "fp1" for port 1 on a 4port card
* argv[3]: mode, may be:
* "slip" (point-to-point SLIP)
* "kissui" (AX.25 UI frame format in SLIP for raw TNC)
* "ax25ui" (same as kissui)
* "kissi" (AX.25 I frame format in SLIP for raw TNC)
* "ax25i" (same as kissi)
* "nrs" (NET/ROM format serial protocol)
* "ppp" (Point-to-Point Protocol, RFC1171, RFC1172)
* argv[4]: interface label, e.g., "sl0"
* argv[5]: receiver ring buffer size in bytes
* argv[6]: maximum transmission unit, bytes
* argv[7]: interface speed, e.g, "9600"
* argv[8]: optional flags,
* 'v' for Van Jacobson TCP header compression (SLIP only,
* use ppp command for VJ compression with PPP);
* 'c' for cts flow control
* 'r' for rlsd (cd) detection
*/
int
asy_attach(argc,argv,p)
int argc;
char *argv[];
void *p;
{
register struct iface *ifp;
int dev;
int trigchar = -1;
int cts,rlsd;
struct asymode *ap;
char *cp;
int base;
int irq;
struct asy *asyp;
int i,n;
int chain;
if(if_lookup(argv[4]) != NULL){
printf("Interface %s already exists\n",argv[4]);
return -1;
}
if(setencap(NULL,argv[3]) == -1){
printf("Unknown encapsulation %s\n",argv[3]);
return -1;
}
/* Find unused asy control block */
for(dev=0;dev < ASY_MAX;dev++){
if(Asy[dev].iface == NULL)
break;
}
if(dev >= ASY_MAX){
printf("Too many asynch controllers\n");
return -1;
}
asyp = &Asy[dev];
base = htoi(argv[1]);
if(*argv[2] == 's'){
/* This is a port on a 4port card with shared interrupt */
for(i=0;i<FPORT_MAX;i++){
if(base >= Fport[i].base && base < Fport[i].base+32){
n = (base - Fport[i].base) >> 3;
Fport[i].asy[n] = asyp;
break;
}
}
if(i == FPORT_MAX){
printf("%x not a known 4port address\n");
return -1;
}
irq = -1;
} else
irq = atoi(argv[2]);
/* Create interface structure and fill in details */
ifp = (struct iface *)callocw(1,sizeof(struct iface));
ifp->addr = Ip_addr;
ifp->name = strdup(argv[4]);
ifp->mtu = atoi(argv[6]);
ifp->dev = dev;
ifp->stop = asy_detach;
setencap(ifp,argv[3]);
/* Look for the interface mode in the table */
for(ap = Asymode;ap->name != NULL;ap++){
if(stricmp(argv[3],ap->name) == 0){
trigchar = ap->trigchar;
if((*ap->init)(ifp) != 0){
printf("%s: mode %s Init failed\n",
ifp->name,argv[3]);
if_detach(ifp);
return -1;
}
break;
}
}
if(ap->name == NULL){
printf("Mode %s unknown for interface %s\n",argv[3],argv[4]);
if_detach(ifp);
return -1;
}
/* Link in the interface */
ifp->next = Ifaces;
Ifaces = ifp;
cts = rlsd = 0;
if(argc > 8){
if(strchr(argv[8],'c') != NULL)
cts = 1;
if(strchr(argv[8],'r') != NULL)
rlsd = 1;
}
if(strchr(argv[2],'c') != NULL)
chain = 1;
else
chain = 0;
asy_init(dev,ifp,base,irq,(uint16)atol(argv[5]),
trigchar,atol(argv[7]),cts,rlsd,chain);
cp = if_name(ifp," tx");
ifp->txproc = newproc(cp,768,if_tx,0,ifp,NULL,0);
free(cp);
return 0;
}
static int
asy_detach(ifp)
struct iface *ifp;
{
struct asymode *ap;
if(ifp == NULL)
return -1;
asy_stop(ifp);
/* Call mode-dependent routine */
for(ap = Asymode;ap->name != NULL;ap++){
if(ifp->iftype != NULL
&& stricmp(ifp->iftype->name,ap->name) == 0
&& ap->free != NULL){
(*ap->free)(ifp);
}
}
return 0;
}