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

Cache object: 72180584fdea800004cf554fe85327fe


[ 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.