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

Cache object: 7e508158c20eccbac91bbc6709020446


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