FreeBSD/Linux Kernel Cross Reference
sys/dev/ic/tropic.c
1 /* $NetBSD: tropic.c,v 1.24 2005/02/27 00:27:02 perry Exp $ */
2
3 /*
4 * Ported to NetBSD by Onno van der Linden
5 * Many thanks to Larry Lile for sending me the IBM TROPIC documentation.
6 *
7 * Mach Operating System
8 * Copyright (c) 1991 Carnegie Mellon University
9 * Copyright (c) 1991 IBM Corporation
10 * All Rights Reserved.
11 *
12 * Permission to use, copy, modify and distribute this software and its
13 * documentation is hereby granted, provided that both the copyright
14 * notice and this permission notice appear in all copies of the
15 * software, derivative works or modified versions, and any portions
16 * thereof, and that both notices appear in supporting documentation,
17 * and that the name IBM not be used in advertising or publicity
18 * pertaining to distribution of the software without specific, written
19 * prior permission.
20 *
21 * CARNEGIE MELLON AND IBM ALLOW FREE USE OF THIS SOFTWARE IN ITS "AS IS"
22 * CONDITION. CARNEGIE MELLON AND IBM DISCLAIM ANY LIABILITY OF ANY KIND FOR
23 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
24 *
25 * Carnegie Mellon requests users of this software to return to
26 *
27 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
28 * School of Computer Science
29 * Carnegie Mellon University
30 * Pittsburgh PA 15213-3890
31 *
32 * any improvements or extensions that they make and grant Carnegie Mellon
33 * the rights to redistribute these changes.
34 */
35
36 #include <sys/cdefs.h>
37 __KERNEL_RCSID(0, "$NetBSD: tropic.c,v 1.24 2005/02/27 00:27:02 perry Exp $");
38
39 #include "opt_inet.h"
40 #include "opt_ns.h"
41 #include "bpfilter.h"
42
43 #include <sys/param.h>
44 #include <sys/systm.h>
45 #include <sys/callout.h>
46 #include <sys/kernel.h>
47 #include <sys/proc.h>
48 #include <sys/mbuf.h>
49 #include <sys/buf.h>
50 #include <sys/socket.h>
51 #include <sys/syslog.h>
52 #include <sys/ioctl.h>
53 #include <sys/errno.h>
54 #include <sys/device.h>
55
56 #include <net/if.h>
57 #include <net/if_llc.h>
58 #include <net/if_ether.h>
59 #include <net/if_media.h>
60 #include <net/netisr.h>
61 #include <net/route.h>
62 #include <net/if_token.h>
63
64 #ifdef INET
65 #include <netinet/in.h>
66 #include <netinet/if_inarp.h>
67 #include <netinet/in_systm.h>
68 #include <netinet/ip.h>
69 #include <netinet/in_var.h>
70 #endif
71
72 #ifdef NS
73 #include <netns/ns.h>
74 #include <netns/ns_if.h>
75 #endif
76
77 #if NBPFILTER > 0
78 #include <net/bpf.h>
79 #include <net/bpfdesc.h>
80 #endif
81
82 #include <machine/cpu.h>
83 #include <machine/bus.h>
84
85 #include <dev/ic/tropicreg.h>
86 #include <dev/ic/tropicvar.h>
87
88 static void tr_shutdown(void *);
89 static void tr_reopen(void *);
90
91 void tr_rint(struct tr_softc *);
92 void tr_xint(struct tr_softc *);
93 void tr_oldxint(struct tr_softc *);
94 struct mbuf *tr_get(struct tr_softc *, int, struct ifnet *);
95 void tr_opensap(struct tr_softc *, u_char);
96 int tr_mbcopy(struct tr_softc *, bus_size_t, struct mbuf *);
97 void tr_bcopy(struct tr_softc *, u_char *, int);
98 void tr_start(struct ifnet *);
99 void tr_oldstart(struct ifnet *);
100 void tr_watchdog(struct ifnet *);
101 int tr_mediachange(struct ifnet *);
102 void tr_mediastatus(struct ifnet *, struct ifmediareq *);
103 int tropic_mediachange(struct tr_softc *);
104 void tropic_mediastatus(struct tr_softc *, struct ifmediareq *);
105 void tr_reinit(void *);
106
107 /*
108 * TODO:
109 * clean up tr_intr: more subroutines
110 * IFF_LINK0 == IFM_TOK_SRCRT change to link flag implies media flag change
111 * IFF_LINK1 == IFM_TOK_ALLR change to link flag implies media flag change
112 * XXX Create receive_done queue to kill "ASB not free", but does this ever
113 * XXX happen ?
114 */
115
116 static int media[] = {
117 IFM_TOKEN | IFM_TOK_UTP4,
118 IFM_TOKEN | IFM_TOK_STP4,
119 IFM_TOKEN | IFM_TOK_UTP16,
120 IFM_TOKEN | IFM_TOK_STP16,
121 IFM_TOKEN | IFM_TOK_UTP4,
122 IFM_TOKEN | IFM_TOK_UTP16,
123 IFM_TOKEN | IFM_TOK_STP4,
124 IFM_TOKEN | IFM_TOK_STP16
125 };
126
127 int
128 tropic_mediachange(sc)
129 struct tr_softc *sc;
130 {
131 if (IFM_TYPE(sc->sc_media.ifm_media) != IFM_TOKEN)
132 return EINVAL;
133
134 switch (IFM_SUBTYPE(sc->sc_media.ifm_media)) {
135 case IFM_TOK_STP16:
136 case IFM_TOK_UTP16:
137 if ((sc->sc_init_status & RSP_16) == 0) {
138 tr_stop(sc);
139 if (tr_setspeed(sc, 16))
140 return EINVAL;
141 if (tr_reset(sc))
142 return EINVAL;
143 if (tr_config(sc))
144 return EINVAL;
145 }
146 break;
147 case IFM_TOK_STP4:
148 case IFM_TOK_UTP4:
149 if ((sc->sc_init_status & RSP_16) != 0) {
150 tr_stop(sc);
151 if (tr_setspeed(sc, 4))
152 return EINVAL;
153 if (tr_reset(sc))
154 return EINVAL;
155 if (tr_config(sc))
156 return EINVAL;
157 }
158 break;
159 }
160 /*
161 * XXX Handle Early Token Release !!!!
162 */
163 return 0;
164 }
165
166 void
167 tropic_mediastatus(sc, ifmr)
168 struct tr_softc *sc;
169 struct ifmediareq *ifmr;
170 {
171 struct ifmedia *ifm = &sc->sc_media;
172
173 ifmr->ifm_active = ifm->ifm_cur->ifm_media;
174 }
175
176 int
177 tr_config(sc)
178 struct tr_softc *sc;
179 {
180 if (sc->sc_init_status & FAST_PATH_TRANSMIT) {
181 int i;
182
183 for (i=0; i < SRB_CFP_CMDSIZE; i++)
184 SRB_OUTB(sc, sc->sc_srb, i, 0);
185
186 SRB_OUTB(sc, sc->sc_srb, SRB_CMD, DIR_CONFIG_FAST_PATH_RAM);
187
188 SRB_OUTW(sc, sc->sc_srb, SRB_CFP_RAMSIZE,
189 (16 + (sc->sc_nbuf * FP_BUF_LEN) / 8));
190 SRB_OUTW(sc, sc->sc_srb, SRB_CFP_BUFSIZE, FP_BUF_LEN);
191
192 /* tell adapter: command in SRB */
193 ACA_SETB(sc, ACA_ISRA_o, CMD_IN_SRB);
194
195 for (i = 0; i < 30000; i++) {
196 if (ACA_RDB(sc, ACA_ISRP_o) & SRB_RESP_INT)
197 break;
198 delay(100);
199 }
200
201 if (i == 30000 && sc->sc_srb == ACA_RDW(sc, ACA_WRBR)) {
202 printf("%s: no response for fast path cfg\n",
203 sc->sc_dev.dv_xname);
204 return 1;
205 }
206
207 ACA_RSTB(sc, ACA_ISRP_o, ~(SRB_RESP_INT));
208
209 if ((SRB_INB(sc, sc->sc_srb, SRB_RETCODE) != 0)) {
210 printf("%s: cfg fast path returned: 0x%02x\n",
211 sc->sc_dev.dv_xname,
212 SRB_INB(sc, sc->sc_srb, SRB_RETCODE));
213 return 1;
214 }
215
216 sc->sc_txca = SRB_INW(sc, sc->sc_srb, SRB_CFPRESP_FPXMIT);
217 sc->sc_srb = SRB_INW(sc, sc->sc_srb, SRB_CFPRESP_SRBADDR);
218 }
219 else {
220 if (sc->sc_init_status & RSP_16)
221 sc->sc_maxmtu = sc->sc_dhb16maxsz;
222 else
223 sc->sc_maxmtu = sc->sc_dhb4maxsz;
224 /*
225 * XXX Not completely true because Fast Path Transmit has 514 byte buffers
226 * XXX and TR_MAX_LINK_HDR is only correct when source-routing is used.
227 * XXX depending on wether source routing is used change the calculation
228 * XXX use IFM_TOK_SRCRT (IFF_LINK0)
229 * XXX recompute sc_minbuf !!
230 */
231 sc->sc_maxmtu -= TR_MAX_LINK_HDR;
232 }
233 return 0;
234 }
235
236 int
237 tr_attach(sc)
238 struct tr_softc *sc;
239 {
240 int nmedia, *mediaptr, *defmediaptr;
241 int i, temp;
242 u_int8_t myaddr[ISO88025_ADDR_LEN];
243 struct ifnet *ifp = &sc->sc_ethercom.ec_if;
244
245 if (sc->sc_init_status & FAST_PATH_TRANSMIT) {
246 int nbuf = 0;
247
248 switch (sc->sc_memsize) {
249 case 65536:
250 nbuf = 58;
251 sc->sc_maxmtu = IPMTU_4MBIT_MAX;
252 break;
253 case 32768:
254 nbuf = 29;
255 sc->sc_maxmtu = IPMTU_4MBIT_MAX;
256 break;
257 case 16384:
258 nbuf = 13;
259 sc->sc_maxmtu = IPMTU_4MBIT_MAX;
260 break;
261 case 8192:
262 nbuf = 5;
263 sc->sc_maxmtu = ISO88025_MTU;
264 }
265
266 sc->sc_minbuf = ((sc->sc_maxmtu + 511) / 512) + 1;
267 sc->sc_nbuf = nbuf;
268
269 /*
270 * Create circular queues caching the buffer pointers ?
271 */
272 }
273 else {
274 /*
275 * MAX_MACFRAME_SIZE = DHB_SIZE - 6
276 * IPMTU = MAX_MACFRAME_SIZE - (14 + 18 + 8)
277 * (14 = header, 18 = sroute, 8 = llcsnap)
278 */
279
280 switch (sc->sc_memsize) {
281 case 8192:
282 sc->sc_dhb4maxsz = 2048;
283 sc->sc_dhb16maxsz = 2048;
284 break;
285 case 16384:
286 sc->sc_dhb4maxsz = 4096;
287 sc->sc_dhb16maxsz = 4096;
288 break;
289 case 32768:
290 sc->sc_dhb4maxsz = 4464;
291 sc->sc_dhb16maxsz = 8192;
292 break;
293 case 65536:
294 sc->sc_dhb4maxsz = 4464;
295 sc->sc_dhb16maxsz = 8192;
296 break;
297 }
298 switch (MM_INB(sc, TR_DHB4_OFFSET)) {
299 case 0xF:
300 if (sc->sc_dhb4maxsz > 2048)
301 sc->sc_dhb4maxsz = 2048;
302 break;
303 case 0xE:
304 if (sc->sc_dhb4maxsz > 4096)
305 sc->sc_dhb4maxsz = 4096;
306 break;
307 case 0xD:
308 if (sc->sc_dhb4maxsz > 4464)
309 sc->sc_dhb4maxsz = 4464;
310 break;
311 }
312
313 switch (MM_INB(sc, TR_DHB16_OFFSET)) {
314 case 0xF:
315 if (sc->sc_dhb16maxsz > 2048)
316 sc->sc_dhb16maxsz = 2048;
317 break;
318 case 0xE:
319 if (sc->sc_dhb16maxsz > 4096)
320 sc->sc_dhb16maxsz = 4096;
321 break;
322 case 0xD:
323 if (sc->sc_dhb16maxsz > 8192)
324 sc->sc_dhb16maxsz = 8192;
325 break;
326 case 0xC:
327 if (sc->sc_dhb16maxsz > 8192)
328 sc->sc_dhb16maxsz = 8192;
329 break;
330 case 0xB:
331 if (sc->sc_dhb16maxsz > 8192)
332 sc->sc_dhb16maxsz = 8192;
333 break;
334 }
335 }
336
337 if (tr_config(sc))
338 return 1;
339
340 /*
341 * init network-visible interface
342 */
343 strcpy(ifp->if_xname, sc->sc_dev.dv_xname);
344 ifp->if_softc = sc;
345 ifp->if_ioctl = tr_ioctl;
346 if (sc->sc_init_status & FAST_PATH_TRANSMIT)
347 ifp->if_start = tr_start;
348 else
349 ifp->if_start = tr_oldstart;
350 ifp->if_flags = IFF_BROADCAST | IFF_NOTRAILERS;
351 ifp->if_watchdog = tr_watchdog;
352 IFQ_SET_READY(&ifp->if_snd);
353
354 switch (MM_INB(sc, TR_MEDIAS_OFFSET)) {
355 case 0xF:
356 nmedia = 1;
357 mediaptr = &media[6];
358 break;
359 case 0xE:
360 nmedia = 2;
361 mediaptr = &media[0];
362 break;
363 case 0xD:
364 nmedia = 1;
365 mediaptr = &media[4];
366 break;
367 default:
368 nmedia = 0;
369 mediaptr = NULL;
370 }
371
372 switch (MM_INB(sc, TR_RATES_OFFSET)) {
373 case 0xF:
374 /* 4 Mbps */
375 break;
376 case 0xE:
377 /* 16 Mbps */
378 if (mediaptr)
379 mediaptr += nmedia;
380 break;
381 case 0xD:
382 /* 4/16 Mbps */
383 nmedia *= 2;
384 break;
385 }
386
387 switch (MM_INB(sc, TR_MEDIA_OFFSET)) {
388 case 0xF:
389 /* STP */
390 defmediaptr = &media[6];
391 break;
392 case 0xE:
393 /* UTP */
394 defmediaptr = &media[4];
395 break;
396 case 0xD:
397 /* STP and UTP == a single shielded RJ45 which supports both */
398 /* XXX additional types in net/if_media.h ?? */
399 defmediaptr = &media[4];
400 break;
401 default:
402 defmediaptr = NULL;
403 }
404
405 if (defmediaptr && (sc->sc_init_status & RSP_16))
406 ++defmediaptr;
407
408 if (sc->sc_mediachange == NULL && sc->sc_mediastatus == NULL) {
409 switch (MM_INB(sc, TR_TYP_OFFSET)) {
410 case 0x0D:
411 case 0x0C:
412 sc->sc_mediachange = tropic_mediachange;
413 sc->sc_mediastatus = tropic_mediastatus;
414 }
415 }
416
417 ifmedia_init(&sc->sc_media, 0, tr_mediachange, tr_mediastatus);
418 if (mediaptr != NULL) {
419 for (i = 0; i < nmedia; i++)
420 ifmedia_add(&sc->sc_media, mediaptr[i], 0, NULL);
421 if (defmediaptr)
422 ifmedia_set(&sc->sc_media, *defmediaptr);
423 else
424 ifmedia_set(&sc->sc_media, 0);
425 }
426 else {
427 ifmedia_add(&sc->sc_media, IFM_TOKEN | IFM_MANUAL, 0, NULL);
428 ifmedia_set(&sc->sc_media, IFM_TOKEN | IFM_MANUAL);
429 }
430
431 if_attach(ifp);
432
433 for (i = 0, temp = 0; i < ISO88025_ADDR_LEN; i++, temp += 4) {
434 myaddr[i] = (MM_INB(sc, (TR_MAC_OFFSET + temp)) & 0xf) << 4;
435 myaddr[i] |= MM_INB(sc, (TR_MAC_OFFSET + temp + 2)) & 0xf;
436 }
437
438 token_ifattach(ifp, myaddr);
439
440 printf("%s: address %s ring speed %d Mbps\n", sc->sc_dev.dv_xname,
441 token_sprintf(myaddr), (sc->sc_init_status & RSP_16) ? 16 : 4);
442
443 callout_init(&sc->sc_init_callout);
444 callout_init(&sc->sc_reinit_callout);
445
446 sc->sc_sdhook = shutdownhook_establish(tr_shutdown, sc);
447 return 0;
448 }
449
450 int
451 tr_setspeed(sc, speed)
452 struct tr_softc *sc;
453 u_int8_t speed;
454 {
455 SRB_OUTB(sc, sc->sc_srb, SRB_CMD, DIR_SET_DEFAULT_RING_SPEED);
456 SRB_OUTB(sc, sc->sc_srb, CMD_RETCODE, 0xfe);
457 SRB_OUTB(sc, sc->sc_srb, SRB_SET_DEFRSP, speed);
458 /* Tell adapter: command in SRB. */
459 ACA_SETB(sc, ACA_ISRA_o, CMD_IN_SRB);
460
461 /* Wait for it to complete. */
462 tr_sleep(sc);
463
464 if ((SRB_INB(sc, sc->sc_srb, SRB_RETCODE) != 0)) {
465 printf("%s: set default ringspeed returned: 0x%02x\n",
466 sc->sc_dev.dv_xname, SRB_INB(sc, sc->sc_srb, SRB_RETCODE));
467 return 1;
468 }
469 return 0;
470 }
471
472 int
473 tr_mediachange(ifp)
474 struct ifnet *ifp;
475 {
476 struct tr_softc *sc = ifp->if_softc;
477
478 if (sc->sc_mediachange)
479 return ((*sc->sc_mediachange)(sc));
480 return EINVAL;
481 }
482
483 void
484 tr_mediastatus(ifp, ifmr)
485 struct ifnet *ifp;
486 struct ifmediareq *ifmr;
487 {
488 struct tr_softc *sc = ifp->if_softc;
489
490 /* set LINK0 and/or LINK1 */
491 if (sc->sc_mediastatus)
492 (*sc->sc_mediastatus)(sc, ifmr);
493 }
494
495 int
496 tr_reset(sc)
497 struct tr_softc *sc;
498 {
499 int i;
500
501 sc->sc_srb = 0;
502
503 /*
504 * Reset the card.
505 */
506 /* latch on an unconditional adapter reset */
507 bus_space_write_1(sc->sc_piot, sc->sc_pioh, TR_RESET, 0);
508 delay(50000); /* delay 50ms */
509 /*
510 * XXX set paging if we have the right type of card
511 */
512 /* turn off adapter reset */
513 bus_space_write_1(sc->sc_piot, sc->sc_pioh, TR_RELEASE, 0);
514
515 /* Enable interrupts. */
516
517 ACA_SETB(sc, ACA_ISRP_e, INT_ENABLE);
518
519 /* Wait for an answer from the adapter. */
520
521 for (i = 0; i < 35000; i++) {
522 if (ACA_RDB(sc, ACA_ISRP_o) & SRB_RESP_INT)
523 break;
524 delay(100);
525 }
526
527 if (i == 35000 && sc->sc_srb == 0) {
528 printf("%s: no response from adapter after reset\n",
529 sc->sc_dev.dv_xname);
530 return 1;
531 }
532
533 ACA_RSTB(sc, ACA_ISRP_o, ~(SRB_RESP_INT));
534
535 ACA_OUTB(sc, ACA_RRR_e, (sc->sc_maddr >> 12));
536 sc->sc_srb = ACA_RDW(sc, ACA_WRBR);
537 if (SRB_INB(sc, sc->sc_srb, SRB_CMD) != 0x80) {
538 printf("%s: initialization incomplete, status: 0x%02x\n",
539 sc->sc_dev.dv_xname, SRB_INB(sc, sc->sc_srb, SRB_CMD));
540 return 1;
541 }
542 if (SRB_INB(sc, sc->sc_srb, SRB_INIT_BUC) != 0) {
543 printf("%s: Bring Up Code %02x\n", sc->sc_dev.dv_xname,
544 SRB_INB(sc, sc->sc_srb, SRB_INIT_BUC));
545 return 1;
546 }
547
548 sc->sc_init_status = SRB_INB(sc, sc->sc_srb, SRB_INIT_STATUS);
549
550 sc->sc_xmit_head = sc->sc_xmit_tail = 0;
551
552 /* XXX should depend on sc_resvdmem. */
553 if (MM_INB(sc, TR_RAM_OFFSET) == 0xB && sc->sc_memsize == 65536)
554 for (i = 0; i < 512; i++)
555 SR_OUTB(sc, 0xfe00 + i, 0);
556 return 0;
557 }
558
559 /*
560 * tr_stop - stop interface (issue a DIR.CLOSE.ADAPTER command)
561 */
562 void
563 tr_stop(sc)
564 struct tr_softc *sc;
565 {
566 struct ifnet *ifp = &sc->sc_ethercom.ec_if;
567
568 if ((ifp->if_flags & IFF_RUNNING) != 0) {
569 /*
570 * transmitter cannot be used from now on
571 */
572 ifp->if_flags |= IFF_OACTIVE;
573
574 /* Close command. */
575 SRB_OUTB(sc, sc->sc_srb, SRB_CMD, DIR_CLOSE);
576 /* Tell adapter: command in SRB. */
577 ACA_SETB(sc, ACA_ISRA_o, CMD_IN_SRB);
578
579 /* Wait for it to complete. */
580 tr_sleep(sc);
581 sc->sc_srb = ACA_RDW(sc, ACA_WRBR);
582 }
583 }
584
585 static void
586 tr_shutdown(arg)
587 void *arg;
588 {
589 struct tr_softc *sc = arg;
590
591 tr_stop(sc);
592 }
593
594 void
595 tr_reinit(arg)
596 void *arg;
597 {
598 struct tr_softc *sc = arg;
599 int s;
600
601 s = splnet();
602 if (tr_reset(sc) == 0) {
603 if (tr_config(sc) == 0)
604 tr_init(arg);
605 }
606 splx(s);
607 }
608
609 static void
610 tr_reopen(arg)
611 void *arg;
612 {
613 int s;
614
615 s = splnet();
616 tr_init(arg);
617 splx(s);
618 }
619
620 /*
621 * tr_init - initialize network interface, open adapter for packet
622 * - reception and start any pending output
623 * - must be called at splnet
624 */
625 void
626 tr_init(arg)
627 void *arg;
628 {
629 struct tr_softc *sc = arg;
630 struct ifnet *ifp = &sc->sc_ethercom.ec_if;
631 bus_size_t open_srb;
632 int num_dhb, resvdmem, availmem, dhbsize;
633
634 if ((ifp->if_flags & IFF_RUNNING) != 0)
635 return;
636
637 ifp->if_flags &= ~IFF_OACTIVE;
638 sc->sc_xmit_head = sc->sc_xmit_tail = 0; /* XXX tr_reset() */
639
640 open_srb = sc->sc_srb;
641
642 /* Zero SRB. */
643 bus_space_set_region_1(sc->sc_memt, sc->sc_sramh,
644 open_srb, 0, SRB_OPEN_CMDSIZE);
645
646 /* Open command. */
647 SRB_OUTB(sc, open_srb, SRB_CMD, DIR_OPEN_ADAPTER);
648 /*
649 * XXX handle IFM_TOK_ETR !!!!
650 */
651 /* Set open parameters in SRB. */
652 SRB_OUTW(sc, open_srb, SRB_OPEN_OPTIONS, OPEN_PASS_BCON_MAC);
653
654 num_dhb = 1;
655
656 if ((sc->sc_init_status & FAST_PATH_TRANSMIT) == 0) {
657 availmem = sc->sc_memsize;
658 resvdmem = RESVDMEM_SIZE + sc->sc_memreserved;
659
660 /* allow MAX of two SAPS */
661 SRB_OUTB(sc, open_srb, SRB_OPEN_DLCMAXSAP, 2);
662 resvdmem += 2 * SAPCB_SIZE;
663
664 /* allow MAX of 4 stations */
665 SRB_OUTB(sc, open_srb, SRB_OPEN_DLCMAXSTA, 4);
666 resvdmem += 4 * LSCB_SIZE;
667
668 if (sc->sc_init_status & RSP_16) {
669 dhbsize = sc->sc_dhb16maxsz;
670 }
671 else {
672 dhbsize = sc->sc_dhb4maxsz;
673 }
674 #if 0 /* XXXchb unneeded? */
675 if (dhbsize > 2048)
676 num_dhb = 2;
677 #endif
678 SRB_OUTW(sc, open_srb, SRB_OPEN_DHBLEN, dhbsize);
679 sc->sc_nbuf = (dhbsize + 511) / 512;
680 /*
681 * Try to leave room for two fullsized packets when
682 * requesting DHBs.
683 */
684 availmem -= resvdmem;
685 num_dhb = (availmem / dhbsize) - 2;
686 if (num_dhb > 2)
687 num_dhb = 2; /* firmware can't cope with more DHBs */
688 if (num_dhb < 1)
689 num_dhb = 1; /* we need at least one */
690 }
691 else
692 SRB_OUTW(sc, open_srb, SRB_OPEN_DHBLEN, DHB_LENGTH);
693
694 SRB_OUTB(sc, open_srb, SRB_OPEN_NUMDHB, num_dhb);
695 SRB_OUTW(sc, open_srb, SRB_OPEN_RCVBUFLEN, RCV_BUF_LEN);
696 SRB_OUTW(sc, open_srb, SRB_OPEN_NUMRCVBUF, sc->sc_nbuf);
697
698 /* Tell adapter: command in SRB. */
699 ACA_SETB(sc, ACA_ISRA_o, CMD_IN_SRB);
700
701 }
702
703 /*
704 * tr_oldstart - Present transmit request to adapter
705 */
706 void
707 tr_oldstart(ifp)
708 struct ifnet *ifp;
709 {
710 struct tr_softc *sc = ifp->if_softc;
711 bus_size_t srb = sc->sc_srb;
712
713 if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING)
714 return;
715
716 ifp->if_flags |= IFF_OACTIVE;
717
718 /* Load SRB to request transmit. */
719 SRB_OUTB(sc, srb, SRB_CMD, XMIT_UI_FRM);
720 SRB_OUTW(sc, srb, XMIT_STATIONID, sc->exsap_station);
721 ACA_SETB(sc, ACA_ISRA_o, CMD_IN_SRB);
722 }
723
724 void
725 tr_start(ifp)
726 struct ifnet *ifp;
727 {
728 struct tr_softc *sc = ifp->if_softc;
729 bus_size_t first_txbuf, txbuf;
730 struct mbuf *m0, *m;
731 int size, bufspace;
732 bus_size_t framedata;
733
734 if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING)
735 return;
736
737
738 next:
739 if (sc->sc_xmit_buffers < sc->sc_minbuf)
740 return;
741
742 /* if data in queue, copy mbuf chain to fast path buffers */
743 IFQ_DEQUEUE(&ifp->if_snd, m0);
744
745 if (m0 == 0)
746 return;
747 #if NBPFILTER > 0
748 if (ifp->if_bpf)
749 bpf_mtap(ifp->if_bpf, m0);
750 #endif
751 first_txbuf = txbuf = TXCA_INW(sc, TXCA_FREE_QUEUE_HEAD) - XMIT_NEXTBUF;
752 framedata = txbuf + XMIT_FP_DATA;
753 size = 0;
754 bufspace = FP_BUF_LEN - XMIT_FP_DATA;
755 for (m = m0; m; m = m->m_next) {
756 int len = m->m_len;
757 char *ptr = mtod(m, char *);
758
759 while (len >= bufspace) {
760 --sc->sc_xmit_buffers;
761 bus_space_write_region_1(sc->sc_memt, sc->sc_sramh,
762 framedata, ptr, bufspace);
763 size += bufspace;
764 ptr += bufspace;
765 len -= bufspace;
766 TXB_OUTW(sc, txbuf, XMIT_BUFLEN,
767 (FP_BUF_LEN - XMIT_FP_DATA));
768 txbuf = TXB_INW(sc, txbuf, XMIT_NEXTBUF) - XMIT_NEXTBUF;
769 framedata = txbuf + XMIT_FP_DATA;
770 bufspace = FP_BUF_LEN - XMIT_FP_DATA;
771 }
772 if (len > 0) {
773 bus_space_write_region_1(sc->sc_memt, sc->sc_sramh,
774 framedata, ptr, len);
775 size += len;
776 bufspace -= len;
777 framedata += len;
778 }
779 }
780 if (size % (FP_BUF_LEN - XMIT_FP_DATA)) {
781 --sc->sc_xmit_buffers;
782 TXB_OUTW(sc, txbuf, XMIT_BUFLEN,
783 (FP_BUF_LEN - XMIT_FP_DATA - bufspace));
784 }
785
786 m_freem(m0); /* free mbuf chain */
787
788 TXB_OUTB(sc, first_txbuf, XMIT_RETCODE, 0xfe);
789 TXB_OUTW(sc, first_txbuf, XMIT_FRAMELEN, size);
790 TXB_OUTW(sc, first_txbuf, XMIT_LASTBUF, (txbuf + XMIT_NEXTBUF));
791 TXB_OUTB(sc, first_txbuf, XMIT_CMD, XMIT_DIR_FRAME);
792 TXB_OUTW(sc, first_txbuf, XMIT_STATIONID, 0);
793 TXB_OUTB(sc, first_txbuf, XMIT_CMDCORR, sc->sc_xmit_correlator);
794 sc->sc_xmit_correlator = (sc->sc_xmit_correlator + 1) & 0x7f;
795
796 /*
797 * To prevent race conditions on 8-bit cards when reading or writing
798 * 16-bit values. See page 4-12 of the IBM manual.
799 */
800 TXCA_OUTW(sc, TXCA_FREE_QUEUE_HEAD, 1);
801 TXCA_OUTW(sc, TXCA_FREE_QUEUE_HEAD, TXB_INW(sc, txbuf, XMIT_NEXTBUF));
802
803 ACA_SETB(sc, ACA_ISRA_o, XMIT_REQ);
804
805 ifp->if_flags |= IFF_OACTIVE;
806 ifp->if_opackets++;
807 #if 1
808 /* XXX do while construction */
809 goto next;
810 #endif
811 }
812
813
814 /*
815 * tr_intr - interrupt handler. Find the cause of the interrupt and
816 * service it.
817 */
818 int
819 tr_intr(arg)
820 void *arg;
821 {
822 struct tr_softc *sc = arg;
823 struct ifnet *ifp = &sc->sc_ethercom.ec_if;
824 u_char status; /* holds status from adapter status register */
825 u_char command; /* holds command from status or request block */
826 u_char retcode; /* holds return value from status or request block */
827 int rc = 0; /* 0 = unclaimed interrupt, 1 = interrupt claimed */
828
829 status = ACA_RDB(sc, ACA_ISRP_o);
830 while (status != 0) {
831
832 /* Is this interrupt caused by an adapter check? */
833 if (status & ADAP_CHK_INT) {
834 printf("%s: adapter check 0x%04x\n",
835 sc->sc_dev.dv_xname,
836 (unsigned int)ntohs(ACA_RDW(sc, ACA_WWCR)));
837
838 /* Clear this interrupt bit */
839 ACA_RSTB(sc, ACA_ISRP_o, ~(ADAP_CHK_INT));
840
841 rc = 1; /* Claim interrupt. */
842 break; /* Terminate loop. */
843 }
844 else if (status & XMIT_COMPLETE) {
845 ACA_RSTB(sc, ACA_ISRP_o, ~(XMIT_COMPLETE));
846 tr_xint(sc);
847 rc = 1;
848 }
849
850 /*
851 * Process SRB_RESP_INT, ASB_FREE_INT, ARB_CMD_INT
852 * & SSB_RESP_INT in that order, ISRP-L Hi to Lo
853 */
854 else if (status & SRB_RESP_INT) { /* Adapter response in SRB? */
855 bus_size_t sap_srb;
856 bus_size_t srb;
857 #ifdef TROPICDEBUG
858 bus_size_t log_srb;
859 #endif
860 if (sc->sc_srb == 0)
861 sc->sc_srb = ACA_RDW(sc, ACA_WRBR);
862 srb = sc->sc_srb; /* pointer to SRB */
863 retcode = SRB_INB(sc, srb, SRB_RETCODE);
864 command = SRB_INB(sc, srb, SRB_CMD);
865 switch (command) {
866 case 0x80: /* 0x80 == initialization complete */
867 case DIR_CONFIG_FAST_PATH_RAM:
868 break;
869 case XMIT_DIR_FRAME: /* Response to xmit request */
870 case XMIT_UI_FRM: /* Response to xmit request */
871 /* Response not valid? */
872 if (retcode != 0xff)
873 printf("%s: error on xmit request = "
874 "0x%x\n", sc->sc_dev.dv_xname,
875 retcode);
876 break;
877
878 case DIR_OPEN_ADAPTER: /* open-adapter-cmd response */
879 /* Open successful? */
880 if (retcode == 0) {
881 ifp->if_flags |= IFF_UP | IFF_RUNNING;
882 /* Save new ACA ctrl block addresses */
883 sc->sc_ssb = SRB_INW(sc, srb,
884 SRB_OPENRESP_SSBADDR);
885 sc->sc_arb = SRB_INW(sc, srb,
886 SRB_OPENRESP_ARBADDR);
887 sc->sc_srb = SRB_INW(sc, srb,
888 SRB_OPENRESP_SRBADDR);
889 sc->sc_asb = SRB_INW(sc, srb,
890 SRB_OPENRESP_ASBADDR);
891
892 /*
893 * XXX, what about LLC_{X25,ISO}_LSAP ?
894 * open two more saps .....
895 */
896 if (sc->sc_init_status &
897 FAST_PATH_TRANSMIT) {
898 sc->sc_xmit_buffers =
899 TXCA_INW(sc,
900 TXCA_BUFFER_COUNT);
901 sc->sc_nbuf =
902 sc->sc_xmit_buffers;
903 #ifdef TROPICDEBUG
904 printf("%s: %d buffers\n",
905 sc->sc_dev.dv_xname,
906 sc->sc_xmit_buffers);
907 #endif
908 sc->sc_xmit_correlator = 0;
909 wakeup(&sc->tr_sleepevent);
910 }
911 else
912 tr_opensap(sc, LLC_SNAP_LSAP);
913 }
914 else {
915 printf("%s: open error = 0x%x\n",
916 sc->sc_dev.dv_xname,
917 SRB_INB(sc, srb, SRB_RETCODE));
918 ifp->if_flags &= ~IFF_RUNNING;
919 ifp->if_flags &= ~IFF_UP;
920 /*
921 * XXX untimeout depending on the error, timeout in other cases
922 * XXX error 0x24 && autospeed mode: open again !!!!
923 */
924 callout_reset(&sc->sc_init_callout,
925 hz * 30, tr_reopen, sc);
926 }
927 break;
928
929 case DIR_CLOSE: /* Response to close adapter command */
930 /* Close not successful? */
931 if (retcode != 0)
932 printf("%s: close error = 0x%x\n",
933 sc->sc_dev.dv_xname, retcode);
934 else {
935 ifp->if_flags &= ~IFF_RUNNING;
936 ifp->if_flags &= ~IFF_UP;
937 ifp->if_flags &= ~IFF_OACTIVE;
938 wakeup(&sc->tr_sleepevent);
939 }
940 break;
941 case DIR_SET_DEFAULT_RING_SPEED:
942 wakeup(&sc->tr_sleepevent);
943 break;
944
945 case DLC_OPEN_SAP: /* Response to open sap cmd */
946 sap_srb = sc->sc_srb;
947 if (SRB_INB(sc, sap_srb, SRB_OPNSAP_SAPVALUE)
948 == LLC_SNAP_LSAP)
949 sc->exsap_station =
950 SRB_INW(sc, sap_srb,
951 SRB_OPNSAP_STATIONID);
952 printf("%s: Token Ring opened\n",
953 sc->sc_dev.dv_xname);
954 wakeup(&sc->tr_sleepevent);
955 break;
956 /* XXX DLC_CLOSE_SAP not needed ? */
957 case DLC_CLOSE_SAP: /* Response to close sap cmd */
958 break;
959 case DIR_READ_LOG: /* Response to read log */
960 /* Cmd not successful? */
961 if (retcode != 0)
962 printf("%s: read error log cmd err = "
963 "0x%x\n", sc->sc_dev.dv_xname,
964 retcode);
965 #ifdef TROPICDEBUG
966 log_srb = sc->sc_srb;
967 printf("%s: ERROR LOG:\n",sc->sc_dev.dv_xname);
968 printf("%s: Line=%d, Internal=%d, Burst=%d\n",
969 sc->sc_dev.dv_xname,
970 (SRB_INB(sc, log_srb, SRB_LOG_LINEERRS)),
971 (SRB_INB(sc, log_srb, SRB_LOG_INTERRS)),
972 (SRB_INB(sc, log_srb, SRB_LOG_BRSTERRS)));
973 printf("%s: A/C=%d, Abort=%d, Lost frames=%d\n",
974 sc->sc_dev.dv_xname,
975 (SRB_INB(sc, log_srb, SRB_LOG_ACERRS)),
976 (SRB_INB(sc, log_srb, SRB_LOG_ABRTERRS)),
977 (SRB_INB(sc, log_srb, SRB_LOG_LOSTFRMS)));
978 printf("%s: Receive congestion=%d, Frame copied=%d, Frequency=%d\n",
979 sc->sc_dev.dv_xname,
980 (SRB_INB(sc, log_srb, SRB_LOG_RCVCONG)),
981 (SRB_INB(sc, log_srb, SRB_LOG_FCPYERRS)),
982 (SRB_INB(sc, log_srb, SRB_LOG_FREQERRS)));
983 printf("%s: Token=%d\n",sc->sc_dev.dv_xname,
984 (SRB_INB(sc, log_srb, SRB_LOG_TOKENERRS)));
985 #endif /* TROPICDEBUG */
986 ifp->if_flags &= ~IFF_OACTIVE;
987 break;
988 default:
989 printf("%s: bad SRB command encountered 0x%x\n",
990 sc->sc_dev.dv_xname, command);
991 break;
992 }
993 /* clear the SRB-response interrupt bit */
994 ACA_RSTB(sc, ACA_ISRP_o, ~(SRB_RESP_INT));
995
996 }
997
998 else if (status & ASB_FREE_INT) { /* Is ASB Free? */
999 bus_size_t asb = sc->sc_asb;
1000
1001 /*
1002 * Remove message from asb queue, first element in
1003 * structure is the command. command == REC_DATA?
1004 * size = 8 : size = 10
1005 * reply in isra_l with (RESP_IN_ASB | ASB_FREE)
1006 */
1007 retcode = ASB_INB(sc, asb, CMD_RETCODE);
1008 command = ASB_INB(sc, asb, CMD_CMD);
1009 switch (command) {
1010 case REC_DATA: /* Receive */
1011 /* Response not valid? */
1012 if (retcode != 0xff)
1013 printf("%s: ASB bad receive response = 0x%x\n",
1014 sc->sc_dev.dv_xname, retcode);
1015 break;
1016 case XMIT_DIR_FRAME: /* Transmit */
1017 case XMIT_UI_FRM: /* Transmit */
1018 /* Response not valid? */
1019 if (retcode != 0xff)
1020 printf("%s: ASB response err on xmit = 0x%x\n",
1021 sc->sc_dev.dv_xname, retcode);
1022 break;
1023 default:
1024 printf("%s: invalid command in ASB = 0x%x\n",
1025 sc->sc_dev.dv_xname, command);
1026 break;
1027 }
1028 /* Clear this interrupt bit */
1029 ACA_RSTB(sc, ACA_ISRP_o, ~(ASB_FREE_INT));
1030 }
1031 else if (status & ARB_CMD_INT) { /* Command for PC to handle? */
1032 bus_size_t arb = sc->sc_arb;
1033
1034 command = ARB_INB(sc, arb, ARB_CMD);
1035 switch (command) {
1036 case DLC_STATUS: /* DLC status change */
1037 printf("%s: ARB new DLC status = 0x%x\n",
1038 sc->sc_dev.dv_xname,
1039 ARB_INW(sc, arb, ARB_DLCSTAT_STATUS));
1040 break;
1041 case REC_DATA: /* Adapter has data for PC */
1042 /* Call receive interrupt handler */
1043 tr_rint(sc);
1044 break;
1045
1046 case RING_STAT_CHANGE: /* Ring status change */
1047 if (ARB_INW(sc, arb, ARB_RINGSTATUS) &
1048 (SIGNAL_LOSS + LOBE_FAULT)){
1049 printf("%s: signal loss / lobe fault\n",
1050 sc->sc_dev.dv_xname);
1051 ifp->if_flags &= ~IFF_RUNNING;
1052 ifp->if_flags &= ~IFF_UP;
1053 IFQ_PURGE(&ifp->if_snd);
1054 callout_reset(&sc->sc_reinit_callout,
1055 hz * 30, tr_reinit, sc);
1056 }
1057 else {
1058 #ifdef TROPICDEBUG
1059 if (ARB_INW(sc, arb, ARB_RINGSTATUS) &
1060 ~(SOFT_ERR))
1061 printf("%s: ARB new ring status"
1062 " = 0x%x\n",
1063 sc->sc_dev.dv_xname,
1064 ARB_INW(sc, arb,
1065 ARB_RINGSTATUS));
1066 #endif /* TROPICDEBUG */
1067 }
1068 if (ARB_INW(sc, arb, ARB_RINGSTATUS) &
1069 LOG_OFLOW){
1070 /*
1071 * XXX CMD_IN_SRB, handle with SRB_FREE_INT ?
1072 */
1073 ifp->if_flags |= IFF_OACTIVE;
1074 SRB_OUTB(sc, sc->sc_srb, SRB_CMD,
1075 DIR_READ_LOG);
1076 /* Read & reset err log cmnd in SRB. */
1077 ACA_SETB(sc, ACA_ISRA_o, CMD_IN_SRB);
1078 }
1079 break;
1080
1081 case XMIT_DATA_REQ: /* Adapter wants data to transmit */
1082 /* Call transmit interrupt handler */
1083 tr_oldxint(sc);
1084 break;
1085
1086 default:
1087 printf("%s: invalid command in ARB = 0x%x\n",
1088 sc->sc_dev.dv_xname, command);
1089 break;
1090 }
1091
1092 /* Clear this interrupt bit */
1093 ACA_RSTB(sc, ACA_ISRP_o, ~(ARB_CMD_INT));
1094
1095 /* Tell adapter that ARB is now free */
1096 ACA_SETB(sc, ACA_ISRA_o, ARB_FREE);
1097 }
1098
1099
1100 else if (status & SSB_RESP_INT) { /* SSB resp. to SRB cmd? */
1101 bus_size_t ssb = sc->sc_ssb;
1102
1103 retcode = SSB_INB(sc, ssb, SSB_RETCODE);
1104 command = SSB_INB(sc, ssb, SSB_CMD);
1105 switch (command) {
1106 case XMIT_UI_FRM:
1107 case XMIT_DIR_FRAME: /* SSB response to SRB xmit cmd */
1108 /* collect status on last packet */
1109 if (retcode != 0) {
1110 printf("%s: xmit return code = 0x%x\n",
1111 sc->sc_dev.dv_xname, retcode);
1112 /* XXXchb */
1113 if (retcode == 0x22) {
1114 printf("%s: FS = 0x%2x\n",
1115 sc->sc_dev.dv_xname,
1116 SSB_INB(sc, ssb,
1117 SSB_XMITERR));
1118 }
1119 ifp->if_oerrors++;
1120 }
1121 else
1122 ifp->if_opackets++;
1123
1124 ifp->if_flags &= ~IFF_OACTIVE;
1125 /*
1126 * XXX should this be done here ?
1127 */
1128 /* if data on send queue */
1129 if (IFQ_IS_EMPTY(&ifp->if_snd) == 0)
1130 tr_oldstart(ifp);
1131 break;
1132
1133 case XMIT_XID_CMD:
1134 printf("tr_int: xmit XID return code = 0x%x\n",
1135 retcode);
1136 break;
1137 default:
1138 printf("%s: SSB error, invalid command =%x\n",
1139 sc->sc_dev.dv_xname, command);
1140 }
1141 /* clear this interrupt bit */
1142 ACA_RSTB(sc, ACA_ISRP_o, ~(SSB_RESP_INT));
1143
1144 /* tell adapter that SSB is available */
1145 ACA_SETB(sc, ACA_ISRA_o, SSB_FREE);
1146 }
1147 rc = 1; /* Claim responsibility for interrupt */
1148 status = ACA_RDB(sc, ACA_ISRP_o);
1149 }
1150 /* Is this interrupt caused by an adapter error or access violation? */
1151 if (ACA_RDB(sc, ACA_ISRP_e) & (TCR_INT | ERR_INT | ACCESS_INT)) {
1152 printf("%s: adapter error, ISRP_e = 0x%x\n",
1153 sc->sc_dev.dv_xname, ACA_RDB(sc, ACA_ISRP_e));
1154
1155 /* Clear these interrupt bits */
1156 ACA_RSTB(sc, ACA_ISRP_e, ~(TCR_INT | ERR_INT | ACCESS_INT));
1157 rc = 1; /* Claim responsibility for interrupt */
1158
1159 }
1160
1161 /* Clear IRQ latch in order to reenable interrupts. */
1162 bus_space_write_1(sc->sc_piot, sc->sc_pioh, TR_CLEARINT, 0);
1163 return (rc);
1164 }
1165
1166 #ifdef notyet
1167 int asb_reply_rcv()
1168 {
1169 }
1170
1171 int asb_reply_xmit()
1172 {
1173 }
1174
1175 int asb_response(bus_size_t asb, size_t len)
1176 {
1177 if (empty_queue) {
1178 answer with RESP_IN_ASB | ASB_FREE
1179 }
1180 else {
1181 put asb in queue
1182 }
1183 }
1184 #endif
1185
1186
1187 /*
1188 * U-B receive interrupt.
1189 *
1190 * in the original version, this routine had three tasks:
1191 *
1192 * 1. move the data into the receive buffer and set up various pointers
1193 * in the tr_softc struct
1194 * 2. switch on the type field for ip and arp, dropping all else
1195 * 3. resetting the adaptor status block info (asb) and updating the
1196 * tr_softc struct
1197 * determine lan message type, pull packet off interface and
1198 * pass to an appropriate higher-level routine
1199 *
1200 */
1201 void
1202 tr_rint(sc)
1203 struct tr_softc *sc;
1204 {
1205 bus_size_t arb = sc->sc_arb;
1206 bus_size_t asb = sc->sc_asb;
1207 struct rbcb *rbc = &sc->rbc;
1208 struct mbuf *m;
1209 struct ifnet *ifp = &sc->sc_ethercom.ec_if;
1210
1211 #ifdef TROPICDEBUG
1212 printf("tr_rint: arb.command = %x, arb.station_id= %x\n",
1213 ARB_INB(sc, arb, ARB_CMD), ARB_INW(sc, arb, ARB_STATIONID));
1214 printf("arb.buf_addr = %x, arb.lan_hdr_len = %x\n",
1215 ARB_INW(sc, arb, ARB_RXD_BUFADDR),
1216 ARB_INB(sc, arb, ARB_RXD_LANHDRLEN));
1217 printf("arb.dlc_hdr_len = %d, arb.frame_len = %d\n",
1218 ARB_INB(sc, arb, ARB_RXD_DLCHDRLEN),
1219 ARB_INW(sc, arb, ARB_RXD_FRAMELEN));
1220 printf("arb.msg_type = %x\n", ARB_INB(sc, arb, ARB_RXD_MSGTYPE));
1221 #endif /* TROPICDEBUG */
1222 /*
1223 * copy the offset in RAM of the first receive buffer from the
1224 * receive-data block of the adapter request block associated
1225 * with the unit's softc struct into the receive control block.
1226 */
1227 rbc->rbufp = ARB_INW(sc, arb, ARB_RXD_BUFADDR);
1228
1229 /*
1230 * copy the pointer to data in first receive buffer
1231 */
1232 rbc->rbuf_datap = rbc->rbufp + RB_DATA;
1233 /*
1234 * the token-ring header is viewed as two header structs: the physical
1235 * header (aka TR header) with access, frame, dest, src, and routing
1236 * information, and the logical link control header (aka LLC header)
1237 * with dsap, ssap, llc, proto and type fields.
1238 *
1239 * rfc1042 requires support for unnumbered information (UI) commands,
1240 * but does not specify a required semantic, so we'll discard them.
1241 *
1242 */
1243
1244 /*
1245 * if there is a second receive buffer, set up the next pointer
1246 */
1247 if (RB_INW(sc, rbc->rbufp, RB_NEXTBUF))
1248 rbc->rbufp_next = RB_INW(sc, rbc->rbufp, RB_NEXTBUF) -
1249 RB_NEXTBUF;
1250 else
1251 rbc->rbufp_next = 0; /* we're finished */
1252
1253 rbc->data_len = RB_INW(sc, rbc->rbufp, RB_BUFLEN);
1254 /*
1255 * At this point we move the packet from the adapter to a chain
1256 * of mbufs
1257 */
1258 m = tr_get(sc, ARB_INW(sc, arb, ARB_RXD_FRAMELEN), ifp);
1259 /*
1260 * XXX Clear ARB interrupt here?
1261 */
1262 /*
1263 * XXX create a queue where the responses are buffered
1264 * XXX but is it really needed ?
1265 */
1266
1267 if (ASB_INB(sc, asb, RECV_RETCODE) != 0xff)
1268 printf("tr_rint: ASB IS NOT FREE!!!\n");
1269 /*
1270 * Load receive response into ASB.
1271 */
1272 ASB_OUTB(sc, asb, RECV_CMD, REC_DATA);
1273 ASB_OUTW(sc, asb, RECV_STATIONID, ARB_INW(sc, arb, ARB_STATIONID));
1274 ASB_OUTW(sc, asb, RECV_RESP_RECBUFADDR,
1275 ARB_INW(sc, arb, ARB_RXD_BUFADDR));
1276
1277 if (m == 0) {
1278 /*
1279 * Tell adapter data lost, no mbufs.
1280 */
1281 ASB_OUTB(sc, asb, RECV_RETCODE, 0x20);
1282 ACA_SETB(sc, ACA_ISRA_o, RESP_IN_ASB);
1283 ++ifp->if_ierrors;
1284 #ifdef TROPICDEBUG
1285 printf("tr_rint: packet dropped\n");
1286 #endif /* TROPICDEBUG */
1287 }
1288 else {
1289 /*
1290 * Indicate successful receive.
1291 */
1292 ASB_OUTB(sc, asb, RECV_RETCODE, 0);
1293 ACA_SETB(sc, ACA_ISRA_o, RESP_IN_ASB);
1294 ++ifp->if_ipackets;
1295
1296 #if NBPFILTER > 0
1297 if (ifp->if_bpf)
1298 bpf_mtap(ifp->if_bpf, m);
1299 #endif
1300 (*ifp->if_input)(ifp, m);
1301 }
1302 }
1303
1304 /*
1305 * Interrupt handler for old style "adapter requires data to transmit".
1306 */
1307 void
1308 tr_oldxint(sc)
1309 struct tr_softc *sc;
1310 {
1311 bus_size_t arb = sc->sc_arb; /* pointer to ARB */
1312 bus_size_t asb = sc->sc_asb; /* pointer to ASB */
1313 bus_size_t dhb; /* pointer to DHB */
1314 struct mbuf *m0; /* pointer to top of mbuf chain */
1315 u_short size = 0;
1316 char command;
1317 struct ifnet *ifp = &sc->sc_ethercom.ec_if;
1318 struct token_header *trh;
1319 int i;
1320 u_int8_t hlen;
1321
1322 /*
1323 * XXX xmit_asb_response()
1324 */
1325 if (ASB_INB(sc, asb, XMIT_RETCODE) != 0xff)
1326 printf("tr_oldxint: ASB IS NOT FREE!!!\n");
1327
1328 /* load parameters into ASB */
1329 ASB_OUTB(sc, asb, XMIT_CMDCORR, ARB_INB(sc, arb, ARB_XMT_CMDCORR));
1330 ASB_OUTW(sc, asb, XMIT_STATIONID, ARB_INW(sc, arb, ARB_STATIONID));
1331 ASB_OUTB(sc, asb, XMIT_RETCODE, 0);
1332 /*
1333 * XXX LLC_{X25,ISO}_LSAP
1334 */
1335 ASB_OUTB(sc, asb, XMIT_REMSAP, LLC_SNAP_LSAP);
1336
1337 /* XXX if num_dhb == 2 this should alternate between the two buffers */
1338 dhb = ARB_INW(sc, arb, ARB_XMT_DHBADDR);
1339
1340 command = SRB_INB(sc, sc->sc_srb, SRB_CMD);
1341
1342 if (command == XMIT_XID_CMD || command == XMIT_TEST_CMD) {
1343 ASB_OUTB(sc, asb, XMIT_CMD, command);
1344 ASB_OUTW(sc, asb, XMIT_FRAMELEN, 0x11);
1345 /*
1346 * XXX 0xe == sizeof(struct token_header)
1347 */
1348 ASB_OUTB(sc, asb, XMIT_HDRLEN, 0x0e);
1349
1350 SR_OUTB(sc, (dhb + 0), TOKEN_AC);
1351 SR_OUTB(sc, (dhb + 1), TOKEN_FC);
1352 /* Load destination and source addresses. */
1353 for (i=0; i < ISO88025_ADDR_LEN; i++) {
1354 SR_OUTB(sc, (dhb + 2 + i), 0xff);
1355 SR_OUTB(sc, (dhb + 8 + i), 0x00);
1356 }
1357 }
1358 else {
1359 /*
1360 * XXX what's command here ? command = 0x0d (always ?)
1361 */
1362 /* if data in queue, copy mbuf chain to DHB */
1363 IFQ_DEQUEUE(&ifp->if_snd, m0);
1364 if (m0 != 0) {
1365 #if NBPFILTER > 0
1366 if (ifp->if_bpf)
1367 bpf_mtap(ifp->if_bpf, m0);
1368 #endif
1369 /* Pull packet off interface send queue, fill DHB. */
1370 trh = mtod(m0, struct token_header *);
1371 hlen = sizeof(struct token_header);
1372 if (trh->token_shost[0] & TOKEN_RI_PRESENT) {
1373 /*
1374 * XXX assumes route info is in the same mbuf as the token-ring header
1375 */
1376 struct token_rif *rif;
1377
1378 rif = TOKEN_RIF(trh);
1379 hlen += ((ntohs(rif->tr_rcf) & TOKEN_RCF_LEN_MASK) >> 8);
1380 }
1381 size = tr_mbcopy(sc, dhb, m0);
1382 m_freem(m0);
1383
1384 ASB_OUTB(sc, asb, XMIT_CMD, XMIT_UI_FRM);
1385 ASB_OUTB(sc, asb, XMIT_HDRLEN, hlen);
1386
1387 /* Set size of transmission frame in ASB. */
1388 ASB_OUTW(sc, asb, XMIT_FRAMELEN, size);
1389 }
1390 else {
1391 printf("%s: unexpected empty mbuf send queue\n",
1392 sc->sc_dev.dv_xname);
1393
1394 /* Set size of transmission frame in ASB to zero. */
1395 ASB_OUTW(sc, asb, XMIT_FRAMELEN, 0);
1396 }
1397 }
1398 /*
1399 * XXX asb_response(void *asb, len)
1400 */
1401 /* tell adapter that there is a response in the ASB */
1402 ACA_SETB(sc, ACA_ISRA_o, RESP_IN_ASB);
1403 }
1404
1405 /*
1406 * Interrupt handler for fast path transmit complete
1407 */
1408 void
1409 tr_xint(sc)
1410 struct tr_softc *sc;
1411 {
1412 u_short tail;
1413 struct ifnet *ifp = &sc->sc_ethercom.ec_if;
1414 bus_size_t txbuf;
1415
1416 /*
1417 * To prevent race conditions on 8-bit cards when reading or writing
1418 * 16-bit values. See page 4-12 of the IBM manual.
1419 * XXX use volatile ?
1420 */
1421 do {
1422 tail = TXCA_INW(sc, TXCA_COMPLETION_QUEUE_TAIL);
1423 } while (tail != TXCA_INW(sc, TXCA_COMPLETION_QUEUE_TAIL));
1424 while (tail != TXCA_INW(sc, TXCA_FREE_QUEUE_TAIL)) {
1425 txbuf = TXCA_INW(sc, TXCA_FREE_QUEUE_TAIL) - XMIT_NEXTBUF;
1426 txbuf = TXB_INW(sc, txbuf, XMIT_NEXTBUF) - XMIT_NEXTBUF;
1427 if (TXB_INB(sc, txbuf, XMIT_RETCODE) != 0) {
1428 ifp->if_oerrors++;
1429 printf("%s: xmit error = 0x%x\n", sc->sc_dev.dv_xname,
1430 TXB_INB(sc, txbuf, XMIT_RETCODE));
1431 }
1432 sc->sc_xmit_buffers +=
1433 (TXB_INW(sc, txbuf, XMIT_FRAMELEN) + 514 - 1) / 514;
1434 tail = TXB_INW(sc, txbuf, XMIT_LASTBUF);
1435 TXCA_OUTW(sc, TXCA_FREE_QUEUE_TAIL, tail);
1436 tail = TXCA_INW(sc, TXCA_COMPLETION_QUEUE_TAIL);
1437 do {
1438 tail = TXCA_INW(sc, TXCA_COMPLETION_QUEUE_TAIL);
1439 } while (tail != TXCA_INW(sc, TXCA_COMPLETION_QUEUE_TAIL));
1440 }
1441 if (sc->sc_xmit_buffers == sc->sc_nbuf)
1442 ifp->if_flags &= ~IFF_OACTIVE;
1443 tr_start(ifp);
1444 }
1445
1446
1447 /*
1448 * copy out the packet byte-by-byte in reasonably optimal fashion
1449 */
1450 int
1451 tr_mbcopy(sc, dhb, m0)
1452 struct tr_softc *sc;
1453 bus_size_t dhb;
1454 struct mbuf *m0;
1455 {
1456 bus_size_t addr = dhb;
1457 int len, size = 0;
1458 char *ptr;
1459 struct mbuf *m;
1460
1461 for (m = m0; m; m = m->m_next) {
1462 len = m->m_len;
1463 ptr = mtod(m, char *);
1464
1465 bus_space_write_region_1(sc->sc_memt, sc->sc_sramh,
1466 addr, ptr, len);
1467 size += len;
1468 addr += len;
1469 }
1470 return (size);
1471 }
1472
1473 /*
1474 * Pull read data off an interface.
1475 * Len is length of data, with local net header stripped.
1476 * Off is non-zero if a trailer protocol was used, and
1477 * gives the offset of the trailer information.
1478 * XXX trailer information, really ????
1479 * We copy the trailer information and then all the normal
1480 * data into mbufs.
1481 *
1482 * called from tr_rint - receive interrupt routine
1483 */
1484 struct mbuf *
1485 tr_get(sc, totlen, ifp)
1486 struct tr_softc *sc;
1487 int totlen;
1488 struct ifnet *ifp;
1489 {
1490 int len;
1491 struct mbuf *m, *m0, *newm;
1492
1493 MGETHDR(m0, M_DONTWAIT, MT_DATA);
1494 if (m0 == 0)
1495 return (0);
1496
1497 m0->m_pkthdr.rcvif = ifp;
1498 m0->m_pkthdr.len = totlen;
1499 len = MHLEN;
1500
1501 m = m0;
1502 while (totlen > 0) {
1503 if (totlen >= MINCLSIZE) {
1504 MCLGET(m, M_DONTWAIT);
1505 if ((m->m_flags & M_EXT) == 0) {
1506 m_free(m0);
1507 return 0;
1508 }
1509 len = MCLBYTES;
1510 }
1511
1512 /*
1513 * Make sure data after the MAC header is aligned.
1514 */
1515 if (m == m0) {
1516 caddr_t newdata = (caddr_t)
1517 ALIGN(m->m_data + sizeof(struct token_header)) -
1518 sizeof(struct token_header);
1519 len -= newdata - m->m_data;
1520 m->m_data = newdata;
1521 }
1522 m->m_len = len = min(totlen, len);
1523 tr_bcopy(sc, mtod(m, char *), len);
1524 totlen -= len;
1525 if (totlen > 0) {
1526 MGET(newm, M_DONTWAIT, MT_DATA);
1527 if (newm == 0){
1528 m_freem(m0);
1529 return (0);
1530 }
1531 m->m_next = newm;
1532 m = newm;
1533 len = MLEN;
1534 }
1535 /*
1536 * ignore trailers case again
1537 */
1538 }
1539 return (m0);
1540 }
1541
1542 /*
1543 * tr_ioctl - process an ioctl request
1544 */
1545 int
1546 tr_ioctl(ifp, cmd, data)
1547 struct ifnet *ifp;
1548 u_long cmd;
1549 caddr_t data;
1550 {
1551 struct tr_softc *sc = ifp->if_softc;
1552 struct ifreq *ifr = (struct ifreq *) data;
1553 struct ifaddr *ifa = (struct ifaddr *) data;
1554 int s;
1555 int error = 0;
1556
1557 s = splnet();
1558
1559 switch (cmd) {
1560 case SIOCSIFADDR:
1561 if ((error = tr_enable(sc)) != 0)
1562 break;
1563
1564 switch (ifa->ifa_addr->sa_family) {
1565 #ifdef INET
1566 case AF_INET:
1567 /* XXX if not running */
1568 if ((ifp->if_flags & IFF_RUNNING) == 0) {
1569 tr_init(sc); /* before arp_ifinit */
1570 tr_sleep(sc);
1571 }
1572 arp_ifinit(ifp, ifa);
1573 break;
1574 #endif /*INET*/
1575 default:
1576 /* XXX if not running */
1577 if ((ifp->if_flags & IFF_RUNNING) == 0) {
1578 tr_init(sc); /* before arpwhohas */
1579 tr_sleep(sc);
1580 }
1581 break;
1582 }
1583 break;
1584 case SIOCSIFFLAGS:
1585 /*
1586 * 1- If the adapter is DOWN , turn the device off
1587 * ie. adapter down but still running
1588 * 2- If the adapter is UP, turn the device on
1589 * ie. adapter up but not running yet
1590 */
1591 if ((ifp->if_flags & (IFF_RUNNING | IFF_UP)) == IFF_RUNNING) {
1592 tr_stop(sc);
1593 ifp->if_flags &= ~IFF_RUNNING;
1594 tr_disable(sc);
1595 }
1596 else if ((ifp->if_flags & (IFF_RUNNING | IFF_UP)) == IFF_UP) {
1597 if ((error = tr_enable(sc)) != 0)
1598 break;
1599 tr_init(sc);
1600 tr_sleep(sc);
1601 }
1602 else {
1603 /*
1604 * XXX handle other flag changes
1605 */
1606 }
1607 break;
1608 case SIOCGIFMEDIA:
1609 case SIOCSIFMEDIA:
1610 error = ifmedia_ioctl(ifp, ifr, &sc->sc_media, cmd);
1611 break;
1612 #ifdef SIOCSIFMTU
1613 case SIOCSIFMTU:
1614 if (ifr->ifr_mtu > sc->sc_maxmtu)
1615 error = EINVAL;
1616 else
1617 ifp->if_mtu = ifr->ifr_mtu;
1618 break;
1619 #endif
1620 default:
1621 error = EINVAL;
1622 }
1623 splx(s);
1624 return (error);
1625 }
1626
1627
1628 /*
1629 * tr_bcopy - like bcopy except that it knows about the structure of
1630 * adapter receive buffers.
1631 */
1632 void
1633 tr_bcopy(sc, dest, len)
1634 struct tr_softc *sc; /* pointer to softc struct for this adapter */
1635 u_char *dest; /* destination address */
1636 int len; /* number of bytes to copy */
1637 {
1638 struct rbcb *rbc = &sc->rbc; /* pointer to rec buf ctl blk */
1639
1640 /* While amount of data needed >= amount in current receive buffer. */
1641 while (len >= rbc->data_len) {
1642 /* Copy all data from receive buffer to destination. */
1643
1644 bus_space_read_region_1(sc->sc_memt, sc->sc_sramh,
1645 rbc->rbuf_datap, dest, (bus_size_t)rbc->data_len);
1646 len -= rbc->data_len; /* update length left to transfer */
1647 dest += rbc->data_len; /* update destination address */
1648
1649 /* Make next receive buffer current receive buffer. */
1650 rbc->rbufp = rbc->rbufp_next;
1651 if (rbc->rbufp != 0) { /* More receive buffers? */
1652
1653 /* Calculate pointer to next receive buffer. */
1654 rbc->rbufp_next = RB_INW(sc, rbc->rbufp, RB_NEXTBUF);
1655 if (rbc->rbufp_next != 0)
1656 rbc->rbufp_next -= RB_NEXTBUF;
1657
1658 /* Get pointer to data in current receive buffer. */
1659 rbc->rbuf_datap = rbc->rbufp + RB_DATA;
1660
1661 /* Get length of data in current receive buffer. */
1662 rbc->data_len = RB_INW(sc, rbc->rbufp, RB_BUFLEN);
1663 }
1664 else {
1665 if (len != 0) /* len should equal zero. */
1666 printf("tr_bcopy: residual data not copied\n");
1667 return;
1668 }
1669 }
1670
1671 /* Amount of data needed is < amount in current receive buffer. */
1672
1673 bus_space_read_region_1(sc->sc_memt, sc->sc_sramh,
1674 rbc->rbuf_datap, dest, (bus_size_t)len);
1675 rbc->data_len -= len; /* Update count of data in receive buffer. */
1676 rbc->rbuf_datap += len; /* Update pointer to receive buffer data. */
1677 }
1678
1679 /*
1680 * tr_opensap - open the token ring SAP interface
1681 */
1682 void
1683 tr_opensap(sc, type)
1684 struct tr_softc *sc;
1685 u_char type;
1686 {
1687 bus_size_t srb = sc->sc_srb;
1688
1689 /************************************************************************
1690 ** To use the SAP level interface, we will have to execute a **
1691 ** DLC.OPEN.SAP (pg.6-61 of the Token Ring Tech. Ref.) after we have **
1692 ** received a good return code from the DIR.OPEN.ADAPTER command. **
1693 ** We will open the IP SAP x'aa'. **
1694 ** **
1695 ** STEPS: **
1696 ** 1) Reset SRB response interrupt bit **
1697 ** 2) Use the open_sap srb. **
1698 ** 3) Fill the following fields: **
1699 ** command - x'15' **
1700 ** sap_value - x'aa' **
1701 ** sap_options- x'24' **
1702 ** **
1703 ***********************************************************************/
1704
1705 ACA_RSTB(sc, ACA_ISRP_o, ~(SRB_RESP_INT));
1706
1707 SRB_OUTB(sc, srb, SRB_CMD, DLC_OPEN_SAP);
1708 SRB_OUTB(sc, srb, SRB_RETCODE, 0x00);
1709 SRB_OUTW(sc, srb, SRB_OPNSAP_STATIONID, 0x0000);
1710 SRB_OUTB(sc, srb, SRB_OPNSAP_TIMERT1, 0x00);
1711 SRB_OUTB(sc, srb, SRB_OPNSAP_TIMERT2, 0x00);
1712 SRB_OUTB(sc, srb, SRB_OPNSAP_TIMERTI, 0x00);
1713 SRB_OUTB(sc, srb, SRB_OPNSAP_MAXOUT, 0x00);
1714 SRB_OUTB(sc, srb, SRB_OPNSAP_MAXIN, 0x00);
1715 SRB_OUTB(sc, srb, SRB_OPNSAP_MAXOUTINCR, 0x00);
1716 SRB_OUTB(sc, srb, SRB_OPNSAP_MAXRETRY, 0x00);
1717 SRB_OUTB(sc, srb, SRB_OPNSAP_GSAPMAXMEMB, 0x00);
1718 SRB_OUTW(sc, srb, SRB_OPNSAP_MAXIFIELD, 0x0088);
1719 SRB_OUTB(sc, srb, SRB_OPNSAP_SAPVALUE, type);
1720 SRB_OUTB(sc, srb, SRB_OPNSAP_SAPOPTIONS, 0x24);
1721 SRB_OUTB(sc, srb, SRB_OPNSAP_STATIONCNT, 0x01);
1722 SRB_OUTB(sc, srb, SRB_OPNSAP_SAPGSAPMEMB, 0x00);
1723
1724 ACA_SETB(sc, ACA_ISRP_e, INT_ENABLE);
1725 ACA_SETB(sc, ACA_ISRA_o, CMD_IN_SRB);
1726 }
1727
1728 /*
1729 * tr_sleep - sleep to wait for adapter to open
1730 */
1731 void
1732 tr_sleep(sc)
1733 struct tr_softc *sc;
1734 {
1735 int error;
1736
1737 error = tsleep(&sc->tr_sleepevent, 1, "trsleep", hz * 30);
1738 if (error == EWOULDBLOCK)
1739 printf("%s: sleep event timeout\n", sc->sc_dev.dv_xname);
1740 }
1741
1742 void
1743 tr_watchdog(ifp)
1744 struct ifnet *ifp;
1745 {
1746 struct tr_softc *sc = ifp->if_softc;
1747
1748 log(LOG_ERR,"%s: device timeout\n", sc->sc_dev.dv_xname);
1749 ++ifp->if_oerrors;
1750
1751 tr_reset(sc);
1752 }
1753
1754 int
1755 tr_enable(sc)
1756 struct tr_softc *sc;
1757 {
1758 if (sc->sc_enabled == 0 && sc->sc_enable != NULL) {
1759 if ((*sc->sc_enable)(sc) != 0) {
1760 printf("%s: device enable failed\n",
1761 sc->sc_dev.dv_xname);
1762 return (EIO);
1763 }
1764 }
1765
1766 sc->sc_enabled = 1;
1767 return (0);
1768 }
1769
1770 void
1771 tr_disable(sc)
1772 struct tr_softc *sc;
1773 {
1774 if (sc->sc_enabled != 0 && sc->sc_disable != NULL) {
1775 (*sc->sc_disable)(sc);
1776 sc->sc_enabled = 0;
1777 }
1778 }
1779
1780 int
1781 tr_activate(self, act)
1782 struct device *self;
1783 enum devact act;
1784 {
1785 struct tr_softc *sc = (struct tr_softc *)self;
1786 struct ifnet *ifp = &sc->sc_ethercom.ec_if;
1787 int rv = 0, s;
1788
1789 s = splnet();
1790 switch (act) {
1791 case DVACT_ACTIVATE:
1792 rv = EOPNOTSUPP;
1793 break;
1794
1795 case DVACT_DEACTIVATE:
1796 if_deactivate(ifp);
1797 break;
1798 }
1799 splx(s);
1800 return (rv);
1801 }
1802
1803 int
1804 tr_detach(self, flags)
1805 struct device *self;
1806 int flags;
1807 {
1808 struct tr_softc *sc = (struct tr_softc *)self;
1809 struct ifnet *ifp = &sc->sc_ethercom.ec_if;
1810
1811 tr_disable(sc);
1812
1813 callout_stop(&sc->sc_init_callout);
1814 callout_stop(&sc->sc_reinit_callout);
1815
1816 /* Delete all remaining media. */
1817 ifmedia_delete_instance(&sc->sc_media, IFM_INST_ANY);
1818
1819 token_ifdetach(ifp);
1820 if_detach(ifp);
1821
1822 shutdownhook_disestablish(sc->sc_sdhook);
1823
1824 return (0);
1825 }
Cache object: 72180584fdea800004cf554fe85327fe
|