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

Cache object: ee3a689a0481eccb9baaac836aed3f4b


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