FreeBSD/Linux Kernel Cross Reference
sys/i386ps2/if_tr.c
1 /*
2 * Mach Operating System
3 * Copyright (c) 1991 Carnegie Mellon University
4 * Copyright (c) 1991 IBM Corporation
5 * All Rights Reserved.
6 *
7 * Permission to use, copy, modify and distribute this software and its
8 * documentation is hereby granted, provided that both the copyright
9 * notice and this permission notice appear in all copies of the
10 * software, derivative works or modified versions, and any portions
11 * thereof, and that both notices appear in supporting documentation,
12 * and that the nema IBM not be used in advertising or publicity
13 * pertaining to distribution of the software without specific, written
14 * prior permission.
15 *
16 * CARNEGIE MELLON AND IBM ALLOW FREE USE OF THIS SOFTWARE IN ITS "AS IS"
17 * CONDITION. CARNEGIE MELLON AND IBM DISCLAIM ANY LIABILITY OF ANY KIND FOR
18 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
19 *
20 * Carnegie Mellon requests users of this software to return to
21 *
22 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
23 * School of Computer Science
24 * Carnegie Mellon University
25 * Pittsburgh PA 15213-3890
26 *
27 * any improvements or extensions that they make and grant Carnegie Mellon
28 * the rights to redistribute these changes.
29 */
30
31 /*
32 * HISTORY
33 * $Log: if_tr.c,v $
34 * Revision 2.4 93/05/28 21:22:34 rvb
35 * In tropen(), wait until the adapter is actually running before
36 * returning.
37 * [93/05/28 15:12:30 chs]
38 *
39 * Revision 2.3 93/05/15 19:44:05 mrt
40 * machparam.h -> machspl.h
41 *
42 * Revision 2.2 93/02/04 08:00:19 danner
43 * Integrate PS2 code from IBM.
44 * [93/01/18 prithvi]
45 *
46 */
47
48
49 /*
50 * COMPONENT_NAME: (MKDEVNET) Mach Network Device Drivers
51 *
52 * FUNCTIONS:
53 *
54 * ORIGINS: 27
55 */
56
57 /*
58 * IBM/4.3 6152 token-ring driver (Ungerman-Bass adaptor card)
59 *
60 * modified for OSF/1
61 * routines:
62 * trprobe(addr)
63 * trattach(iod)
64 * trreset(unit)
65 * trsuspend(iod, idr, how) needed only for DOS
66 * trinit(unit)
67 * trstart(trs,m0)
68 * trint(unit)
69 * trrint(unit)
70 * trxint(unit)
71 * trmbcopy(dhb, m0)
72 * trget(trs, totlen,ifp) rewritten
73 * troutput(ifp, m0, dst) not moved to if_tokensubr.c
74 * trioctl(ifp, cmd, data)
75 * trbcopy(trs, dest, len)
76 * trprinttraddr(p)
77 * tropensap(unit,type)
78 * trsleep(unit)
79 * trtimout(unit)
80 *
81 * Major problem areas:
82 * - getting the dependencies (header, byte order) correct, the if_un.c
83 * code is the model
84 * - modification of trget() to match 4.4bsd mbuf changes, again, the
85 * if_un.c code is the model
86 * - whether to create a net/if_tokensubr.c equivalent or change the
87 * troutput()/trrint() routines in place
88 * Minor nits:
89 * - the type fields are common (ip, arp, whatever), so use ETHERTYPE_IP
90 * and ETHERTYPE_ARP for the moment (replaces TR_IPTYPE, TR_ARPTYPE).
91 * - there could be a net/if_802.5.h corresponding if if_ether.h, with
92 * declarations moved from both if_trvar.h and if_trreg.h.
93 * OSF/1 changes:
94 * - routing information field handling in arpresolve, etc., see
95 * netinet/if_ether.c and netinet/if_ether.h
96 * ACIS todo:
97 * - add IFF_BRIDGE check to output routine ca_atr/if_lan.c
98 * - make the two drivers consistent in symbol use, e.g., TR_IPTYPE
99 */
100
101 #ifdef hc
102 pragma off (optimize)
103 #endif hc
104
105 #include "tr.h"
106 #if NTR > 0
107
108 #if defined(TRDEBUG) && !defined(DEBUG)
109 #define DEBUG 1 /* driver specific debugging */
110 #endif
111
112 #ifdef MACH_KERNEL
113 #include <kern/time_out.h>
114 #include <device/device_types.h>
115 #include <device/errno.h>
116 #include <device/io_req.h>
117 #include <device/if_hdr.h>
118 #include <device/if_ether.h>
119 #include <device/net_status.h>
120 #include <device/net_io.h>
121 #else MACH_KERNEL
122 #include <sys/param.h>
123 #include <sys/systm.h>
124 #include <sys/mbuf.h>
125 #include <sys/buf.h>
126 #include <sys/protosw.h>
127 #include <sys/socket.h>
128 #include <sys/vmmac.h>
129 #include <sys/ioctl.h>
130 #include <sys/errno.h>
131
132 #include <sys/time.h>
133 #include <sys/kernel.h>
134
135 #include <net/if.h>
136 #include <net/netisr.h>
137 #include <net/route.h>
138
139 #include <netinet/in.h>
140 #include <netinet/in_systm.h>
141 #include <netinet/ip.h>
142 #include <netinet/in_var.h>
143 #include <netinet/if_ether.h>
144
145 #include <inet.h>
146
147 #endif MACH_KERNEL
148
149 /*
150 * here is the first problem, ca/io.h and caio/ioccvar.h
151 * are not used... we'll use the AT386 source as a model.
152 * if_trreg.h and if_trvar.h appear to be used, so in they go.
153 */
154
155 #include <i386ps2/if_common.h>
156 #include <i386ps2/bus.h>
157 #include "if_trreg.h"
158 #include "if_trvar.h"
159 #include <i386/seg.h>
160 #include <i386/ipl.h>
161 #include <i386/machspl.h>
162 #ifdef OSF
163 #include <i386/handler.h>
164 #endif
165
166 #ifdef OSF
167 static ihandler_t tr_handler;
168 static ihandler_id_t *tr_handler_id;
169 #endif OSF
170
171 /*
172 * here is the first problem with the token-ring driver:
173 * ca/io.h and caio/ioccvar.h
174 * are not used... we'll use the AT386 source as a model.
175 *
176 * ../machine/io.h
177 * large number of macros are defined, e.g., OUT(port,d)
178 * #include "../machineio/ioccvar.h"
179 */
180
181
182 int trprobe(), trattach();
183 unsigned short tr_swap();
184
185 caddr_t trstd[] = { (caddr_t) 0x00000a20, (caddr_t) 0x00000a24, 0};
186
187 /*
188 * this was a pointer to an iocc_device in ca_atr/if_lan.c
189 * in if_un.c we specify values, here we don't, refer to relyea, eric
190 */
191 struct i386_dev *trinfo[NTR];
192
193 int trint(), trinit(), trioctl(), troutput(), trreset(), trtimout();
194 int trsuspend();
195 int trstart();
196
197 unsigned long tokdebug = 0; /* flag for debugfs */
198
199 /*
200 * see <i386/AT386/atbus.h> for declaration, eric
201 */
202 struct i386_driver trdriver =
203 /* probe slave attach dname dinfo mname minfo */
204 {trprobe, 0, trattach, "tr", trinfo, 0, 0};
205
206
207 int (*trintrs[])() = {trint, 0};
208
209
210 /*
211 * Token-Ring software status per adapter
212 */
213 struct tr_softc {
214 #ifdef MACH_KERNEL
215 struct ifnet trs_if; /* generic interface header */
216 u_char trs_addr[6]; /* token-ring hardware address */
217 #else MACH_KERNEL
218 struct arpcom trs_ac; /* like ethernet */
219 #define trs_if trs_ac.ac_if /* network-visible interface */
220 #define trs_addr trs_ac.ac_enaddr /* hardware token-ring address */
221 #endif MACH_KERNEL
222 unsigned char trs_intlevel; /* adapter interrupt level */
223 short trs_ocount; /* count of active output requests */
224 char srbfree; /* 0 = SRB free, 1 = SRB in use */
225 unsigned char *mmio; /* address of MMIO region */
226 unsigned char *sram; /* address of shared RAM */
227 struct rbcb rbc; /* receiver buffer control block */
228 struct aca *aca; /* pointer to adapter ACA */
229 struct trs_cb cb; /* struct of pointers to ctl blocks */
230 struct init_resp init_rs; /* adapter initialization response */
231 unsigned short exsap_station; /* station assigned by open sap cmd */
232 struct trs_cb init_cb; /* place to save initial srb address */
233 unsigned char wire_fault; /* flag a wire fault has occurred */
234 caddr_t trsleep_event; /* tr event signalled on successful */
235 /* open of adapter */
236 int alive; /* card is alive */
237 int trs_flags; /* saved flags over suspend */
238 } tr_softc[NTR];
239
240
241
242 /*
243 * trprobe
244 */
245 trprobe(addr, iod)
246 register struct trdevice *addr; /* pointer to device registers */
247 register struct i386_dev *iod; /* pointer to device structure */
248 {
249 register unsigned char *mmio = 0; /* pointer to MMIO Region */
250 register struct aca *aca; /* pointer to Attachment Control Area */
251 int s;
252 int irq;
253
254
255 if (inb(addr) == inb(0xffff)) {
256 outb(addr,0);
257 if (inb(addr) == inb(0xffff)) {
258 return(0);
259 }
260 }
261
262 if (irq = tr_get_irq(addr))
263 iod->dev_pic = irq; /* set the IRQ level */
264
265 iod->dev_spl = SPL4; /* set to known spl level */
266
267
268 /*
269 * Generate interrupt
270 */
271 OUT(&addr->reset, 0); /* latch on an unconditional adapter reset */
272 trdelay(50); /* delay 50ms */
273
274 /*
275 * turn off adapter reset, generate interrupt
276 */
277 OUT(&addr->release_reset, 0);
278
279 /*
280 * Calculate address of Attachment Control Area
281 */
282 mmio = (unsigned char *) (((IN(&addr->switch_read) & 0xfc) << 11)
283 + TR_MMIO_OFFSET);
284 aca = (struct aca *)(mmio + TR_ACA_OFFSET); /* get ACA address */
285
286 /*
287 * allow adapter to interrupt PC
288 */
289 s = splhigh();
290 MM_OUT(&aca->set.isrp_h, INT_ENABLE);
291
292 trdelay(1000);
293
294 #ifdef notdef
295 PROBE_DELAY(1 000 000); /* delay for 1 seconds, delay is interruptable */
296 #endif
297 /*
298 * since ps-2 uses level trigerring for interrupts, we must
299 * not allow interupts to go to the pc until we clear the
300 * SRB RESPONSE INTERRUPT in TRATTACH
301 */
302 MM_OUT(&aca->reset.isrp_h, ~(INT_ENABLE));
303 splx(s);
304
305
306 return(PROBE_OK); /* indicate adapter should have interrupted */
307 }
308
309 #define TOKEN_ID 0xE000
310
311 /*
312 * determine what IRQ we are at
313 */
314 tr_get_irq(port)
315 int port;
316 {
317 int slot;
318 int addr;
319 int irq = 0;
320
321 for (slot=0; (slot = pos_slot(TOKEN_ID, slot)) >= 0; ++slot) {
322 addr = (slots[slot].pos_info[1] & 1) == 0 ? 0xa20 : 0xa24;
323 if (addr != port)
324 continue; /* look for another */
325 irq = 2 + (slots[slot].pos_info[1]>>7) +
326 ((slots[slot].pos_info[2]&1) << 3);
327 break;
328 }
329
330 if (irq == 2)
331 irq = 9; /* IRQ 2 is remaped to IRQ 9 */
332 return(irq); /* don't know - assume normal default */
333 }
334
335
336 /*
337 * trattach - Make this interface available to the system-network-software.
338 * When the system-network-software is ready to accept packets it will
339 * initialize the interface by calling trinit().
340 */
341 trattach(iod)
342 register struct i386_dev *iod; /* pointer to device structure */
343 {
344 register struct tr_softc *trs = &tr_softc[iod->dev_unit];
345 register struct ifnet *ifp = &trs->trs_if;
346 register struct trdevice *addr =
347 (struct trdevice *)((unsigned int)iod->dev_addr & 0xffffff);
348 unsigned long i;
349 int temp;
350
351 trs->wire_fault = 0x00;
352
353 /*
354 * init network-visible interface
355 */
356 ifp->if_unit = iod->dev_unit;
357 ifp->if_mtu = ETHERMTU;
358 #ifdef MACH_KERNEL
359 ifp->if_header_size = sizeof(struct tr_head);
360 ifp->if_header_format = HDR_802;
361 ifp->if_address_size = 6;
362 ifp->if_address = (char *)&trs->trs_addr[0];
363 if_init_queues(ifp);
364 #else MACH_KERNEL
365 ifp->if_name = "tr";
366 #endif MACH_KERNEL
367
368 /*
369 * Save interrupt level in softc struct
370 * not used! eric
371 * trs->trs_intlevel = iod->dev_irq;
372 */
373
374 /* Read adapter switches and calculate addresses of MMIO and ACA */
375 i = IN(&addr->switch_read); /* Read switches */
376
377 /* set MMIO address */
378 trs->mmio = 0;
379 trs->mmio = (unsigned char *) (((i & 0xfc) << 11) + TR_MMIO_OFFSET);
380 /* set ACA address */
381 trs->aca = (struct aca *)(trs->mmio + TR_ACA_OFFSET);
382 DEBUGF(tokdebug,printf("trattach: ram = %x mmio=%x aca=%x\n",
383 ((i&0xfc) <<11),trs->mmio, trs->aca););
384
385 /*
386 * Get address of adapter shared RAM from PIO read of loc. 0xa22
387 */
388 i = IN(&addr->release_reset) & 0xfe; /* Read switches */
389
390 /*
391 * Get address of sram
392 */
393 trs->sram = (unsigned char *) (caddr_t)(i << 12);
394 DEBUGF(tokdebug,printf("trattach: sram = %x\n",trs->sram););
395
396 /*
397 * Save address of SRB in softc struct
398 */
399 #if 1
400 trdelay(2000);
401 temp = MM_IN(&trs->aca->rw.wrb_h);
402 temp <<= 8;
403 /* trdelay(500); */
404 temp |= MM_IN(&trs->aca->rw.wrb_l);
405 #else
406 for (temp=i=0; i<10; ++i)
407 temp |= MM_INW(&trs->aca->rw.wrb); /* hardware bug? */
408 #endif
409 trs->cb.srb = (union sr_srb *)(trs->sram + temp);
410 trs->init_cb.srb = trs->cb.srb;
411 DEBUGF(tokdebug,printf("trattach: srb = %x\n",trs->init_cb.srb));
412 DEBUGF(tokdebug,printf("trattach: srb at sram + %#x\n", temp));
413 /*
414 * Save SRB response to adapter card initialization
415 */
416 for (i = 0; i < sizeof(struct init_resp); i++)
417 ((unsigned char *)&trs->init_rs)[i] = MM_IN(((char *)trs->cb.srb + i));
418
419 trs->init_rs.encoded_addr = tr_swap(trs->init_rs.encoded_addr);
420 DEBUGF(tokdebug,
421 {
422 trs->init_rs.bring_up_res = tr_swap(trs->init_rs.bring_up_res);
423 trs->init_rs.level_addr = tr_swap(trs->init_rs.level_addr);
424 trs->init_rs.adap_addr = tr_swap(trs->init_rs.adap_addr);
425 trs->init_rs.params_addr = tr_swap(trs->init_rs.params_addr);
426 trs->init_rs.mac_addr = tr_swap(trs->init_rs.mac_addr);
427 printf("\t\tbring up result=%x\n",trs->init_rs.bring_up_res);
428 printf("\t\tencoded address=%x\n",trs->init_rs.encoded_addr);
429 printf("\t\tlevel address=%x\n",trs->init_rs.level_addr);
430 printf("\t\tadapter address=%x\n",trs->init_rs.adap_addr);
431 printf("\t\tparameter address=%x\n",trs->init_rs.params_addr);
432 printf("\t\tMAC buffer address=%x\n",trs->init_rs.mac_addr);
433 })
434
435 /*
436 * Save adapter hardware address
437 */
438 for (i = 0; i < TR_ADDR_LEN; i++)
439 trs->trs_addr[i] =
440 MM_IN((trs->init_rs.encoded_addr + trs->sram + i));
441
442 printf("tr%d: token-ring address ", ifp->if_unit);
443 trprinttraddr(trs->trs_addr);
444 printf("\n");
445
446 /* Indicate that SRB is used */
447 trs->srbfree = 1;
448 #ifndef MACH_KERNEL
449 /*
450 * we use the same method as in un_attach,
451 * the trstart() entry in the ifp struct is added
452 *
453 * flags are set to IFF_BROADCAST, do we want to handle trailers?
454 * we don't in the pegasus-derived osf1 ethernet driver
455 */
456 ifp->if_init = trinit;
457 ifp->if_output = troutput;
458 ifp->if_ioctl = trioctl;
459 ifp->if_reset = trreset;
460 #ifdef OSF /* REALLY BSD44 */
461 ifp->if_start = trstart;
462 #endif OSF
463 #endif MACH_KERNEL
464 ifp->if_flags = IFF_BROADCAST;
465 /*
466 * clear the SRB-response interrupt bit
467 */
468 MM_OUT(&trs->aca->reset.isrp_l, ~(SRB_RESP_INT));
469 MM_OUT(&trs->aca->reset.isra_l, ~(CMD_IN_SRB));
470 MM_OUT(&trs->aca->set.isrp_h, INT_ENABLE); /*allow pc ints. */
471 #ifndef MACH_KERNEL
472 if_attach(ifp);
473 #endif MACH_KERNEL
474
475 trs->alive = 1;
476 DEBUGF(tokdebug, printf("tr%d: attached\n", iod->dev_unit);)
477 }
478
479
480
481 /*
482 * trreset - reset interface (issue a DIR CLOSE ADAPTER command)
483 */
484 trreset(unit)
485 register int unit;
486 {
487 register struct i386_dev *iod; /* pointer to device structure */
488 register struct tr_softc *trs = &tr_softc[unit];
489 register union sr_srb *srb = trs->cb.srb;
490 register struct ifnet *ifp = &trs->trs_if;
491
492
493
494 if (unit < NTR && (iod = trinfo[unit]) != 0 && iod->dev_alive != 0){
495 if (ifp->if_flags & IFF_RUNNING) {
496 trs->srbfree = 1; /* indicate SRB in use */
497 /* close command */
498 MM_OUT(&srb->close.command, DIR_CLOSE);
499 /* tell adapter: command in SRB */
500 MM_OUT(&trs->aca->set.isra_l, CMD_IN_SRB);
501 /* wait for it to complete */
502 trsleep(ifp->if_unit);
503 }
504 MM_OUT(&trs->aca->reset.isrp_h, ~(INT_ENABLE)); /* paranoia */
505 DEBUGF(tokdebug, printf("tr%d: reset\n", unit);)
506 }
507 }
508
509 #ifdef ATR
510 /*
511 * routine called when a suspend command has been issued that
512 * shuts down (by calling trreset) the interface when we're about
513 * to return control to DOS, and then brings it back again after
514 * we regain control. We keep a local copy of the ifp->if_flags
515 * in trs->trs_softc so that we can tell if we should get the adapter
516 * running again (trreset clears IFF_RUNNING etc).
517 */
518 trsuspend(iod, idr, how)
519 register struct i386_dev *iod;
520 struct i386_dev *idr;
521 {
522 int unit = iod->dev_unit;
523 register struct tr_softc *trs = &tr_softc[unit];
524 register struct ifnet *ifp = &trs->trs_if;
525
526 if (how == SUSPEND_START) {
527 trs->trs_flags = ifp->if_flags; /* save flag state */
528 if (ifp->if_flags & IFF_RUNNING)
529 trreset(unit); /* stop it running */
530 } else if (how == SUSPEND_DONE) {
531 /* clear the SRB-response interrupt bit */
532 MM_OUT(&trs->aca->reset.isrp_l, ~(SRB_RESP_INT));
533 MM_OUT(&trs->aca->reset.isra_l, ~(CMD_IN_SRB));
534 if (trs->trs_flags & IFF_RUNNING) {
535 /*allow pc ints. */
536 MM_OUT(&trs->aca->set.isrp_h, INT_ENABLE);
537 /* pretend not running */
538 ifp->if_flags &= ~IFF_RUNNING;
539 trinit(unit);
540 }
541 }
542
543 }
544 #endif ATR
545
546
547 /*
548 * trinit - initialize network interface, open adapter for packet
549 * reception and start any pending output
550 */
551 trinit(unit)
552 register int unit;
553 {
554 register struct tr_softc *trs = &tr_softc[unit];
555 register struct ifnet *ifp = &trs->trs_if;
556 register union sr_srb *srb = trs->init_cb.srb;
557 register int i;
558 register struct i386_dev *iod = trinfo[unit]; /* pointer to device structure */
559 int s;
560
561 #ifdef MACH_KERNEL
562 #else MACH_KERNEL
563 if (ifp->if_addrlist == (struct ifaddr *) 0) {
564 /* no address */
565 return;
566 }
567 #endif MACH_KERNEL
568 if ((ifp->if_flags & IFF_RUNNING) == 0) { /* if not running */
569 s = splimp();
570 trs->trs_ocount = 0; /* reset active-output-request count */
571 /*
572 * open adapter. the open-complete interrupt handler will
573 * start any pending output.
574 */
575 trs->srbfree = 1; /* indicate SRB in use */
576
577 /* zero SRB */
578 trs->cb.srb = trs->init_cb.srb;
579 /* restore initial srb in trs structure */
580
581 for (i=0; i < sizeof(*trs->cb.srb); i++)
582 MM_OUT(((char *)(trs->cb.srb) + i), 0);
583
584 /* set open parameters in SRB */
585 MM_OUT(&srb->open_cmd.command, DIR_OPEN_ADAPTER); /* open cmd */
586 MM_OUTW(&srb->open_cmd.open_options, OPEN_PASS_BCON_MAC);
587 MM_OUTW(&srb->open_cmd.num_rcv_buf, NUM_RCV_BUF);
588 MM_OUTW(&srb->open_cmd.rcv_buf_len, RCV_BUF_LEN);
589 MM_OUTW(&srb->open_cmd.dhb_length, DHB_LENGTH);
590 MM_OUT(&srb->open_cmd.num_dhb, NUM_DHB);
591 MM_OUT(&srb->open_cmd.dlc_max_sap, 2);
592 /* allow MAX of two SAPS */
593 MM_OUT(&srb->open_cmd.dlc_max_sta, 8);
594 /* allow MAX of 8 stations */
595
596 #ifdef OSF
597 tr_handler.ih_level = 9;
598 tr_handler.ih_handler = trint;
599 tr_handler.ih_resolver = (int (*)()) NULL;
600 tr_handler.ih_stats.intr_type = INTR_DEVICE;
601 tr_handler.ih_stats.intr_cnt = 0;
602 tr_handler.ih_priority = SPL7;
603 tr_handler.ih_flags = IH_FLAG_NOSHARE;
604 if ((tr_handler_id = handler_add( &tr_handler )) != NULL)
605 handler_enable( tr_handler_id );
606 else
607 return(ENXIO);
608 #else
609 take_dev_irq(iod); /* take over interrupt */
610 #endif OSF
611
612 /* allow interrupts */
613 MM_OUT(&trs->aca->set.isrp_h, INT_ENABLE);
614
615 /* tell adapter: command in SRB */
616 MM_OUT(&trs->aca->set.isra_l, CMD_IN_SRB);
617
618
619 splx(s);
620 }
621 DEBUGF(tokdebug, printf("tr%d: init'ed\n", unit);)
622 }
623
624
625
626 /*
627 * trstart - Present transmit request to adapter
628 */
629 trstart(trs)
630 register struct tr_softc *trs; /* pointer to softc struct */
631 {
632 register union sr_srb *srb = trs->cb.srb; /* pointer to SRB */
633
634 DEBUGF(tokdebug, printf("tr%d: trstart\n",trs->trs_if.if_unit);)
635 trs->srbfree = 1; /* indicate SRB in use */
636
637 /* load SRB to request transmit */
638
639 MM_OUT(&srb->xmit.command, XMIT_UI_FRM); /* xmit ui frame */
640
641 MM_OUTW(&srb->xmit.station_id, trs->exsap_station);
642 /* tell adapter that SRB loaded and ask for SRB free interrupt */
643 MM_OUT(&trs->aca->set.isra_l, (CMD_IN_SRB + SRB_FREE));
644 }
645
646
647 #ifdef MACH_KERNEL
648 #define IF_EMPTYQUEUE(queue) ((queue).ifq_len == 0)
649 #else MACH_KERNEL
650 #define IF_EMPTYQUEUE(queue) ((queue).ifq_head == 0)
651 #endif MACH_KERNEL
652
653 /*
654 * trint - interrupt handler. Find the cause of the interrupt and
655 * service it.
656 */
657 trint()
658 {
659 register int unit = 0; /* TEMP */
660 /* get address of softc struct for this adapter */
661 register struct tr_softc *trs = &tr_softc[unit];
662 register struct ifnet *ifp = &trs->trs_if;
663
664
665 /* holds status read from adapter status register */
666 register unsigned char status;
667
668 /* holds command read from status or request block */
669 register unsigned char command;
670
671 /* 1 = unclaimed interrupt, 0 = interrupt claimed */
672 int rc = 1;
673
674 int close_signal = 0; /* remember if now closed */
675
676 if (trs->aca == 0) {
677 return(rc);
678 }
679
680 /* do not allow interrupts until we finish and reset the */
681 /* corresponding system block. */
682 MM_OUT(&trs->aca->reset.isrp_h, ~(INT_ENABLE));
683
684 /* Is this interrupt caused by an adapter check? */
685 if ((status = MM_IN(&trs->aca->rw.isrp_l)) & ADAP_CHK_INT) {
686 printf("tr%d: adapter check\n", unit);
687
688 /* Clear this interrupt bit */
689 MM_OUT(&trs->aca->reset.isrp_l, ~(ADAP_CHK_INT));
690 MM_OUT(&trs->aca->set.isrp_h, INT_ENABLE);
691
692 rc = 0; /* Claim responsibility for interrupt */
693 }
694
695 /* Is this interrupt caused by an adapter error or access violation? */
696 else if (MM_IN(&trs->aca->rw.isrp_h) & TCR_INT + ERR_INT + ACCESS_INT) {
697 printf("tr%d: adapter error, ISRPH = %x\n",
698 unit, MM_IN(&trs->aca->rw.isrp_h));
699
700 /* Clear these interrupt bits */
701 MM_OUT(&trs->aca->reset.isrp_h, ~(TCR_INT + ERR_INT + ACCESS_INT));
702 MM_OUT(&trs->aca->set.isrp_h, INT_ENABLE);
703
704 rc = 0; /* Claim responsibility for interrupt */
705
706 }
707
708 /* Is this interrupt caused by normal operation of adapter? */
709 else if (status & SRB_RESP_INT + ASB_FREE_INT
710 + ARB_CMD_INT + SSB_RESP_INT) {
711
712 DEBUGF(tokdebug, printf("tr%d: ISRPL = %x\n", unit, status);)
713
714 /* Process SRB_RESP_INT, ASB_FREE_INT, ARB_CMD_INT
715 & SSB_RESP_INT in that order, ISRP-L Hi to Lo */
716
717 if (status & SRB_RESP_INT) { /* Adapter response in SRB? */
718 register union sr_srb *srb = trs->cb.srb; /* pointer to SRB */
719
720 command = MM_IN(&srb->xmit.command);
721 switch(command) {
722
723 case XMIT_DIR_FRAME: /* Response to xmit request */
724 /* Response not valid? */
725 if (MM_IN(&srb->xmit.retcode) != 0xff)
726 printf("tr%d: SRB error on xmit request =%x\n",
727 unit, MM_IN(&srb->xmit.retcode));
728 else {
729 /* inc count of active xmit cmds */
730 trs->trs_ocount++;
731 DEBUGF(tokdebug,
732 printf("tr%d: trs_ocount = %d\n",
733 unit, trs->trs_ocount);)
734 }
735 break;
736
737 case XMIT_UI_FRM: /* Response to xmit request */
738 if (MM_IN(&srb->xmit.retcode) != 0xff)
739 printf("tr%d: SRB error on xmit request =%x\n",
740 unit, MM_IN(&srb->xmit.retcode));
741 else {
742 /* inc count of active xmit cmds */
743 trs->trs_ocount++;
744 DEBUGF(tokdebug,
745 printf("tr%d: trs_ocount = %d\n",
746 unit, trs->trs_ocount);)
747 }
748 break;
749 case DIR_OPEN_ADAPTER: /* open-adapter-cmd response */
750 /* Open successful? */
751 if (MM_IN(&srb->open_resp.retcode) == 0){
752 trs->trs_if.if_flags |= IFF_UP | IFF_RUNNING;
753 /* Save new ACA ctrl block addresses */
754 trs->cb.ssb = (struct sr_ssb *) (MM_INW(&srb->open_resp.ssb_addr) + trs->sram);
755 trs->cb.arb = (union sr_arb *) (MM_INW(&srb->open_resp.arb_addr) + trs->sram);
756 trs->cb.srb = (union sr_srb *) (MM_INW(&srb->open_resp.srb_addr) + trs->sram);
757 trs->cb.asb = (union sr_asb *) (MM_INW(&srb->open_resp.asb_addr) + trs->sram);
758
759 /* re enable interrupts to the PC so we do not */
760 /* miss the open sap interrupt.... */
761 MM_OUT(&trs->aca->set.isrp_h, INT_ENABLE);
762
763 /* reset the wire fault signal */
764 trs->wire_fault = 0x00;
765 tropensap(unit,EXTENDED_SAP);
766
767 } else {
768 printf("tr%d: Open error = %x\n",
769 unit, MM_IN(&srb->open_resp.retcode));
770 ifp->if_flags &= ~IFF_RUNNING;
771 ifp->if_flags &= ~IFF_UP;
772 timeout(trinit,ifp->if_unit,hz*30);
773 }
774 break;
775
776 case DIR_CLOSE: /* Response to close adapter command */
777 /* close not successful? */
778 if (MM_IN(&srb->close.retcode) != 0)
779 printf("tr%d: close error = %x\n",
780 unit, MM_IN(&srb->close.retcode));
781 else if
782 (MM_IN(&srb->close.retcode) == 0) {
783 close_signal = 1;
784 ifp->if_flags &= ~IFF_RUNNING;
785 ifp->if_flags &= ~IFF_UP;
786 MM_OUT(&trs->aca->reset.isrp_h, ~(INT_ENABLE));
787 untimeout(trtimout, unit);
788 wakeup(&trs->trsleep_event);
789 }
790 break;
791
792 case DIR_INTERRUPT: /* Response to generate-intr cmd */
793 /* generate-interrupt cmd not successful? */
794 if (MM_IN(&srb->intr.retcode) != 0)
795 printf("tr%d: int cmd error =%x\n",
796 unit, MM_IN(&srb->intr.retcode));
797 break;
798
799 case DIR_MOD_OPEN_PARAMS: /* Response to mod params */
800 /* cmd not successful? */
801 if (MM_IN(&srb->mod_params.retcode) != 0)
802 printf("tr%d: mod params cmd err =%x\n",
803 unit, MM_IN(&srb->mod_params.retcode));
804 break;
805
806 case DIR_SET_GRP_ADDR: /* Response to set-grp-addr */
807 case DIR_SET_FUNC_ADDR: /* Response to set-func-addr */
808 /* cmd not successful? */
809 if (MM_IN(&srb->set_addr.retcode) != 0)
810 printf("tr%d: set grp or func addr err =%x\n",
811 unit, MM_IN(&srb->set_addr.retcode));
812 break;
813
814 case OPEN_SAP: /* Response to open sap cmd */
815
816 if (MM_IN(&srb->open_sap.sap_value) == EXTENDED_SAP) {
817 trs->exsap_station = MM_INW(&srb->open_sap.station_id);
818 }
819 printf("tr%d: Token Ring opened\n", unit);
820 untimeout(trtimout, unit);
821 wakeup(&trs->trsleep_event);
822 break;
823 case CLOSE_SAP: /* Response to close sap cmd */
824 break;
825 case DIR_READ_LOG: /* Response to read log */
826 /* cmd not successful? */
827 if (MM_IN(&srb->log.retcode) != 0)
828 printf("tr%d: read error log cmd err =%x\n",
829 unit, MM_IN(&srb->log.retcode));
830 DEBUGF(tokdebug, {
831 printf("tr%d: ERROR LOG:\n",unit);
832 printf("tr%d: Line=%d, Internal=%d, Burst=%d\n",unit,(MM_IN(&srb->log.data[0])),(MM_IN(&srb->log.data[1])),(MM_IN(&srb->log.data[2])));
833 printf("tr%d: A/C=%d, Abort=%d, Lost frames=%d\n",unit,(MM_IN(&srb->log.data[3])),(MM_IN(&srb->log.data[4])),(MM_IN(&srb->log.data[6])));
834 printf("tr%d: Receive congestion=%d, Frame copied=%d, Frequency=%d\n",unit,(MM_IN(&srb->log.data[7])),(MM_IN(&srb->log.data[8])),(MM_IN(&srb->log.data[9])));
835 printf("tr%d: Token=%d\n",unit,(MM_IN(&srb->log.data[10])));
836 };)
837 trs->srbfree = 0; /* done with SRB */
838 break;
839 default:
840 printf("tr%d: bad SRB command encountered\n",
841 unit);
842 break;
843 }
844 /* clear the SRB-response interrupt bit */
845 MM_OUT(&trs->aca->reset.isrp_l, ~(SRB_RESP_INT));
846
847 /* Try to start output? */
848 if (command == OPEN_SAP &&
849 MM_IN(&srb->open_resp.retcode) == 0) {
850
851 trs->srbfree = 0;
852 /* if output not active */
853 if (trs->trs_ocount == 0 &&
854 /* and data on send queue */
855 ! IF_EMPTYQUEUE(trs->trs_if.if_snd))
856 /* Continue output from queue */
857 trstart(trs);
858 }
859 }
860
861 if (status & ASB_FREE_INT){ /* Is Adapter Status Block Free? */
862 register union sr_asb *asb = trs->cb.asb; /* pointer to ASB */
863
864 switch (command = MM_IN(&asb->rec_resp.command)) {
865 case REC_DATA: /* Receive */
866 /* Response not valid? */
867 if (MM_IN(&asb->rec_resp.retcode) != 0xff)
868 printf("tr%d: ASB bad receive response =%x\n",
869 unit, MM_IN(&asb->rec_resp.retcode));
870 break;
871
872 case XMIT_DIR_FRAME: /* Transmit */
873 /* Response not valid? */
874 if (MM_IN(&asb->xmit_resp.retcode) != 0xff)
875 printf("tr%d: ASB response err on xmit =%x\n",
876 unit, MM_IN(&asb->xmit_resp.retcode));
877 break;
878
879 case XMIT_UI_FRM: /* Transmit */
880 /* Response not valid? */
881 if (MM_IN(&asb->xmit_resp.retcode) != 0xff)
882 printf("tr%d: ASB response err on xmit =%x\n",
883 unit, MM_IN(&asb->xmit_resp.retcode));
884 break;
885
886 default:
887 printf("tr%d: Invalid command in ASB =%x\n",
888 unit, command);
889 break;
890 }
891
892 /* Clear this interrupt bit */
893 MM_OUT(&trs->aca->reset.isrp_l, ~(ASB_FREE_INT));
894 }
895
896 if (status & ARB_CMD_INT) { /* Command for PC to process? */
897 switch (command = MM_IN(&trs->cb.arb->stat.command)) {
898 case DLC_STATUS: /* DLC status change */
899 DEBUGF(tokdebug, printf("tr%d: ARB new DLC status = 0x%x\n",
900 unit, MM_INW(&trs->cb.arb->dlc.status));)
901 break;
902
903 case REC_DATA: /* Adapter has data for PC */
904 /* Call receive interrupt handler */
905 trrint(unit);
906 break;
907
908 case RING_STAT_CHANGE: /* Ring status change */
909 if (MM_INW(&trs->cb.arb->stat.ring_status) & (SIGNAL_LOSS + LOBE_FAULT)){
910 printf("tr%d: SIGNAL LOSS/LOBE FAULT\n",
911 unit);
912
913 ifp->if_flags &= ~IFF_RUNNING;
914 ifp->if_flags &= ~IFF_UP;
915 trs->wire_fault = 0x01;
916 timeout(trinit,ifp->if_unit,hz*30);
917 } else {
918 DEBUGF(tokdebug,
919 if (MM_INW(&trs->cb.arb->stat.ring_status) & ~(SOFT_ERR))
920 printf("tr%d: ARB new ring status = 0x%x\n",
921 unit, MM_INW(&trs->cb.arb->stat.ring_status));)
922 }
923 if (MM_INW(&trs->cb.arb->stat.ring_status) & LOG_OFLOW){
924 trs->srbfree = 1; /* using SRB */
925 MM_OUT(&trs->cb.srb->log.command, DIR_READ_LOG);
926
927 /* read & reset err log cmnd in SRB */
928 /* enable PC ints so we get response */
929
930 MM_OUT(&trs->aca->set.isrp_h, INT_ENABLE);
931 MM_OUT(&trs->aca->set.isra_l, CMD_IN_SRB);
932 DEBUGF(tokdebug, printf("tr%d: read adapter error log\n", unit);)
933 }
934 break;
935
936 case XMIT_DATA_REQ: /* Adapter wants data to transmit */
937 /* Call transmit interrupt handler */
938 trxint(unit);
939
940
941 break;
942
943 default:
944 printf("tr%d: Invalid command in ARB =%x\n",
945 unit, command);
946 break;
947 }
948
949 /* Clear this interrupt bit */
950 MM_OUT(&trs->aca->reset.isrp_l, ~(ARB_CMD_INT));
951
952 /* Tell adapter that ARB is now free */
953 MM_OUT(&trs->aca->set.isra_l, ARB_FREE);
954 }
955
956
957 if (status & SSB_RESP_INT){ /* SSB response to SRB command? */
958
959 /* pointer to SSB */
960 register struct sr_ssb *ssb = trs->cb.ssb;
961 switch(MM_IN(&ssb->command)) {
962
963 case XMIT_DIR_FRAME: /* SSB response to SRB xmit cmd */
964 if (trs->trs_ocount <= 0)
965 printf("tr%d: bad active-xmit count\n",
966 unit);
967
968 /* collect status on last packet */
969 if (MM_IN(&ssb->retcode) != 0) { /* error on xmit? */
970 /* increment output error count */
971 trs->trs_if.if_oerrors++;
972 DEBUGF(tokdebug,
973 {printf("trint: xmit err retcode = %x ",
974 MM_IN(&ssb->retcode));
975 printf(" xmit_error = 0x%x\n",
976 MM_IN(&ssb->xmit_err));})
977 } else
978 /* increment output packet count */
979 trs->trs_if.if_opackets++;
980
981 /* decrement active output count */
982 trs->trs_ocount--;
983
984 /* if data on send queue */
985 if (! IF_EMPTYQUEUE(trs->trs_if.if_snd) &&
986 /* and SRB is free */
987 trs->srbfree == 0)
988 trstart(trs);
989 break;
990
991 case XMIT_UI_FRM: /* SSB response to SRB xmit cmd */
992 trs->srbfree = 0;
993 if (trs->trs_ocount <= 0)
994 printf("tr%d: bad active-xmit count\n",
995 unit);
996
997 /* collect status on last packet */
998 if (MM_IN(&ssb->retcode) != 0) { /* error on xmit? */
999 /* increment output error count */
1000 trs->trs_if.if_oerrors++;
1001 DEBUGF(tokdebug,
1002 {printf("trint: xmit err retcode = %x ",
1003 MM_IN(&ssb->retcode));
1004 printf(" xmit_error = 0x%x\n",
1005 MM_IN(&ssb->xmit_err));})
1006 } else
1007 /* increment output packet count */
1008 trs->trs_if.if_opackets++;
1009
1010 /* decrement active output count */
1011 trs->trs_ocount--;
1012
1013 /* if data on send queue */
1014 if (! IF_EMPTYQUEUE(trs->trs_if.if_snd) &&
1015 /* and SRB is free */
1016 trs->srbfree == 0) {
1017 trstart(trs);
1018 }
1019 break;
1020
1021 case XMIT_XID_CMD:
1022 printf("trint: xmit XID return code = 0x%x\n",
1023 MM_IN(&ssb->retcode));
1024 break;
1025
1026 default:
1027 printf("tr%d: SSB error, invalid command =%x\n",
1028 unit, MM_IN(&ssb->command));
1029 }
1030 /* clear this interrupt bit */
1031 MM_OUT(&trs->aca->reset.isrp_l, ~(SSB_RESP_INT));
1032
1033 /* tell adapter that SSB is available */
1034 MM_OUT(&trs->aca->set.isra_l, SSB_FREE);
1035 }
1036 rc = 0; /* Claim responsibility for interrupt */
1037 }
1038 DEBUGF(tokdebug, printf("tr%d: rc=%d\n", unit, rc);)
1039 if (!close_signal) {
1040 MM_OUT(&trs->aca->set.isrp_h, INT_ENABLE);
1041 }
1042 return(rc);
1043 }
1044
1045
1046 /*
1047 * U-B receive interrupt.
1048 *
1049 * in the original version, this routine had three tasks:
1050 *
1051 * 1. move the data into the receive buffer and set up various pointers
1052 * in the tr_softc struct
1053 * 2. switch on the type field for ip and arp, dropping all else
1054 * 3. resetting the adaptor status block info (asb) and updating the
1055 * tr_softc struct
1056 * determine lan message type, pull packet off interface and
1057 * pass to an appropriate higher-level routine
1058 *
1059 */
1060 trrint(unit)
1061 int unit;
1062 {
1063 register struct tr_softc *trs = &tr_softc[unit];
1064 register union sr_arb *arb = trs->cb.arb;
1065 register union sr_asb *asb = trs->cb.asb;
1066 register struct rbcb *rbc = &trs->rbc;
1067 register int totlen;
1068 int i;
1069 register int hsize;
1070 unsigned char type;
1071 unsigned short etype;
1072 struct ifqueue *inq;
1073 unsigned char *llcptr;
1074 register struct tr_head *trhead;
1075 unsigned char trheadbuf[64];
1076 #ifndef MACH_KERNEL
1077 register struct mbuf *m;
1078 struct mbuf *trget();
1079 #else
1080 ipc_kmsg_t new_kmsg;
1081 struct tr_head *thp;
1082 struct packet_header *pkt;
1083 #endif
1084
1085 DEBUGF(tokdebug,
1086 printf("trrint: arb.command = %x, arb.station_id= %x\n",
1087 MM_IN(&arb->rec.command), MM_INW(&arb->rec.station_id));)
1088 DEBUGF(tokdebug,
1089 printf("arb.buf_addr = %x, arb.lan_hdr_len = %x\n",
1090 MM_INW(&arb->rec.buf_addr), MM_IN(&arb->rec.lan_hdr_len));)
1091 DEBUGF(tokdebug,
1092 printf("arb.dlc_hdr_len = %d, arb.frame_len = %d\n",
1093 MM_IN(&arb->rec.dlc_hdr_len), MM_INW(&arb->rec.frame_len));)
1094 DEBUGF(tokdebug,
1095 printf("arb.msg_type = %x\n", MM_IN(&arb->rec.msg_type));)
1096 /*
1097 * copy the offset in RAM of the first receive buffer from the
1098 * receive-data block of the adapter request block associated
1099 * with the unit's softc struct into the receive control block.
1100 */
1101 rbc->rbufp = (struct rec_buf *)(MM_INW(&arb->rec.buf_addr) + trs->sram);
1102
1103 /*
1104 * copy the pointer to data in first receive buffer
1105 */
1106 rbc->rbuf_datap = rbc->rbufp->data;
1107 /*
1108 * the token-ring header is viewed as two header structs: the physical
1109 * header (aka TR header) with access, frame, dest, src, and routing
1110 * information, and the logical link control header (aka LLC header)
1111 * with dsap, ssap, llc, proto and type fields.
1112 *
1113 * rfc1042 requires support for unnumbered information (UI) commands,
1114 * but does not specify a required semantic, so we'll discard them.
1115 *
1116 * set llcptr to point past the TR physical header (including
1117 * routing information), and also skip the dsap and ssap fields
1118 * of the LLC frame, if UI, chuckit.
1119 */
1120 llcptr = (unsigned char *)(
1121 (int) rbc->rbuf_datap + MM_IN(&arb->rec.lan_hdr_len))
1122 + SKIP_DSAP_SSAP;
1123 if ((type = MM_IN(llcptr)) !=UI_CMD) {
1124 DEBUGF(tokdebug,
1125 printf("trrint: non-UI frame received, type = %x\n",type);)
1126 goto chuckit;
1127 }
1128 /*
1129 * backup to the beginning of the LLC header and get the type field
1130 */
1131 llcptr = (unsigned char *)(
1132 (int)rbc->rbuf_datap + MM_IN(&arb->rec.lan_hdr_len));
1133 etype = MM_INW(&((struct tr_llc *)llcptr)->ethertype);
1134 /*
1135 * if there is a second receive buffer, set up the next pointer
1136 */
1137 if (MM_INW(&rbc->rbufp->buf_pointer))
1138 rbc->rbufp_next =
1139 (struct rec_buf *)(MM_INW(&rbc->rbufp->buf_pointer)
1140 + trs->sram - 2);
1141 else
1142 rbc->rbufp_next = 0; /* we're finished */
1143 /*
1144 * get size of lan and dlc headers, add 5 for the SNAP LENGTH
1145 */
1146 hsize = MM_IN(&arb->rec.lan_hdr_len)
1147 + MM_IN(&arb->rec.dlc_hdr_len)
1148 + SNAP_LENGTH;
1149 /*
1150 * get total length of data in frame
1151 */
1152 totlen = MM_INW(&arb->rec.frame_len) - hsize;
1153
1154 DEBUGF(tokdebug & 2,{
1155 int i;
1156 printf("tr%d: trrint - physical header\n", unit);
1157 for (i=0; i < hsize; i++)
1158 printf("0x%x ",MM_IN((rbc->rbuf_datap + i)));
1159 printf("\n");
1160 })
1161 /*
1162 * read in the tr header and store it in trheadbuf
1163 */
1164 for (i=0; i < hsize; i++)
1165 trheadbuf[i] = MM_IN(rbc->rbuf_datap + i);
1166 /*
1167 * set trhead to point to lan header for tr_arpinput
1168 */
1169 trhead = (struct tr_head *)trheadbuf;
1170 /*
1171 * adjust data pointer to skip headers not needed
1172 */
1173 rbc->rbuf_datap += hsize;
1174 /*
1175 * calculate length of data in 1st receive buffer
1176 */
1177 rbc->data_len = MM_INW(&rbc->rbufp->buf_len) - hsize;
1178 /*
1179 * At this point we move the packet from the adapter to a chain
1180 * of mbufs
1181 */
1182 #ifdef MACH_KERNEL
1183 new_kmsg = net_kmsg_get();
1184
1185 if (new_kmsg == IKM_NULL) {
1186 DEBUGF(tokdebug, printf("tr%d: trrint: net_kmsg_get failed\n",
1187 unit));
1188 goto chuckit;
1189 }
1190
1191 thp = (struct tr_head *) (&net_kmsg(new_kmsg)->header[0]);
1192 pkt = (struct packet_header *)(&net_kmsg(new_kmsg)->packet[0]);
1193
1194 /*
1195 * Get header.
1196 */
1197 *thp = *trhead;
1198
1199 /*
1200 * Get packet body.
1201 */
1202 trbcopy(trs, (char *)(pkt + 1), totlen);
1203
1204 pkt->type = htons(etype);
1205 pkt->length = totlen + sizeof(struct packet_header);
1206 /*
1207 * Send the packet through the input filters.
1208 */
1209 DEBUGF(tokdebug&2, printf("tr%d: trrint: calling net_packet; len=%d\n",
1210 unit, pkt->length);)
1211 net_packet(&trs->trs_if, new_kmsg, pkt->length, TRUE);
1212 /* !tr_broadcast(new_kmsg) XXX */
1213
1214 #else MACH_KERNEL
1215 /*
1216 * this is where we _should_ generalize packet decoding ala
1217 * token_input()
1218 */
1219 m = trget(trs, totlen, &trs->trs_if);
1220 if (m == 0) /* no mbuf chain returned? */
1221 goto chuckit;
1222
1223 switch (etype) {
1224 #if INET
1225 case ETHERTYPE_IP:
1226 {
1227 int s;
1228 schednetisr(NETISR_IP);
1229 s = splimp();
1230 inq = &ipintrq;
1231 if (IF_QFULL(inq)) {
1232 DEBUGF(tokdebug & 0x2, printf(" qfull\n");)
1233 IF_DROP(inq);
1234 m_freem(m);
1235 } else {
1236 IF_ENQUEUE(inq, m);
1237 DEBUGF(tokdebug & 0x2, printf(" queued\n");)
1238 }
1239 splx(s);
1240 break;
1241 }
1242
1243 case ETHERTYPE_ARP:
1244 tr_arpinput(&trs->trs_ac, m, trhead); /* arpinput frees m */
1245 DEBUGF(tokdebug & 0x2, printf(" arpinput\n");)
1246 break;
1247 #endif
1248 default:
1249 DEBUGF(tokdebug, printf("trrint: unknown packet type %x\n",etype);)
1250 m_freem(m);
1251 break;
1252 }
1253 /*
1254 * end of future token_input() code
1255 */
1256 #endif MACH_KERNEL
1257 trs->trs_if.if_ipackets++; /* increment input packet count */
1258
1259 if (MM_IN(&asb->rec_resp.retcode) != 0xff)
1260 printf("trrint: ASB IS NOT FREE!!!\n");
1261 /*
1262 * load receive response into ASB
1263 */
1264 MM_OUT(&asb->rec_resp.command, REC_DATA);
1265 MM_OUTW(&asb->rec_resp.station_id, MM_INW(&arb->rec.station_id));
1266 MM_OUTW(&asb->rec_resp.rec_buf_addr, MM_INW(&arb->rec.buf_addr));
1267 /*
1268 * indicate successful receive
1269 */
1270 MM_OUT(&asb->rec_resp.retcode, 0);
1271 /*
1272 * tell adapter response in ASB
1273 */
1274 MM_OUT(&trs->aca->set.isra_l, RESP_IN_ASB);
1275
1276 return;
1277 chuckit:
1278
1279 trs->trs_if.if_ierrors++; /* increment input error count */
1280
1281 if (MM_IN(&asb->rec_resp.retcode) != 0xff)
1282 printf("trrint: ASB IS NOT FREE!!!\n");
1283
1284 DEBUGF(tokdebug, printf("trrint: packet dropped\n");)
1285 /*
1286 * load receive response into ASB
1287 */
1288 MM_OUT(&asb->rec_resp.command, REC_DATA);
1289 MM_OUTW(&asb->rec_resp.station_id, MM_INW(&arb->rec.station_id));
1290 MM_OUTW(&asb->rec_resp.rec_buf_addr, MM_INW(&arb->rec.buf_addr));
1291 /*
1292 * tell adapter data lost, no mbufs
1293 */
1294 MM_OUT(&asb->rec_resp.retcode, 0x20);
1295 /*
1296 * tell adapter response in ASB
1297 */
1298 MM_OUT(&trs->aca->set.isra_l, RESP_IN_ASB);
1299 }
1300
1301
1302
1303
1304
1305 /*
1306 * Interrupt handler for "adapter requires data to transmit" interrupt
1307 */
1308 trxint(unit)
1309 int unit;
1310 {
1311 register struct tr_softc *trs = &tr_softc[unit];
1312 register union sr_arb *arb = trs->cb.arb; /* pointer to ARB */
1313 register union sr_asb *asb = trs->cb.asb; /* pointer to ASB */
1314 register unsigned char *dhb; /* pointer to DHB */
1315 #ifdef MACH_KERNEL
1316 io_req_t m0;
1317 #else MACH_KERNEL
1318 register struct mbuf *m0; /* pointer to top of mbuf chain */
1319 #endif MACH_KERNEL
1320 register unsigned short size = 0;
1321 int i;
1322 unsigned char ri_present_byt;
1323 u_short rcf = 0;
1324 int ri_len;
1325
1326 DEBUGF(tokdebug, printf("tr%d: trxint\n", unit);)
1327 if (MM_IN(&asb->xmit_resp.retcode) != 0xff)
1328 printf("trxint: ASB IS NOT FREE!!!\n");
1329
1330 /* load parameters into ASB */
1331 MM_OUT(&asb->xmit_resp.command, XMIT_UI_FRM);
1332 MM_OUT(&asb->xmit_resp.cmd_corr, MM_IN(&arb->xmit.cmd_corr));
1333 MM_OUTW(&asb->xmit_resp.station_id, MM_INW(&arb->xmit.station_id));
1334 MM_OUT(&asb->xmit_resp.retcode, 0);
1335 MM_OUT(&asb->xmit_resp.rsap_value, EXTENDED_SAP);
1336
1337 if (MM_IN(&trs->cb.srb->xmit.command) == 0x0e) {
1338 MM_OUT(&asb->xmit_resp.command, 0x0e); /* command is TRANSMIT.XID.CMD */
1339 MM_OUTW(&asb->xmit_resp.frame_len, 0x11); /* length of frame */
1340 MM_OUT(&asb->xmit_resp.header_len, 0x0e); /* length of TR header */
1341 MM_OUT(&asb->xmit_resp.rsap_value, EXTENDED_SAP); /* destination SAP */
1342 /* get address of data holding buffer */
1343 dhb = (unsigned char *)(MM_INW(&arb->xmit.dhb_addr) + trs->sram);
1344
1345 /* load dhb */
1346 MM_OUT(&dhb[0], AC);
1347 MM_OUT(&dhb[1], FC);
1348 /* load destination and source addresses */
1349 for (i=0; i < TR_ADDR_LEN; i++) {
1350 MM_OUT(&dhb[2 + i], 0xff);
1351 MM_OUT(&dhb[8 + i], 0x00);
1352 }
1353 } else if (MM_IN(&trs->cb.srb->xmit.command) == 0x11) {
1354 MM_OUT(&asb->xmit_resp.command, 0x11); /* command is TRANSMIT.TEST.CMD */
1355 MM_OUTW(&asb->xmit_resp.frame_len, 0x11); /* length of frame */
1356 MM_OUT(&asb->xmit_resp.header_len, 0x0e); /* length of TR header */
1357 MM_OUT(&asb->xmit_resp.rsap_value, EXTENDED_SAP); /* destination SAP */
1358 /* get address of data holding buffer */
1359 dhb = (unsigned char *)(MM_INW(&arb->xmit.dhb_addr) + trs->sram);
1360
1361 /* load dhb */
1362 MM_OUT(&dhb[0], AC);
1363 MM_OUT(&dhb[1], FC);
1364 /* load destination and source addresses */
1365 for (i=0; i < TR_ADDR_LEN; i++) {
1366 MM_OUT(&dhb[2 + i], 0xff);
1367 MM_OUT(&dhb[8 + i], 0x00);
1368 }
1369 } else {
1370
1371 /* if data in queue, copy mbuf chain to DHB */
1372 if (! IF_EMPTYQUEUE(trs->trs_if.if_snd)) {
1373 /* compute address of DHB */
1374 dhb = (unsigned char *)(MM_INW(&arb->xmit.dhb_addr) + trs->sram);
1375
1376 /* pull packet off interface send queue, fill DHB */
1377 IF_DEQUEUE(&trs->trs_if.if_snd, m0);
1378 #ifdef MACH_KERNEL
1379 size = m0->io_count;
1380 DEBUGF(tokdebug, printf("tr%d: trxint: filling DHB\n", unit);)
1381 bcopy(m0->io_data, dhb+KVBASE, size);
1382 iodone(m0);
1383 #else MACH_KERNEL
1384 #ifdef notdef
1385 for (m = m0; m; m = m->m_next) {
1386 register unsigned len = m->m_len;
1387
1388 for (i = 0; i < len; i++)
1389 MM_OUT((dhb +i), (mtod(m, char *))[i]);
1390
1391 dhb += len;
1392 size += len; /* measure size of data */
1393 }
1394 #else
1395 size = trmbcopy(dhb, m0);
1396 #endif
1397
1398 m_freem(m0); /* free mbuf chain */
1399 #endif MACH_KERNEL
1400
1401 DEBUGF(tokdebug & 2,{
1402 int i;
1403 unsigned char *dhbp = (unsigned char *)(MM_INW(&arb->xmit.dhb_addr) + trs->sram);
1404 printf("tr%d: trxint - contents of xmit buffer\n", unit);
1405 for (i=0; i < size; i++)
1406 printf("0x%x ",MM_IN(&dhbp[i]));
1407 }
1408 )
1409
1410 /* check to see if there is routing info... */
1411 /* if yes, figure out length of the routing */
1412 /* info and update the ASB. Otherwise set */
1413 /* the ASB length to 14 */
1414
1415 /* compute address of DHB */
1416 dhb = (unsigned char *)(MM_INW(&arb->xmit.dhb_addr) + trs->sram);
1417
1418 ri_present_byt = MM_IN(&dhb[SOURCE_ADDR_BYT0]);
1419
1420
1421 if (ri_present_byt & TR_RI_PRESENT) {
1422 rcf = MM_IN(&dhb[RCF_BYT0]) << 8;
1423 ri_len = (rcf & TR_RCF_LEN_MASK) >> 8;
1424 MM_OUT(&asb->xmit_resp.header_len,
1425 (HDR_LNGTH_NOROUTE + ri_len));
1426 } else
1427 MM_OUT(&asb->xmit_resp.header_len, HDR_LNGTH_NOROUTE);
1428
1429 /* set size of transmission frame in ASB */
1430 MM_OUTW(&asb->xmit_resp.frame_len, size);
1431
1432 } else {
1433 printf("tr%d: unexpected empty mbuf send queue\n", unit);
1434
1435 /* set size of transmission frame in ASB to zero */
1436 MM_OUTW(&asb->xmit_resp.frame_len, 0);
1437 }
1438 }
1439 /* tell adapter that there is a response in the ASB */
1440 MM_OUT(&trs->aca->set.isra_l, RESP_IN_ASB);
1441 }
1442
1443
1444 #ifdef MACH_KERNEL
1445 /*ARGSUSED*/
1446 tropen(dev, flag)
1447 dev_t dev;
1448 int flag;
1449 {
1450 register int unit = minor(dev);
1451
1452 if (unit < 0 || unit >= NTR || !tr_softc[unit].alive)
1453 return (ENXIO);
1454
1455 DEBUGF(tokdebug, printf("tr%d: tropen\n", unit);)
1456 tr_softc[unit].trs_if.if_flags |= IFF_UP;
1457 trinit(unit);
1458
1459 /* don't return until it's really open. */
1460 trsleep(unit);
1461
1462 DEBUGF(tokdebug, printf("tr%d: tropen done.\n", unit);)
1463 return (0);
1464 }
1465
1466 trnetstart(unit)
1467 {
1468 register struct tr_softc *trs = &tr_softc[unit];
1469
1470 if (trs->srbfree == 0 && trs->trs_ocount == 0)
1471 return(trstart(trs));
1472
1473 DEBUGF(tokdebug, printf("tr%d: trnetstart: output already active\n",
1474 trs->trs_if.if_unit);)
1475 }
1476
1477 troutput(dev, ior)
1478 dev_t dev;
1479 io_req_t ior;
1480 {
1481 register int unit = minor(dev);
1482
1483 if (unit < 0 || unit >= NTR || !tr_softc[unit].alive)
1484 return (ENXIO);
1485
1486 DEBUGF(tokdebug, printf("tr%d: troutput request\n", unit);)
1487 return (net_write(&tr_softc[unit].trs_if, trnetstart, ior));
1488 }
1489
1490 trsetinput(dev, receive_port, priority, filter, filter_count)
1491 dev_t dev;
1492 mach_port_t receive_port;
1493 int priority;
1494 filter_t filter[];
1495 unsigned int filter_count;
1496 {
1497 register int unit = minor(dev);
1498
1499 if (unit < 0 || unit >= NTR || !tr_softc[unit].alive)
1500 return (ENXIO);
1501
1502 DEBUGF(tokdebug, printf("tr%d: trsetinput\n", unit);)
1503 return (net_set_filter(&tr_softc[unit].trs_if,
1504 receive_port, priority,
1505 filter, filter_count));
1506 }
1507
1508 trgetstat(dev, flavor, status, count)
1509 dev_t dev;
1510 int flavor;
1511 dev_status_t status; /* pointer to OUT array */
1512 unsigned int *count; /* out */
1513 {
1514 register int unit = minor(dev);
1515
1516 if (unit < 0 || unit >= NTR || !tr_softc[unit].alive)
1517 return (ENXIO);
1518
1519 DEBUGF(tokdebug, printf("tr%d: trgetstat\n", unit);)
1520 return (net_getstat(&tr_softc[unit].trs_if, flavor, status, count));
1521 }
1522
1523 trsetstat(dev, flavor, status, count)
1524 dev_t dev;
1525 int flavor;
1526 dev_status_t status;
1527 unsigned int count;
1528 {
1529 register int unit = minor(dev);
1530 register struct tr_softc *sp;
1531
1532 if (unit < 0 || unit >= NTR || !tr_softc[unit].alive)
1533 return (ENXIO);
1534
1535 DEBUGF(tokdebug, printf("tr%d: trsetstat\n", unit);)
1536 sp = &tr_softc[unit];
1537
1538 switch (flavor) {
1539 case NET_STATUS:
1540 {
1541 #ifdef notdef
1542 /*
1543 * All we can change are flags, and not many of those.
1544 */
1545 register struct net_status *ns = (struct net_status *)status;
1546 int mode = 0;
1547
1548 if (count < NET_STATUS_COUNT)
1549 return (D_INVALID_OPERATION);
1550
1551 if (ns->flags & IFF_ALLMULTI)
1552 mode |= MOD_ENAL;
1553 if (ns->flags & IFF_PROMISC)
1554 mode |= MOD_PROM;
1555
1556 /*
1557 * Force a complete reset if the receive mode changes
1558 * so that these take effect immediately.
1559 */
1560 if (sp->mode != mode) {
1561 sp->mode = mode;
1562 if (sp->flags & DSF_RUNNING) {
1563 sp->flags &= ~(DSF_LOCK|DSF_RUNNING);
1564 trinit(unit);
1565 }
1566 }
1567 break;
1568 #endif
1569 }
1570
1571 default:
1572 return (D_INVALID_OPERATION);
1573 }
1574 return (D_SUCCESS);
1575
1576 }
1577
1578 #else MACH_KERNEL
1579
1580 /*
1581 * copy out the packet byte-by-byte in resonably optimal fashion
1582 */
1583 trmbcopy(dhb, m0)
1584 unsigned char *dhb;
1585 struct mbuf *m0;
1586 {
1587 unsigned char *addr = dhb + KVBASE; /* make a pointer */
1588 int size = 0;
1589 struct mbuf *m;
1590
1591 for (m = m0; m; m = m->m_next) {
1592 int len = m->m_len;
1593 char *ptr = mtod(m, char *);
1594 int i;
1595
1596 bcopy(ptr,addr,len);
1597 size += len; /* measure size of data */
1598 addr += len;
1599 }
1600 pc_copy_out += size;
1601 return(size);
1602 }
1603
1604 /*
1605 * Token-ring output routine.
1606 * Encapsulate a packet of type family for the local net.
1607 * put packet on send queue.
1608 *
1609 * changes:
1610 * m->m_off is gone, but it wasn't used anyway!
1611 */
1612 troutput(ifp, m0, dst)
1613 register struct ifnet *ifp; /* network interface pointer */
1614 register struct mbuf *m0; /* pointer to 1st mbuf in chain */
1615 struct sockaddr *dst; /* pointer to destination socket */
1616
1617 {
1618 int s;
1619 int error;
1620 register int i;
1621 unsigned char trdst[TR_ADDR_LEN]; /* token-ring dest hardware addr */
1622 struct in_addr idst; /* internet destination address */
1623 register struct tr_softc *trs = &tr_softc[ifp->if_unit];
1624 register struct mbuf *m;
1625 register struct ether_header *eh; /* pointer to ethernet header */
1626 register struct tr_head *trhead; /* pointer to token-ring header */
1627 register struct tr_llc *trllc; /* pointer to token-ring llc */
1628 struct mbuf *m_get(); /* function returning pointer to mbuf */
1629 int usetrailers; /* for 4.3 -- jer */
1630 u_short rcf = 0; /* routing control field */
1631 u_short rseg[TR_MAX_BRIDGE]; /* routing registers */
1632 int ri_len; /* route info length */
1633 unsigned short ethtype;
1634
1635 DEBUGF(tokdebug, printf("tr output request\n");)
1636
1637 rcf = 0;
1638
1639 if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)){
1640 error = ENETDOWN;
1641 goto bad;
1642 }
1643
1644 /* add token-ring physical header. allocate another mbuf for
1645 * this purpose.
1646 */
1647 m = m_get(M_DONTWAIT, MT_HEADER); /* allocate an mbuf */
1648 if (m == 0) { /* no mbuf allocated? */
1649 error = ENOBUFS;
1650 goto bad;
1651 }
1652
1653 switch (dst->sa_family) {
1654
1655 #if INET
1656 case AF_INET:
1657 /* get internet destination address */
1658 idst = ((struct sockaddr_in *)dst)->sin_addr;
1659
1660 /* get token-ring destination hardware address */
1661 if (!tr_arpresolve(&trs->trs_ac, m0, &idst, trdst, &usetrailers,&rcf, rseg)) return(0);
1662
1663 ethtype = ETHERTYPE_IP;
1664 if (!bcmp((caddr_t)trdst, (caddr_t)etherbroadcastaddr, sizeof(trdst))) {
1665
1666 rcf = (((sizeof(rcf)) << 8) & TR_RCF_LEN_MASK)
1667 | TR_RCF_FRAME2K
1668 | TR_RCF_BROADCAST;
1669 }
1670 break;
1671 #endif
1672 case AF_UNSPEC:
1673 /* get pointer to ethernet header */
1674 eh = (struct ether_header *)dst->sa_data;
1675 for (i=0; i < sizeof(trdst); i++)
1676 trdst[i] = *((unsigned char *)eh->ether_dhost + i);
1677
1678 ethtype = ETHERTYPE_ARP;
1679 rcf = (((sizeof(rcf)) << 8) & TR_RCF_LEN_MASK)
1680 | TR_RCF_FRAME2K
1681 | TR_RCF_BROADCAST;
1682 break;
1683 default:
1684 printf("tr%d: can't handle af%d\n",
1685 ifp->if_unit, dst->sa_family);
1686 error = EAFNOSUPPORT;
1687 goto bad;
1688 break;
1689 }
1690
1691 m->m_next = m0; /* put new mbuf on top of chain */
1692 /* m->m_off = MMINOFF; initialize data offset */
1693 trhead = mtod(m, struct tr_head *); /* get pointer to header in mbuf */
1694 trhead->ac = AC; /* access control field */
1695 trhead->fc = FC; /* frame control field */
1696
1697 /* load source address with zeros, adapter will fill in address */
1698 for (i=0; i < TR_ADDR_LEN; i++)
1699 trhead->saddr[i] = 0;
1700
1701
1702 if (rcf) {
1703 DEBUGF(tokdebug & 0x40000,
1704 printf("rcf present\n");
1705 )
1706 trhead->saddr[0] |= TR_RI_PRESENT;
1707 trhead -> rcf = htons(rcf);
1708 ri_len = (rcf & TR_RCF_LEN_MASK) >> 8;
1709 bcopy ((caddr_t)rseg, trhead->rseg, (ri_len - sizeof(rcf)));
1710 } else ri_len = 0;
1711
1712 /* set up pointer to llc structure (14 past trhead) */
1713 trllc = (struct tr_llc *)((int)trhead + HDR_LNGTH_NOROUTE + ri_len);
1714 trllc->protid[0] = 0x00;
1715 trllc->protid[1] = 0x00;
1716 trllc->protid[2] = 0x00;
1717 trllc->dsap = trllc->ssap = EXTENDED_SAP; /* set source and dest SAPs */
1718 trllc->llc = UI_CMD; /* LLC control byte */
1719 trllc->ethertype = htons(ethtype);
1720
1721 /* load destination address */
1722 for (i=0; i < TR_ADDR_LEN; i++)
1723 trhead->daddr[i] = trdst[i];
1724 DEBUGF(tokdebug, {printf("troutput: destination address = ");
1725 trprinttraddr(trhead->daddr);
1726 printf("\n");}
1727 )
1728 /* make room for token-ring header */
1729 m->m_len = HDR_LNGTH_NOROUTE + sizeof(struct tr_llc) + ri_len;
1730 /*
1731 * queue packet for transmission, if output not active then start it
1732 */
1733 s = splimp();
1734 if (IF_QFULL(&ifp->if_snd)) {
1735 IF_DROP(&ifp->if_snd);
1736 error = ENOBUFS;
1737 goto qfull;
1738 }
1739 IF_ENQUEUE(&ifp->if_snd, m); /* put packet on send queue */
1740 /* if SRB is free and output not active */
1741 if (trs->srbfree == 0 && trs->trs_ocount == 0) {
1742 trstart(trs); /* start output */
1743 }
1744 splx(s);
1745 return(0);
1746
1747 qfull:
1748 m0 = m;
1749 splx(s);
1750 DEBUGF(tokdebug, printf("tr%d: IP output queue full\n",ifp->if_unit);)
1751 bad:
1752 m_freem(m0); /* free mbuf chain */
1753 return(error);
1754 }
1755
1756 #ifdef OSF
1757 /*
1758 * Pull read data off an interface.
1759 * Len is length of data, with local net header stripped.
1760 * Off is non-zero if a trailer protocol was used, and
1761 * gives the offset of the trailer information.
1762 * We copy the trailer information and then all the normal
1763 * data into mbufs.
1764 *
1765 * called from trrint - receive interupt routine
1766 */
1767
1768 struct mbuf *
1769 trget(trs, totlen, ifp)
1770 register struct tr_softc *trs;
1771 register int totlen;
1772 struct ifnet *ifp;
1773 {
1774 #define HLEN sizeof(struct token_header)
1775 register int len;
1776 register struct mbuf *m;
1777 struct mbuf *top = NULL, **mp = ⊤
1778
1779 ++ifp->if_ipackets;
1780 DEBUGF(tokdebug&SHOW_IO, {
1781 int i;
1782 printf("tr%d: trget trs=%x", ifp->if_unit,trs);
1783 printf("\n");});
1784
1785 MGETHDR(m, M_DONTWAIT, MT_DATA);
1786 if (m == 0) return 0;
1787 m->m_pkthdr.rcvif = ifp;
1788 m->m_pkthdr.len = totlen;
1789 m->m_len = MHLEN;
1790
1791 while (totlen > 0) {
1792 if (top) {
1793 MGET(m, M_DONTWAIT, MT_DATA);
1794 if (m == (struct mbuf *)0){
1795 m_freem(top);
1796 DEBUGF(tokdebug&SHOW_IO,
1797 printf("un%d: trget BAD\n", ifp->if_unit));
1798 return (0);
1799 }
1800 m->m_len = MLEN;
1801 }
1802 /*
1803 * how much is left to copy?
1804 * no trailers (yet)
1805 */
1806 len = totlen;
1807 if (len > MINCLSIZE) {
1808 MCLGET(m, M_DONTWAIT);
1809 if (m->m_flags & M_EXT)
1810 m->m_len = MCLBYTES;
1811 }
1812 if (len < m->m_len) {
1813 /*
1814 * Place initial small packet/header at end of mbuf.
1815 */
1816 if (top == 0 && len + max_linkhdr <= m->m_len)
1817 m->m_data += max_linkhdr;
1818 m->m_len = len;
1819 }
1820 trbcopy(trs, mtod(m, char *), m->m_len);
1821 totlen -= m->m_len;
1822 *mp = m;
1823 mp = &m->m_next;
1824 /*
1825 * ignore trailers case again
1826 */
1827 }
1828 return(top);
1829 }
1830 #else OSF
1831 /*
1832 * trget - copy packet from adapter's receive buffers into chain
1833 * of mbufs. return a pointer to this chain.
1834 */
1835 struct mbuf *trget(trs, totlen,ifp)
1836 register struct tr_softc *trs; /* pointer to softc struct for this adapter */
1837 register int totlen; /* total amount of data in receive buffers */
1838 struct ifnet *ifp;
1839 {
1840 register struct mbuf *m;
1841 register int len;
1842 struct mbuf *top = 0;
1843 register struct mbuf **mp = ⊤
1844
1845 while (totlen > 0) { /* while more data to transfer */
1846 char *mcp;
1847
1848 MGET(m, M_DONTWAIT, MT_DATA); /* allocate an mbuf */
1849 if (m == 0) /* mbuf not allocated? */
1850 goto bad;
1851 len = totlen;
1852 if (ifp)
1853 len += sizeof(ifp);
1854 /* data amount in receive bufs >= data space in mbuf cluster? */
1855 if (len >= NBPG) {
1856 MCLGET(m);
1857 if (m->m_len == CLBYTES)
1858 m->m_len = len = MIN(len, CLBYTES);
1859 else
1860 m->m_len = len = MIN(MLEN, len);
1861 } else {
1862 m->m_len = len = MIN(MLEN, len);
1863 m->m_off = MMINOFF;
1864 }
1865 mcp = mtod(m, char *);
1866 if (ifp){
1867 /* prepend ifp to first mbuf */
1868 /*
1869 * bcopy is used since since word moves must
1870 * be on 4 byte boundaries on the RT PC
1871 */
1872 bcopy((char *) &ifp, mcp, sizeof(ifp));
1873 mcp += sizeof(ifp);
1874 len -= sizeof(ifp);
1875 ifp = (struct ifnet *) 0;
1876 }
1877 /* get len bytes of data from receive buffers into mbuf */
1878 trbcopy(trs, mcp, len);
1879 *mp = m; /* add mbuf pointed to by m to mbuf chain */
1880 mp = &m->m_next; /* get pointer to m_next field in mbuf */
1881 totlen -= len; /* subtract number of bytes transferred */
1882 }
1883 return(top); /* return pointer to top of mbuf chain */
1884 bad:
1885 m_freem(top); /* free mbuf chain */
1886 return(0); /* indicate no mbuf pointer to return */
1887 }
1888 #endif OSF
1889
1890
1891 /*
1892 * trioctl - process an ioctl request
1893 */
1894 trioctl(ifp, cmd, data)
1895 register struct ifnet *ifp;
1896 register int cmd;
1897 register caddr_t data;
1898 {
1899 register struct ifaddr *ifa = (struct ifaddr *)data;
1900 register int s = splimp();
1901 register int error = 0;
1902
1903 switch (cmd) {
1904 case SIOCSIFADDR:
1905 ifp->if_flags |= IFF_UP;
1906
1907 #ifdef OSF /* REALLY BSD44 */
1908 switch (ifa->ifa_addr->sa_family)
1909 #else
1910 switch (ifa->ifa_addr.sa_family)
1911 #endif OSF
1912 {
1913 #if INET
1914 case AF_INET:
1915 /* if not running */
1916 if ((ifp->if_flags & IFF_RUNNING) == 0) {
1917 trinit(ifp->if_unit); /* before arpwhohas */
1918 trsleep(ifp->if_unit);
1919 }
1920
1921 ((struct arpcom *) ifp)->ac_ipaddr =
1922 IA_SIN(ifa)->sin_addr;
1923 arpwhohas((struct arpcom *)ifp, &IA_SIN(ifa)->sin_addr);
1924 #endif INET
1925 break;
1926 default:
1927 /* if not running */
1928 if ((ifp->if_flags & IFF_RUNNING) == 0) {
1929 trinit(ifp->if_unit); /* before arpwhohas */
1930 trsleep(ifp->if_unit);
1931 }
1932 break;
1933 }
1934 break;
1935 case SIOCSIFFLAGS:
1936 /*********************************************************/
1937 /* 1- If the adapter is DOWN , turn the device off */
1938 /* ie. adapter down but still running */
1939 /* 2- If the adapter is UP, turn the device on */
1940 /* ie. adapter up but not running yet */
1941 /*********************************************************/
1942 if ((ifp->if_flags & IFF_UP) == 0 && ifp->if_flags &
1943 IFF_RUNNING){
1944 trreset(ifp->if_unit);
1945 } else if (ifp->if_flags & IFF_UP && (ifp->if_flags &
1946 IFF_RUNNING) == 0) {
1947 trinit(ifp->if_unit);
1948 if (ifp->if_addrlist != (struct ifaddr *) 0) {
1949 trsleep(ifp->if_unit);
1950 }
1951 }
1952 break;
1953 default:
1954 error = EINVAL;
1955 }
1956 splx(s);
1957 return(error);
1958 }
1959 #endif MACH_KERNEL
1960
1961
1962 /*
1963 * trbcopy - like bcopy except that it knows about the structure of
1964 * adapter receive buffers.
1965 */
1966
1967 trbcopy(trs, dest, len)
1968 register struct tr_softc *trs; /* pointer to softc struct for this adapter */
1969 register unsigned char *dest; /* destination address */
1970 register int len; /* number of bytes to copy */
1971 {
1972 register int i;
1973 register struct rbcb *rbc = &trs->rbc; /* pointer to rec buf ctl blk */
1974
1975 /* while amount of data needed >= amount in current receive buffer */
1976 while (len >= rbc->data_len) {
1977 /* copy all data from receive buffer to destination */
1978
1979 for (i = 0; i < rbc->data_len; i++)
1980 dest[i] = MM_IN(rbc->rbuf_datap + i);
1981
1982 DEBUGF(tokdebug & 2,{
1983 int i;
1984 printf("trrint - packet data\n");
1985 for (i=0; i < rbc->data_len; i++)
1986 printf("0x%x ",*(dest + i));
1987 printf("\n");
1988 })
1989 len -= rbc->data_len; /* update length left to transfer */
1990 dest += rbc->data_len; /* update destination address */
1991
1992 /* make next receive buffer current receive buffer */
1993 if (rbc->rbufp = rbc->rbufp_next) { /* more receive buffers? */
1994
1995 /* calculate pointer to next receive buffer */
1996 if (MM_INW(&rbc->rbufp->buf_pointer))
1997 rbc->rbufp_next =
1998 (struct rec_buf *)(trs->sram +
1999 MM_INW(&rbc->rbufp->buf_pointer) - 2);
2000 else
2001 rbc->rbufp_next = 0; /* at end of chain */
2002
2003 /* get pointer to data in current receive buffer */
2004 rbc->rbuf_datap = rbc->rbufp->data;
2005
2006 /* get length of data in current receive buffer */
2007 rbc->data_len = MM_INW(&rbc->rbufp->buf_len);
2008 } else {
2009 if (len != 0) /* len should equal zero */
2010 printf("trbcopy: residual data not copied\n");
2011 return;
2012 }
2013 }
2014
2015 /* amount of data needed is < amount in current receive buffer */
2016
2017 for (i = 0; i < len; i++)
2018 dest[i] = MM_IN(rbc->rbuf_datap + i);
2019
2020 DEBUGF(tokdebug & 2,{
2021 int i;
2022 printf("trrint - packet data\n");
2023 for (i=0; i < len; i++)
2024 printf("0x%x ",*(dest + i));
2025 printf("\n");
2026 })
2027 rbc->data_len -= len; /* update count of data in receive buffer */
2028 rbc->rbuf_datap += len; /* update pointer to receive buffer data */
2029 pc_copy_in += len;
2030 }
2031
2032
2033
2034
2035 /*
2036 * trprinttraddr - print a token-ring address
2037 */
2038 trprinttraddr(p)
2039 register unsigned char *p;
2040 {
2041 register int i;
2042
2043 for (i = 0; i < TR_ADDR_LEN; i++) {
2044 if (i != 0) printf(":");
2045 printf("%x", *p++);
2046 }
2047 }
2048
2049 /*
2050 * tropensap - open the token ring SAP interface
2051 */
2052 tropensap(unit,type)
2053 register int unit;
2054 unsigned char type;
2055 {
2056 register struct tr_softc *trs = &tr_softc[unit];
2057 register union sr_srb *srb = trs->cb.srb;
2058
2059 /************************************************************************
2060 ** To use the SAP level interface, we will have to execute a **
2061 ** DLC.OPEN.SAP (pg.6-61 of the Token RIng Tech. Ref.) after we have **
2062 ** received a good return code from the DIR.OPEN.ADAPTER command. **
2063 ** We will open the IP SAP x'aa'. **
2064 ** **
2065 ** STEPS: **
2066 ** 1) Reset SRB response interrupt bit **
2067 ** 2) Use the open_sap srb. **
2068 ** 3) Fill the following fields: **
2069 ** command - x'15' **
2070 ** sap_value - x'aa' **
2071 ** sap_options- x'24' **
2072 ** **
2073 ***********************************************************************/
2074
2075 MM_OUT(&trs->aca->reset.isrp_l, ~(SRB_RESP_INT));
2076
2077 MM_OUT(&srb->open_sap.command, OPEN_SAP);
2078 MM_OUT(&srb->open_sap.retcode, 0x00);
2079 MM_OUTW(&srb->open_sap.station_id, 0x0000);
2080 MM_OUT(&srb->open_sap.timer_t1, 0x00);
2081 MM_OUT(&srb->open_sap.timer_t2, 0x00);
2082 MM_OUT(&srb->open_sap.timer_ti, 0x00);
2083 MM_OUT(&srb->open_sap.maxout, 0x00);
2084 MM_OUT(&srb->open_sap.maxin, 0x00);
2085 MM_OUT(&srb->open_sap.maxout_incr, 0x00);
2086 MM_OUT(&srb->open_sap.maxretry, 0x00);
2087 MM_OUT(&srb->open_sap.gsapmaxmem, 0x00);
2088 MM_OUT(&srb->open_sap.sap_value, type);
2089 MM_OUTW(&srb->open_sap.max_i_field, 0x0088);
2090 MM_OUT(&srb->open_sap.sap_options, 0x24);
2091 MM_OUT(&srb->open_sap.station_cnt, 0x01);
2092 MM_OUT(&srb->open_sap.sap_gsap_mems, 0x00);
2093
2094 MM_OUT(&trs->aca->set.isra_l, CMD_IN_SRB);
2095 }
2096
2097 /*
2098 * trsleep - sleep to wait for adapter to open
2099 */
2100 trsleep(unit)
2101 register int unit;
2102 {
2103 register struct tr_softc *trs = &tr_softc[unit];
2104
2105 timeout(trtimout,unit,hz*30);
2106 sleep(&trs->trsleep_event, 1);
2107 }
2108
2109 /*
2110 * trtimout - timeout routine if adapter does not open in 30 seconds
2111 */
2112 trtimout(unit)
2113 register int unit;
2114 {
2115 register int error = 0;
2116 register struct tr_softc *trs = &tr_softc[unit];
2117
2118 printf("Token Ring timeout\n");
2119 wakeup(&trs->trsleep_event);
2120 error = EIO;
2121 return(error);
2122 }
2123
2124 unsigned short
2125 tr_swap(x)
2126 unsigned short x;
2127 {
2128 return (((x & 0xff) << 8) | ((x & 0xff00) >> 8));
2129 }
2130
2131 /*
2132 * trdelay - delay for given number of milliseconds.
2133 *
2134 * spinwait() is normally the routine that should be invoked to delay for a
2135 * specified number of milliseconds. However, this routine must only be
2136 * called after the clock has been initialized, which is not done until after
2137 * the device autoconfig stage. trdelay() is provided for delays needed
2138 * before spinwait() is useable.
2139 */
2140 trdelay(millis)
2141 int millis;
2142 {
2143 int i, j;
2144
2145 for (i = 0; i < millis; i++)
2146 for (j = 0; j < 100; j++) /* 100 * 10microsecs = 1 ms */
2147 tenmicrosec();
2148 }
2149
2150 #endif NTR > 0
Cache object: 7c2a26cf466690c36265e2e26b3c0601
|