before carry to ARPAVAX
[unix-history] / usr / src / sys / vax / if / if_en.c
CommitLineData
8a13b737 1/* if_en.c 4.14 81/11/26 */
11720282
BJ
2
3#include "en.h"
4/*
5 * Ethernet interface driver
6 */
7
8#include "../h/param.h"
9#include "../h/systm.h"
10#include "../h/mbuf.h"
11720282
BJ
11#include "../h/pte.h"
12#include "../h/buf.h"
8a13b737
BJ
13#include "../h/protosw.h"
14#include "../h/socket.h"
11720282
BJ
15#include "../h/ubareg.h"
16#include "../h/ubavar.h"
11720282 17#include "../h/enreg.h"
11720282 18#include "../h/cpu.h"
8a13b737
BJ
19#include "../h/mtpr.h"
20#include "../h/vmmac.h"
21#include "../net/in.h"
22#include "../net/in_systm.h"
23#include "../net/if.h"
24#include "../net/if_en.h"
25#include "../net/if_uba.h"
26#include "../net/ip.h"
27#include "../net/ip_var.h"
28
29#define ENMTU 1024
11720282 30
11720282
BJ
31int enprobe(), enattach(), enrint(), enxint(), encollide();
32struct uba_device *eninfo[NEN];
33u_short enstd[] = { 0 };
34struct uba_driver endriver =
8a13b737 35 { enprobe, 0, enattach, 0, enstd, "es", eninfo };
11720282
BJ
36#define ENUNIT(x) minor(x)
37
8a13b737
BJ
38struct en_softc {
39 struct ifnet *es_if;
40 struct ifuba *es_ifuba;
41 short es_delay;
42 short es_mask;
43 u_char es_addr;
44 u_char es_lastx;
45 short es_oactive;
46 short es_olen;
47} en_softc[NEN];
11720282
BJ
48
49enprobe(reg)
50 caddr_t reg;
51{
52 register int br, cvec;
53 register struct endevice *addr = (struct endevice *)reg;
54
8a13b737 55COUNT(ENPROBE);
11720282
BJ
56#ifdef lint
57 br = 0; cvec = br; br = cvec;
2b4b57cd 58 enrint(0); enxint(0); encollide(0);
11720282 59#endif
11720282 60 addr->en_istat = 0;
11720282
BJ
61 addr->en_owc = -1;
62 addr->en_oba = 0;
941ee7ef 63 addr->en_ostat = EN_IEN|EN_GO;
11720282
BJ
64 DELAY(100000);
65 addr->en_ostat = 0;
11720282
BJ
66 return (1);
67}
68
cdad2eb1 69/*ARGSUSED*/
11720282
BJ
70enattach(ui)
71 struct uba_device *ui;
72{
ae348eea 73
8a13b737
BJ
74COUNT(ENATTACH);
75 eninit(ui->ui_unit);
76 /* net initialization, based on ui->ui_flags?!? */
11720282
BJ
77}
78
ae348eea 79eninit(unit)
11720282 80 int unit;
8a13b737 81{
11720282 82 register struct uba_device *ui;
8a13b737
BJ
83 register struct endevice *addr;
84 register struct en_softc *es;
11720282 85
8a13b737 86COUNT(ENINIT);
11720282 87 if (unit >= NEN || (ui = eninfo[unit]) == 0 || ui->ui_alive == 0) {
8a13b737 88 printf("es%d: not alive\n", unit);
11720282
BJ
89 return;
90 }
8a13b737
BJ
91 es = &en_softc[unit];
92 if (if_ubainit(es->es_ifuba, ui->ui_ubanum,
93 sizeof (struct en_header), btop(ENMTU)) == 0) {
94 printf("es%d: can't initialize\n", unit);
95 return;
11720282 96 }
11720282 97 addr = (struct endevice *)ui->ui_addr;
8a13b737 98 addr->en_istat = addr->en_ostat = 0;
11720282
BJ
99}
100
101enreset(uban)
102 int uban;
103{
104 register int unit;
105 struct uba_device *ui;
106
8a13b737 107COUNT(ENRESET);
11720282
BJ
108 for (unit = 0; unit < NEN; unit++) {
109 ui = eninfo[unit];
110 if (ui == 0 || ui->ui_ubanum != uban || ui->ui_alive == 0)
111 continue;
ae348eea 112 eninit(unit);
8a13b737 113 printf("es%d ", unit);
11720282
BJ
114 }
115}
116
3552a746 117int enlastdel = 25;
8a13b737 118
ae348eea 119enstart(dev)
11720282
BJ
120 dev_t dev;
121{
11720282 122 int unit;
11720282 123 struct uba_device *ui;
8a13b737
BJ
124 register struct endevice *addr;
125 register struct en_softc *es;
126 register struct ifuba *ifu;
127 struct mbuf *m;
128 int dest;
ae348eea 129COUNT(ENSTART);
11720282
BJ
130
131 unit = ENUNIT(dev);
132 ui = eninfo[unit];
8a13b737
BJ
133 es = &en_softc[unit];
134 if (es->es_oactive)
135 goto restart;
136 IF_DEQUEUE(&es->es_if->if_snd, m);
137 if (m == 0) {
138 es->es_oactive = 0;
11720282
BJ
139 return;
140 }
8a13b737
BJ
141 dest = mtod(m, struct en_header *)->en_dhost;
142 es->es_olen = if_wubaput(&es->es_ifuba, m);
143 if (es->es_lastx && es->es_lastx == dest)
144 es->es_delay = enlastdel;
145 else
146 es->es_lastx = dest;
147restart:
148 ifu = es->es_ifuba;
149 UBAPURGE(ifu->ifu_uba, ifu->ifu_w.ifrw_bdp);
11720282 150 addr = (struct endevice *)ui->ui_addr;
8a13b737
BJ
151 addr->en_oba = (int)ifu->ifu_w.ifrw_addr;
152 addr->en_odelay = es->es_delay;
153 addr->en_owc = -((es->es_olen + 1) >> 1);
941ee7ef 154 addr->en_ostat = EN_IEN|EN_GO;
8a13b737 155 es->es_oactive = 1;
11720282
BJ
156}
157
11720282
BJ
158enxint(unit)
159 int unit;
160{
161 register struct endevice *addr;
162 register struct uba_device *ui;
8a13b737 163 register struct en_softc *es;
11720282
BJ
164COUNT(ENXINT);
165
166 ui = eninfo[unit];
8a13b737
BJ
167 es = &en_softc[unit];
168 if (es->es_oactive == 0)
169 return;
11720282 170 addr = (struct endevice *)ui->ui_addr;
8a13b737
BJ
171 es = &en_softc[unit];
172 es->es_oactive = 0;
173 es->es_delay = 0;
174 es->es_mask = ~0;
175 if (addr->en_ostat&EN_OERROR)
176 printf("es%d: output error\n", unit);
177 if (es->es_if->if_snd.ifq_head == 0) {
178 es->es_lastx = 0;
11720282
BJ
179 return;
180 }
8a13b737 181 enstart(unit);
11720282
BJ
182}
183
184encollide(unit)
185 int unit;
186{
8a13b737 187 register struct en_softc *es;
11720282
BJ
188COUNT(ENCOLLIDE);
189
8a13b737
BJ
190 es = &en_softc[unit];
191 es->es_if->if_collisions++;
192 if (es->es_oactive == 0)
11720282 193 return;
8a13b737
BJ
194 if (es->es_mask == 0) {
195 printf("es%d: send error\n", unit);
196 enxint(unit);
11720282 197 } else {
8a13b737
BJ
198 es->es_mask <<= 1;
199 es->es_delay = mfpr(ICR) &~ es->es_mask;
200 enstart(unit);
11720282 201 }
11720282
BJ
202}
203
204enrint(unit)
205 int unit;
206{
8a13b737
BJ
207 struct endevice *addr;
208 register struct en_softc *es;
209 register struct ifuba *ifu;
210 struct en_header *en;
211 struct mbuf *m;
212 struct ifqueue *inq;
11720282 213 register int len;
8a13b737 214 int off;
11720282
BJ
215COUNT(ENRINT);
216
8a13b737 217 addr = (struct endevice *)eninfo[unit]->ui_addr;
941ee7ef 218 if (addr->en_istat&EN_IERROR) {
8a13b737
BJ
219 es->es_if->if_ierrors++;
220 printf("es%d: input error\n", unit);
221 goto setup;
11720282 222 }
8a13b737
BJ
223 ifu = en_softc[unit].es_ifuba;
224 UBAPURGE(ifu->ifu_uba, ifu->ifu_r.ifrw_bdp);
225 en = (struct en_header *)(ifu->ifu_r.ifrw_addr);
226#define endataaddr(en, off, type) ((type)(((caddr_t)((en)+1)+(off))))
227 if (en->en_type >= ENPUP_TRAIL &&
228 en->en_type < ENPUP_TRAIL+ENPUP_NTRAILER) {
229 off = (en->en_type - ENPUP_TRAIL) * 512;
230 en->en_type = *endataaddr(en, off, u_short *);
231 off += 2;
232 } else
233 off = 0;
234 switch (en->en_type) {
235
236#ifdef INET
237 case ENPUP_IPTYPE:
238 len = endataaddr(en, off, struct ip *)->ip_len;
239 setipintr();
240 inq = &ipintrq;
11720282
BJ
241 break;
242#endif
11720282 243
8a13b737
BJ
244 default:
245 printf("en%d: unknow pkt type 0x%x\n", en->en_type);
246 goto setup;
11720282 247 }
8a13b737
BJ
248 if (len == 0)
249 goto setup;
250 m = if_rubaget(&ifu->ifu_r, len, off);
251 IF_ENQUEUE(inq, m);
ae348eea 252setup:
8a13b737
BJ
253 addr->en_iba = es->es_ifuba->ifu_r.ifrw_info;
254 addr->en_iwc = -(sizeof (struct en_header) + ENMTU) >> 1;
941ee7ef 255 addr->en_istat = EN_IEN|EN_GO;
ae348eea 256}
11720282 257
8a13b737
BJ
258/*
259 * Ethernet output routine.
260 * Encapsulate a packet of type family for the local net.
261 */
262enoutput(ifp, m0, pf)
263 struct ifnet *ifp;
264 struct mbuf *m0;
265 int pf;
11720282 266{
8a13b737
BJ
267 int type, dest;
268 register struct mbuf *m;
269 register struct en_header *en;
270 int s;
271
272 switch (pf) {
11720282 273
8a13b737
BJ
274#ifdef INET
275 case PF_INET: {
276 register struct ip *ip = mtod(m0, struct ip *);
277 int off;
278
279 off = ip->ip_len - (ip->ip_hl << 2);
280 if (off && off % 512 == 0 && m0->m_off >= MMINOFF + 2) {
281 type = ENPUP_TRAIL + (off>>9);
282 m0->m_off -= 2;
283 m0->m_len += 2;
284 *mtod(m0, u_short *) = ENPUP_IPTYPE;
285 } else {
286 type = ENPUP_IPTYPE;
287 off = 0;
288 }
289 dest = ip->ip_dst.s_addr >> 24;
290 }
291 break;
292#endif
293
294 default:
295 printf("en%d: can't encapsulate pf%d\n", ifp->if_unit, pf);
296 m_freem(m0);
297 return (0);
298 }
299 if (MMINOFF + sizeof (struct en_header) > m0->m_off) {
300 m = m_get(0);
301 if (m == 0) {
302 m_freem(m0);
303 return (0);
304 }
305 m->m_next = m0;
306 m->m_off = MMINOFF;
307 m->m_len = sizeof (struct en_header);
308 } else {
309 m = m0;
310 m->m_off -= sizeof (struct en_header);
311 m->m_len += sizeof (struct en_header);
11720282 312 }
8a13b737
BJ
313 en = mtod(m, struct en_header *);
314 en->en_shost = ifp->if_host[0];
315 en->en_dhost = dest;
316 en->en_type = type;
317 s = splimp();
318 IF_ENQUEUE(&ifp->if_snd, m);
319 splx(s);
320 if (en_softc[ifp->if_unit].es_oactive == 0)
321 enstart(ifp->if_unit);
11720282 322}