The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/i386ps2/if_tr.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    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 = &top;
 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 = &top;
 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


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.