diff options
Diffstat (limited to 'sys/dev/ic/tropic.c')
-rw-r--r-- | sys/dev/ic/tropic.c | 1732 |
1 files changed, 0 insertions, 1732 deletions
diff --git a/sys/dev/ic/tropic.c b/sys/dev/ic/tropic.c index ad431ce61f5..e69de29bb2d 100644 --- a/sys/dev/ic/tropic.c +++ b/sys/dev/ic/tropic.c @@ -1,1732 +0,0 @@ -/* $OpenBSD: tropic.c,v 1.12 2006/07/09 22:10:05 mk Exp $ */ -/* $NetBSD: tropic.c,v 1.6 1999/12/17 08:26:31 fvdl Exp $ */ - -/* - * Ported to NetBSD by Onno van der Linden - * Many thanks to Larry Lile for sending me the IBM TROPIC documentation. - * - * Mach Operating System - * Copyright (c) 1991 Carnegie Mellon University - * Copyright (c) 1991 IBM Corporation - * All Rights Reserved. - * - * Permission to use, copy, modify and distribute this software and its - * documentation is hereby granted, provided that both the copyright - * notice and this permission notice appear in all copies of the - * software, derivative works or modified versions, and any portions - * thereof, and that both notices appear in supporting documentation, - * and that the name IBM not be used in advertising or publicity - * pertaining to distribution of the software without specific, written - * prior permission. - * - * CARNEGIE MELLON AND IBM ALLOW FREE USE OF THIS SOFTWARE IN ITS "AS IS" - * CONDITION. CARNEGIE MELLON AND IBM DISCLAIM ANY LIABILITY OF ANY KIND FOR - * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. - * - * Carnegie Mellon requests users of this software to return to - * - * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU - * School of Computer Science - * Carnegie Mellon University - * Pittsburgh PA 15213-3890 - * - * any improvements or extensions that they make and grant Carnegie Mellon - * the rights to redistribute these changes. - */ - -#include "bpfilter.h" - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/kernel.h> -#include <sys/proc.h> -#include <sys/mbuf.h> -#include <sys/buf.h> -#include <sys/socket.h> -#include <sys/syslog.h> -#include <sys/ioctl.h> -#include <sys/errno.h> -#include <sys/device.h> -#include <sys/timeout.h> - -#include <net/if.h> -#include <net/if_llc.h> -#include <net/if_media.h> -#include <net/netisr.h> -#include <net/route.h> - -#ifdef INET -#include <netinet/in.h> -#include <netinet/in_systm.h> -#include <netinet/if_ether.h> -#include <netinet/ip.h> -#include <netinet/in_var.h> -#include <net/if_token.h> -#endif - -#if NBPFILTER > 0 -#include <net/bpf.h> -#endif - -#ifndef ifr_mtu -#define ifr_mtu ifr_metric -#endif - -#include <machine/cpu.h> -#include <machine/bus.h> - -#include <dev/ic/tropicreg.h> -#include <dev/ic/tropicvar.h> - -static void tr_shutdown(void *); - -void tr_rint(struct tr_softc *); -void tr_xint(struct tr_softc *); -void tr_oldxint(struct tr_softc *); -struct mbuf *tr_get(struct tr_softc *, int, struct ifnet *); -void tr_opensap(struct tr_softc *, u_char); -int tr_mbcopy(struct tr_softc *, bus_size_t, struct mbuf *); -void tr_bcopy(struct tr_softc *, u_char *, int); -void tr_start(struct ifnet *); -void tr_oldstart(struct ifnet *); -void tr_watchdog(struct ifnet *); -int tr_mediachange(struct ifnet *); -void tr_mediastatus(struct ifnet *, struct ifmediareq *); -int tropic_mediachange(struct tr_softc *); -void tropic_mediastatus(struct tr_softc *, struct ifmediareq *); -void tr_reinit(void *); - -struct cfdriver tr_cd = { - NULL, "tr", DV_IFNET -}; - -/* - * TODO: - * clean up tr_intr: more subroutines - * IFF_LINK0 == IFM_TOK_SRCRT change to link flag implies media flag change - * IFF_LINK1 == IFM_TOK_ALLR change to link flag implies media flag change - * XXX Create receive_done queue to kill "ASB not free", but does this ever - * XXX happen ? - */ - -static int media[] = { - IFM_TOKEN | IFM_TOK_UTP4, - IFM_TOKEN | IFM_TOK_STP4, - IFM_TOKEN | IFM_TOK_UTP16, - IFM_TOKEN | IFM_TOK_STP16, - IFM_TOKEN | IFM_TOK_UTP4, - IFM_TOKEN | IFM_TOK_UTP16, - IFM_TOKEN | IFM_TOK_STP4, - IFM_TOKEN | IFM_TOK_STP16 -}; - -int -tropic_mediachange(sc) - struct tr_softc *sc; -{ - if (IFM_TYPE(sc->sc_media.ifm_media) != IFM_TOKEN) - return EINVAL; - - switch (IFM_SUBTYPE(sc->sc_media.ifm_media)) { - case IFM_TOK_STP16: - case IFM_TOK_UTP16: - if ((sc->sc_init_status & RSP_16) == 0) { - tr_stop(sc); - if (tr_setspeed(sc, 16)) - return EINVAL; - if (tr_reset(sc)) - return EINVAL; - if (tr_config(sc)) - return EINVAL; - } - break; - case IFM_TOK_STP4: - case IFM_TOK_UTP4: - if ((sc->sc_init_status & RSP_16) != 0) { - tr_stop(sc); - if (tr_setspeed(sc, 4)) - return EINVAL; - if (tr_reset(sc)) - return EINVAL; - if (tr_config(sc)) - return EINVAL; - } - break; - } -/* - * XXX Handle Early Token Release !!!! - */ - return 0; -} - -void -tropic_mediastatus(sc, ifmr) - struct tr_softc *sc; - struct ifmediareq *ifmr; -{ - struct ifmedia *ifm = &sc->sc_media; - - ifmr->ifm_active = ifm->ifm_cur->ifm_media; -} - -int -tr_config(sc) - struct tr_softc *sc; -{ - if (sc->sc_init_status & FAST_PATH_TRANSMIT) { - int i; - - for (i=0; i < SRB_CFP_CMDSIZE; i++) - SRB_OUTB(sc, sc->sc_srb, i, 0); - - SRB_OUTB(sc, sc->sc_srb, SRB_CMD, DIR_CONFIG_FAST_PATH_RAM); - - SRB_OUTW(sc, sc->sc_srb, SRB_CFP_RAMSIZE, - (16 + (sc->sc_nbuf * FP_BUF_LEN) / 8)); - SRB_OUTW(sc, sc->sc_srb, SRB_CFP_BUFSIZE, FP_BUF_LEN); - - /* tell adapter: command in SRB */ - ACA_SETB(sc, ACA_ISRA_o, CMD_IN_SRB); - - for (i = 0; i < 30000; i++) { - if (ACA_RDB(sc, ACA_ISRP_o) & SRB_RESP_INT) - break; - delay(100); - } - - if (i == 30000 && sc->sc_srb == ACA_RDW(sc, ACA_WRBR)) { - printf("No response for fast path cfg\n"); - return 1; - } - - ACA_RSTB(sc, ACA_ISRP_o, ~(SRB_RESP_INT)); - - - if ((SRB_INB(sc, sc->sc_srb, SRB_RETCODE) != 0)) { - printf("cfg fast path returned: %02x\n", - SRB_INB(sc, sc->sc_srb, SRB_RETCODE)); - return 1; - } - - sc->sc_txca = SRB_INW(sc, sc->sc_srb, SRB_CFPRESP_FPXMIT); - sc->sc_srb = SRB_INW(sc, sc->sc_srb, SRB_CFPRESP_SRBADDR); - } - else { - if (sc->sc_init_status & RSP_16) - sc->sc_maxmtu = sc->sc_dhb16maxsz; - else - sc->sc_maxmtu = sc->sc_dhb4maxsz; -/* - * XXX Not completely true because Fast Path Transmit has 514 byte buffers - * XXX and TR_MAX_LINK_HDR is only correct when source-routing is used. - * XXX depending on whether source routing is used change the calculation - * XXX use IFM_TOK_SRCRT (IFF_LINK0) - * XXX recompute sc_minbuf !! - */ - sc->sc_maxmtu -= TR_MAX_LINK_HDR; - } - return 0; -} - -int -tr_attach(sc) - struct tr_softc *sc; -{ - int nmedia, *mediaptr, *defmediaptr; - int i, temp; - struct ifnet *ifp = &sc->sc_arpcom.ac_if; - - if (sc->sc_init_status & FAST_PATH_TRANSMIT) { - bus_size_t srb; - int nbuf = 0; - - srb = sc->sc_srb; - - switch (sc->sc_memsize) { - case 65536: - nbuf = 58; - sc->sc_maxmtu = IPMTU_4MBIT_MAX; - break; - case 32768: - nbuf = 29; - sc->sc_maxmtu = IPMTU_4MBIT_MAX; - break; - case 16384: - nbuf = 13; - sc->sc_maxmtu = IPMTU_4MBIT_MAX; - break; - case 8192: - nbuf = 5; - sc->sc_maxmtu = ISO88025_MTU; - } - - sc->sc_minbuf = ((sc->sc_maxmtu + 511) / 512) + 1; - sc->sc_nbuf = nbuf; - -/* - * Create circular queues caching the buffer pointers ? - */ - } - else { -/* - * MAX_MACFRAME_SIZE = DHB_SIZE - 6 - * IPMTU = MAX_MACFRAME_SIZE - (14 + 18 + 8) - * (14 = header, 18 = sroute, 8 = llcsnap) - */ - - switch (sc->sc_memsize) { - case 8192: - sc->sc_dhb4maxsz = 2048; - sc->sc_dhb16maxsz = 2048; - break; - case 16384: - sc->sc_dhb4maxsz = 4096; - sc->sc_dhb16maxsz = 4096; - break; - case 32768: - sc->sc_dhb4maxsz = 4464; - sc->sc_dhb16maxsz = 8192; - break; - case 65536: - sc->sc_dhb4maxsz = 4464; - sc->sc_dhb16maxsz = 8192; - break; - } - switch (MM_INB(sc, TR_DHB4_OFFSET)) { - case 0xF: - if (sc->sc_dhb4maxsz > 2048) - sc->sc_dhb4maxsz = 2048; - break; - case 0xE: - if (sc->sc_dhb4maxsz > 4096) - sc->sc_dhb4maxsz = 4096; - break; - case 0xD: - if (sc->sc_dhb4maxsz > 4464) - sc->sc_dhb4maxsz = 4464; - break; - } - - switch (MM_INB(sc, TR_DHB16_OFFSET)) { - case 0xF: - if (sc->sc_dhb16maxsz > 2048) - sc->sc_dhb16maxsz = 2048; - break; - case 0xE: - if (sc->sc_dhb16maxsz > 4096) - sc->sc_dhb16maxsz = 4096; - break; - case 0xD: - if (sc->sc_dhb16maxsz > 8192) - sc->sc_dhb16maxsz = 8192; - break; - case 0xC: - if (sc->sc_dhb16maxsz > 8192) - sc->sc_dhb16maxsz = 8192; - break; - case 0xB: - if (sc->sc_dhb16maxsz > 8192) - sc->sc_dhb16maxsz = 8192; - break; - } - } - - if (tr_config(sc)) - return 1; - - /* - * init network-visible interface - */ - bcopy(sc->sc_dev.dv_xname, ifp->if_xname, IFNAMSIZ); - ifp->if_softc = sc; - ifp->if_ioctl = tr_ioctl; - if (sc->sc_init_status & FAST_PATH_TRANSMIT) - ifp->if_start = tr_start; - else - ifp->if_start = tr_oldstart; - ifp->if_flags = IFF_BROADCAST | IFF_NOTRAILERS; - ifp->if_watchdog = tr_watchdog; - IFQ_SET_READY(&ifp->if_snd); - - switch (MM_INB(sc, TR_MEDIAS_OFFSET)) { - case 0xF: - nmedia = 1; - mediaptr = &media[6]; - break; - case 0xE: - nmedia = 2; - mediaptr = &media[0]; - break; - case 0xD: - nmedia = 1; - mediaptr = &media[4]; - break; - default: - nmedia = 0; - mediaptr = NULL; - } - - switch (MM_INB(sc, TR_RATES_OFFSET)) { - case 0xF: - /* 4 Mbps */ - break; - case 0xE: - /* 16 Mbps */ - if (mediaptr) - mediaptr += nmedia; - break; - case 0xD: - /* 4/16 Mbps */ - nmedia *= 2; - break; - } - - switch (MM_INB(sc, TR_MEDIA_OFFSET)) { - case 0xF: - /* STP */ - defmediaptr = &media[6]; - break; - case 0xE: - /* UTP */ - defmediaptr = &media[4]; - break; - case 0xD: - /* STP and UTP == a single shielded RJ45 which supports both */ - /* XXX additional types in net/if_media.h ?? */ - defmediaptr = &media[4]; - break; - default: - defmediaptr = NULL; - } - - if (defmediaptr && (sc->sc_init_status & RSP_16)) - ++defmediaptr; - - if (sc->sc_mediachange == NULL && sc->sc_mediastatus == NULL) { - switch (MM_INB(sc, TR_TYP_OFFSET)) { - case 0x0D: - case 0x0C: - sc->sc_mediachange = tropic_mediachange; - sc->sc_mediastatus = tropic_mediastatus; - } - } - - ifmedia_init(&sc->sc_media, 0, tr_mediachange, tr_mediastatus); - if (mediaptr != NULL) { - for (i = 0; i < nmedia; i++) - ifmedia_add(&sc->sc_media, mediaptr[i], 0, NULL); - if (defmediaptr) - ifmedia_set(&sc->sc_media, *defmediaptr); - else - ifmedia_set(&sc->sc_media, 0); - } - else { - ifmedia_add(&sc->sc_media, IFM_TOKEN | IFM_MANUAL, 0, NULL); - ifmedia_set(&sc->sc_media, IFM_TOKEN | IFM_MANUAL); - } - - if_attach(ifp); - - for (i = 0, temp = 0; i < ISO88025_ADDR_LEN; i++, temp += 4) { - sc->sc_arpcom.ac_enaddr[i] = - (MM_INB(sc, (TR_MAC_OFFSET + temp)) & 0xf) << 4; - sc->sc_arpcom.ac_enaddr[i] |= - MM_INB(sc, (TR_MAC_OFFSET + temp + 2)) & 0xf; - } - - token_ifattach(ifp); - - printf("\n%s: address %s ring speed %d Mbps\n", - sc->sc_dev.dv_xname, token_sprintf(sc->sc_arpcom.ac_enaddr), - (sc->sc_init_status & RSP_16) ? 16 : 4); - -#if NBPFILTER > 0 - bpfattach(&ifp->if_bpf, ifp, DLT_IEEE802, sizeof(struct token_header)); -#endif - -/* - * XXX rnd stuff - */ - shutdownhook_establish(tr_shutdown, sc); - return 0; -} - -int -tr_setspeed(sc, speed) -struct tr_softc *sc; -u_int8_t speed; -{ - SRB_OUTB(sc, sc->sc_srb, SRB_CMD, DIR_SET_DEFAULT_RING_SPEED); - SRB_OUTB(sc, sc->sc_srb, CMD_RETCODE, 0xfe); - SRB_OUTB(sc, sc->sc_srb, SRB_SET_DEFRSP, speed); - /* Tell adapter: command in SRB. */ - ACA_SETB(sc, ACA_ISRA_o, CMD_IN_SRB); - - /* Wait for it to complete. */ - tr_sleep(sc); - - if ((SRB_INB(sc, sc->sc_srb, SRB_RETCODE) != 0)) { - printf("set default ringspeed returned: %02x\n", - SRB_INB(sc, sc->sc_srb, SRB_RETCODE)); - return 1; - } - return 0; -} - -int -tr_mediachange(ifp) - struct ifnet *ifp; -{ - struct tr_softc *sc = ifp->if_softc; - - if (sc->sc_mediachange) - return ((*sc->sc_mediachange)(sc)); - return EINVAL; -} - -void -tr_mediastatus(ifp, ifmr) - struct ifnet *ifp; - struct ifmediareq *ifmr; -{ - struct tr_softc *sc = ifp->if_softc; - -/* set LINK0 and/or LINK1 */ - if (sc->sc_mediastatus) - (*sc->sc_mediastatus)(sc, ifmr); -} - -int -tr_reset(sc) -struct tr_softc *sc; -{ - int i; - - sc->sc_srb = 0; - - /* - * Reset the card. - */ - /* latch on an unconditional adapter reset */ - bus_space_write_1(sc->sc_piot, sc->sc_pioh, TR_RESET, 0); - delay(50000); /* delay 50ms */ - /* - * XXX set paging if we have the right type of card - */ - /* turn off adapter reset */ - bus_space_write_1(sc->sc_piot, sc->sc_pioh, TR_RELEASE, 0); - - /* Enable interrupts. */ - - ACA_SETB(sc, ACA_ISRP_e, INT_ENABLE); - - /* Wait for an answer from the adapter. */ - - for (i = 0; i < 35000; i++) { - if (ACA_RDB(sc, ACA_ISRP_o) & SRB_RESP_INT) - break; - delay(100); - } - - if (i == 35000 && sc->sc_srb == 0) { - printf("No response from adapter after reset\n"); - return 1; - } - - ACA_RSTB(sc, ACA_ISRP_o, ~(SRB_RESP_INT)); - - ACA_OUTB(sc, ACA_RRR_e, (sc->sc_maddr >> 12)); - sc->sc_srb = ACA_RDW(sc, ACA_WRBR); - if (SRB_INB(sc, sc->sc_srb, SRB_CMD) != 0x80) { - printf("Initialization incomplete, status: %02x\n", - SRB_INB(sc, sc->sc_srb, SRB_CMD)); - return 1; - } - if (SRB_INB(sc, sc->sc_srb, SRB_INIT_BUC) != 0) { - printf("Bring Up Code %02x\n", - SRB_INB(sc, sc->sc_srb, SRB_INIT_BUC)); - return 1; - } - - sc->sc_init_status = SRB_INB(sc, sc->sc_srb, SRB_INIT_STATUS); - - sc->sc_xmit_head = sc->sc_xmit_tail = 0; - - /* XXX should depend on sc_resvdmem. */ - if (MM_INB(sc, TR_RAM_OFFSET) == 0xB && sc->sc_memsize == 65536) - for (i = 0; i < 512; i++) - SR_OUTB(sc, 0xfe00 + i, 0); - return 0; -} - -/* - * tr_stop - stop interface (issue a DIR CLOSE ADAPTER command) - */ -void -tr_stop(sc) -struct tr_softc *sc; -{ - struct ifnet *ifp = &sc->sc_arpcom.ac_if; - - if ((ifp->if_flags & IFF_RUNNING) != 0) { -/* - * transmitter cannot be used from now on - */ - ifp->if_flags |= IFF_OACTIVE; - - /* Close command. */ - SRB_OUTB(sc, sc->sc_srb, SRB_CMD, DIR_CLOSE); - /* Tell adapter: command in SRB. */ - ACA_SETB(sc, ACA_ISRA_o, CMD_IN_SRB); - - /* Wait for it to complete. */ - tr_sleep(sc); - sc->sc_srb = ACA_RDW(sc, ACA_WRBR); - } -} - -static void -tr_shutdown(arg) - void *arg; -{ - struct tr_softc *sc = arg; - - tr_stop(sc); -} - -void -tr_reinit(arg) - void *arg; -{ - if (tr_reset((struct tr_softc *) arg)) - return; - if (tr_config((struct tr_softc *) arg)) - return; - tr_init(arg); -} - -/* - * tr_init - initialize network interface, open adapter for packet - * reception and start any pending output - */ -void -tr_init(arg) - void *arg; -{ - struct tr_softc *sc = arg; - struct ifnet *ifp = &sc->sc_arpcom.ac_if; - bus_size_t open_srb; - int s, num_dhb; - int resvdmem, availmem, dhbsize; - - if ((ifp->if_flags & IFF_RUNNING) != 0) - return; - - s = splnet(); - - ifp->if_flags &= ~IFF_OACTIVE; - sc->sc_xmit_head = sc->sc_xmit_tail = 0; /* XXX tr_reset() */ - - open_srb = sc->sc_srb; - - /* Zero SRB. */ - bus_space_set_region_1(sc->sc_memt, sc->sc_sramh, - open_srb, 0, SRB_OPEN_CMDSIZE); - - /* Open command. */ - SRB_OUTB(sc, open_srb, SRB_CMD, DIR_OPEN_ADAPTER); -/* - * XXX handle IFM_TOK_ETR !!!! - */ - /* Set open parameters in SRB. */ - SRB_OUTW(sc, open_srb, SRB_OPEN_OPTIONS, OPEN_PASS_BCON_MAC); - - num_dhb = 1; - - if ((sc->sc_init_status & FAST_PATH_TRANSMIT) == 0) { - availmem = sc->sc_memsize; - resvdmem = RESVDMEM_SIZE + sc->sc_memreserved; - - /* allow MAX of two SAPS */ - SRB_OUTB(sc, open_srb, SRB_OPEN_DLCMAXSAP, 2); - resvdmem += 2 * SAPCB_SIZE; - - /* allow MAX of 4 stations */ - SRB_OUTB(sc, open_srb, SRB_OPEN_DLCMAXSTA, 4); - resvdmem += 4 * LSCB_SIZE; - - if (sc->sc_init_status & RSP_16) { - dhbsize = sc->sc_dhb16maxsz; - } - else { - dhbsize = sc->sc_dhb4maxsz; - } -#if 0 /* XXXchb unneeded? */ - if (dhbsize > 2048) - num_dhb = 2; -#endif - SRB_OUTW(sc, open_srb, SRB_OPEN_DHBLEN, dhbsize); - sc->sc_nbuf = (dhbsize + 511) / 512; - /* - * Try to leave room for two fullsized packets when - * requesting DHBs. - */ - availmem -= resvdmem; - num_dhb = (availmem / dhbsize) - 2; - if (num_dhb > 2) - num_dhb = 2; /* firmware can't cope with more DHBs */ - if (num_dhb < 1) - num_dhb = 1; /* we need at least one */ - } - else - SRB_OUTW(sc, open_srb, SRB_OPEN_DHBLEN, DHB_LENGTH); - - SRB_OUTB(sc, open_srb, SRB_OPEN_NUMDHB, num_dhb); - SRB_OUTW(sc, open_srb, SRB_OPEN_RCVBUFLEN, RCV_BUF_LEN); - SRB_OUTW(sc, open_srb, SRB_OPEN_NUMRCVBUF, sc->sc_nbuf); - - /* Tell adapter: command in SRB. */ - ACA_SETB(sc, ACA_ISRA_o, CMD_IN_SRB); - - splx(s); -} - -/* - * tr_oldstart - Present transmit request to adapter - */ -void -tr_oldstart(ifp) -struct ifnet *ifp; -{ - struct tr_softc *sc = ifp->if_softc; - bus_size_t srb = sc->sc_srb; - - if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING) - return; - - ifp->if_flags |= IFF_OACTIVE; - - /* Load SRB to request transmit. */ - SRB_OUTB(sc, srb, SRB_CMD, XMIT_UI_FRM); - SRB_OUTW(sc, srb, XMIT_STATIONID, sc->exsap_station); - ACA_SETB(sc, ACA_ISRA_o, CMD_IN_SRB); -} - -void -tr_start(ifp) -struct ifnet *ifp; -{ - struct tr_softc *sc = ifp->if_softc; - bus_size_t first_txbuf, txbuf; - struct mbuf *m0, *m; - int size, bufspace; - bus_size_t framedata; - - if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING) - return; - - -next: - if (sc->sc_xmit_buffers < sc->sc_minbuf) - return; - - /* if data in queue, copy mbuf chain to fast path buffers */ - IFQ_DEQUEUE(&ifp->if_snd, m0); - - if (m0 == 0) - return; -#if NBPFILTER > 0 - if (ifp->if_bpf) - bpf_mtap(ifp->if_bpf, m0, BPF_DIRECTION_OUT); -#endif - first_txbuf = txbuf = TXCA_INW(sc, TXCA_FREE_QUEUE_HEAD) - XMIT_NEXTBUF; - framedata = txbuf + XMIT_FP_DATA; - size = 0; - bufspace = FP_BUF_LEN - XMIT_FP_DATA; - --sc->sc_xmit_buffers; - for (m = m0; m; m = m->m_next) { - int len = m->m_len; - char *ptr = mtod(m, char *); - - while (len >= bufspace) { - --sc->sc_xmit_buffers; - bus_space_write_region_1(sc->sc_memt, sc->sc_sramh, - framedata, ptr, bufspace); - size += bufspace; - ptr += bufspace; - len -= bufspace; - TXB_OUTW(sc, txbuf, XMIT_BUFLEN, - (FP_BUF_LEN - XMIT_FP_DATA)); - txbuf = TXB_INW(sc, txbuf, XMIT_NEXTBUF) - XMIT_NEXTBUF; - framedata = txbuf + XMIT_FP_DATA; - bufspace = FP_BUF_LEN - XMIT_FP_DATA; - } - if (len > 0) { - bus_space_write_region_1(sc->sc_memt, sc->sc_sramh, - framedata, ptr, len); - size += len; - bufspace -= len; - framedata += len; - } - } - TXB_OUTW(sc, txbuf, XMIT_BUFLEN, (FP_BUF_LEN - XMIT_FP_DATA - bufspace)); - m_freem(m0); /* free mbuf chain */ - - TXB_OUTB(sc, first_txbuf, XMIT_RETCODE, 0xfe); - TXB_OUTW(sc, first_txbuf, XMIT_FRAMELEN, size); - TXB_OUTW(sc, first_txbuf, XMIT_LASTBUF, (txbuf + XMIT_NEXTBUF)); - TXB_OUTB(sc, first_txbuf, XMIT_CMD, XMIT_DIR_FRAME); - TXB_OUTW(sc, first_txbuf, XMIT_STATIONID, 0); - TXB_OUTB(sc, first_txbuf, XMIT_CMDCORR, sc->sc_xmit_correlator); - sc->sc_xmit_correlator = (sc->sc_xmit_correlator + 1) & 0x7f; - - /* - * To prevent race conditions on 8-bit cards when reading or writing - * 16-bit values. See page 4-12 of the IBM manual. - */ - TXCA_OUTW(sc, TXCA_FREE_QUEUE_HEAD, 1); - TXCA_OUTW(sc, TXCA_FREE_QUEUE_HEAD, TXB_INW(sc, txbuf, XMIT_NEXTBUF)); - - ACA_SETB(sc, ACA_ISRA_o, XMIT_REQ); - - ifp->if_flags |= IFF_OACTIVE; - ifp->if_opackets++; -#if 1 -/* XXX do while construction */ - goto next; -#endif -} - -/* - * tr_intr - interrupt handler. Find the cause of the interrupt and - * service it. - */ -int -tr_intr(arg) - void *arg; -{ - struct tr_softc *sc = arg; - struct ifnet *ifp = &sc->sc_arpcom.ac_if; - u_char status; /* holds status from adapter status register */ - u_char command; /* holds command from status or request block */ - u_char retcode; /* holds return value from status or request block */ - int rc = 0; /* 0 = unclaimed interrupt, 1 = interrupt claimed */ - - status = ACA_RDB(sc, ACA_ISRP_o); - while (status != 0) { - - /* Is this interrupt caused by an adapter check? */ - if (status & ADAP_CHK_INT) { - printf("%s: adapter check 0x%04x\n", - sc->sc_dev.dv_xname, - (unsigned int)ntohs(ACA_RDW(sc, ACA_WWCR))); - - /* Clear this interrupt bit */ - ACA_RSTB(sc, ACA_ISRP_o, ~(ADAP_CHK_INT)); - - rc = 1; /* Claim interrupt. */ - break; /* Terminate loop. */ - } - else if (status & XMIT_COMPLETE) { - ACA_RSTB(sc, ACA_ISRP_o, ~(XMIT_COMPLETE)); - tr_xint(sc); - rc = 1; - } - - /* - * Process SRB_RESP_INT, ASB_FREE_INT, ARB_CMD_INT - * & SSB_RESP_INT in that order, ISRP-L Hi to Lo - */ - else if (status & SRB_RESP_INT) { /* Adapter response in SRB? */ - bus_size_t sap_srb; - bus_size_t srb; -#ifdef TROPICDEBUG - bus_size_t log_srb; -#endif - if (sc->sc_srb == 0) - sc->sc_srb = ACA_RDW(sc, ACA_WRBR); - srb = sc->sc_srb; /* pointer to SRB */ - retcode = SRB_INB(sc, srb, SRB_RETCODE); - command = SRB_INB(sc, srb, SRB_CMD); - switch (command) { - case 0x80: /* 0x80 == initialization complete */ - case DIR_CONFIG_FAST_PATH_RAM: - break; - case XMIT_DIR_FRAME: /* Response to xmit request */ - case XMIT_UI_FRM: /* Response to xmit request */ - /* Response not valid? */ - if (retcode != 0xff) - printf("%s: error on xmit request =%x\n", - sc->sc_dev.dv_xname, retcode); - break; - - case DIR_OPEN_ADAPTER: /* open-adapter-cmd response */ - /* Open successful? */ - if (retcode == 0) { - ifp->if_flags |= IFF_UP | IFF_RUNNING; - /* Save new ACA ctrl block addresses */ - sc->sc_ssb = SRB_INW(sc, srb, - SRB_OPENRESP_SSBADDR); - sc->sc_arb = SRB_INW(sc, srb, - SRB_OPENRESP_ARBADDR); - sc->sc_srb = SRB_INW(sc, srb, - SRB_OPENRESP_SRBADDR); - sc->sc_asb = SRB_INW(sc, srb, - SRB_OPENRESP_ASBADDR); - - /* - * XXX, what about LLC_{X25,ISO}_LSAP ? - * open two more saps ..... - */ - if (sc->sc_init_status & - FAST_PATH_TRANSMIT) { - sc->sc_xmit_buffers = - TXCA_INW(sc, TXCA_BUFFER_COUNT); - sc->sc_nbuf = - sc->sc_xmit_buffers; -#ifdef TROPICDEBUG - printf("buffers = %d\n", - sc->sc_xmit_buffers); -#endif - sc->sc_xmit_correlator = 0; - wakeup(&sc->tr_sleepevent); - } - else - tr_opensap(sc, LLC_SNAP_LSAP); - } - else { - printf("%s: Open error = %x\n", - sc->sc_dev.dv_xname, - SRB_INB(sc, srb, SRB_RETCODE)); - ifp->if_flags &= ~IFF_RUNNING; - ifp->if_flags &= ~IFF_UP; -/* - * XXX untimeout depending on the error, timeout in other cases - * XXX error 0x24 && autospeed mode: open again !!!! - */ - if (!timeout_initialized(&sc->init_timeout)) - timeout_set(&sc->init_timeout, - tr_init, sc); - timeout_add(&sc->init_timeout, hz * 30); - } - break; - - case DIR_CLOSE: /* Response to close adapter command */ - /* Close not successful? */ - if (retcode != 0) - printf("%s: close error = %x\n", - sc->sc_dev.dv_xname, retcode); - else { - ifp->if_flags &= ~IFF_RUNNING; - ifp->if_flags &= ~IFF_UP; - ifp->if_flags &= ~IFF_OACTIVE; - wakeup(&sc->tr_sleepevent); - } - break; - case DIR_SET_DEFAULT_RING_SPEED: - wakeup(&sc->tr_sleepevent); - break; - - case DLC_OPEN_SAP: /* Response to open sap cmd */ - sap_srb = sc->sc_srb; - if (SRB_INB(sc, sap_srb, SRB_OPNSAP_SAPVALUE) - == LLC_SNAP_LSAP) - sc->exsap_station = - SRB_INW(sc, sap_srb, - SRB_OPNSAP_STATIONID); - printf("%s: Token Ring opened\n", - sc->sc_dev.dv_xname); - wakeup(&sc->tr_sleepevent); - break; -/* XXX DLC_CLOSE_SAP not needed ? */ - case DLC_CLOSE_SAP: /* Response to close sap cmd */ - break; - case DIR_READ_LOG: /* Response to read log */ - /* Cmd not successful? */ - if (retcode != 0) - printf("%s: read error log cmd err =%x\n", - sc->sc_dev.dv_xname, retcode); -#ifdef TROPICDEBUG - log_srb = sc->sc_srb; - printf("%s: ERROR LOG:\n",sc->sc_dev.dv_xname); - printf("%s: Line=%d, Internal=%d, Burst=%d\n", - sc->sc_dev.dv_xname, - (SRB_INB(sc, log_srb, SRB_LOG_LINEERRS)), - (SRB_INB(sc, log_srb, SRB_LOG_INTERRS)), - (SRB_INB(sc, log_srb, SRB_LOG_BRSTERRS))); - printf("%s: A/C=%d, Abort=%d, Lost frames=%d\n", - sc->sc_dev.dv_xname, - (SRB_INB(sc, log_srb, SRB_LOG_ACERRS)), - (SRB_INB(sc, log_srb, SRB_LOG_ABRTERRS)), - (SRB_INB(sc, log_srb, SRB_LOG_LOSTFRMS))); - printf("%s: Receive congestion=%d, Frame copied=%d, Frequency=%d\n", - sc->sc_dev.dv_xname, - (SRB_INB(sc, log_srb, SRB_LOG_RCVCONG)), - (SRB_INB(sc, log_srb, SRB_LOG_FCPYERRS)), - (SRB_INB(sc, log_srb, SRB_LOG_FREQERRS))); - printf("%s: Token=%d\n",sc->sc_dev.dv_xname, - (SRB_INB(sc, log_srb, SRB_LOG_TOKENERRS))); -#endif /* TROPICDEBUG */ - ifp->if_flags &= ~IFF_OACTIVE; - break; - default: - printf("%s: bad SRB command encountered %x\n", - sc->sc_dev.dv_xname, command); - break; - } - /* clear the SRB-response interrupt bit */ - ACA_RSTB(sc, ACA_ISRP_o, ~(SRB_RESP_INT)); - - } - - else if (status & ASB_FREE_INT) { /* Is ASB Free? */ - bus_size_t asb = sc->sc_asb; - - /* - * Remove message from asb queue, first element in - * structure is the command. command == REC_DATA? - * size = 8 : size = 10 - * reply in isra_l with (RESP_IN_ASB | ASB_FREE) - */ - retcode = ASB_INB(sc, asb, CMD_RETCODE); - command = ASB_INB(sc, asb, CMD_CMD); - switch (command) { - case REC_DATA: /* Receive */ - /* Response not valid? */ - if (retcode != 0xff) - printf("%s: ASB bad receive response =%x\n", - sc->sc_dev.dv_xname, retcode); - break; - case XMIT_DIR_FRAME: /* Transmit */ - case XMIT_UI_FRM: /* Transmit */ - /* Response not valid? */ - if (retcode != 0xff) - printf("%s: ASB response err on xmit =%x\n", - sc->sc_dev.dv_xname, retcode); - break; - default: - printf("%s: Invalid command in ASB =%x\n", - sc->sc_dev.dv_xname, command); - break; - } - /* Clear this interrupt bit */ - ACA_RSTB(sc, ACA_ISRP_o, ~(ASB_FREE_INT)); - } - else if (status & ARB_CMD_INT) { /* Command for PC to handle? */ - bus_size_t arb = sc->sc_arb; - - command = ARB_INB(sc, arb, ARB_CMD); - switch (command) { - case DLC_STATUS: /* DLC status change */ - printf("%s: ARB new DLC status = 0x%x\n", - sc->sc_dev.dv_xname, - ARB_INW(sc, arb, ARB_DLCSTAT_STATUS)); - break; - case REC_DATA: /* Adapter has data for PC */ - /* Call receive interrupt handler */ - tr_rint(sc); - break; - - case RING_STAT_CHANGE: /* Ring status change */ - if (ARB_INW(sc, arb, ARB_RINGSTATUS) & - (SIGNAL_LOSS + LOBE_FAULT)){ - printf("%s: SIGNAL LOSS/LOBE FAULT\n", - sc->sc_dev.dv_xname); - ifp->if_flags &= ~IFF_RUNNING; - ifp->if_flags &= ~IFF_UP; - IFQ_PURGE(&ifp->if_snd); - if (!timeout_initialized(&sc->reinit_timeout)) - timeout_set(&sc->reinit_timeout, - tr_reinit, sc); - timeout_add(&sc->reinit_timeout, hz * 30); - } - else { -#ifdef TROPICDEBUG - if (ARB_INW(sc, arb, ARB_RINGSTATUS) & - ~(SOFT_ERR)) - printf( - "%s: ARB new ring status = 0x%x\n", - sc->sc_dev.dv_xname, - ARB_INW(sc, arb, - ARB_RINGSTATUS)); -#endif /* TROPICDEBUG */ - } - if (ARB_INW(sc, arb, ARB_RINGSTATUS) & - LOG_OFLOW){ -/* - * XXX CMD_IN_SRB, handle with SRB_FREE_INT ? - */ - ifp->if_flags |= IFF_OACTIVE; - SRB_OUTB(sc, sc->sc_srb, SRB_CMD, - DIR_READ_LOG); - /* Read & reset err log cmnd in SRB. */ - ACA_SETB(sc, ACA_ISRA_o, CMD_IN_SRB); - } - break; - - case XMIT_DATA_REQ: /* Adapter wants data to transmit */ - /* Call transmit interrupt handler */ - tr_oldxint(sc); - break; - - default: - printf("%s: Invalid command in ARB =%x\n", - sc->sc_dev.dv_xname, command); - break; - } - - /* Clear this interrupt bit */ - ACA_RSTB(sc, ACA_ISRP_o, ~(ARB_CMD_INT)); - - /* Tell adapter that ARB is now free */ - ACA_SETB(sc, ACA_ISRA_o, ARB_FREE); - } - - - else if (status & SSB_RESP_INT) { /* SSB resp. to SRB cmd? */ - bus_size_t ssb = sc->sc_ssb; - - retcode = SSB_INB(sc, ssb, SSB_RETCODE); - command = SSB_INB(sc, ssb, SSB_CMD); - switch (command) { - case XMIT_UI_FRM: - case XMIT_DIR_FRAME: /* SSB response to SRB xmit cmd */ - /* collect status on last packet */ - if (retcode != 0) { - printf("xmit return code = 0x%x\n", - retcode); - /* XXXchb */ - if (retcode == 0x22) { - printf("FS = 0x%2x\n", - SSB_INB(sc, ssb, - SSB_XMITERR)); - } - ifp->if_oerrors++; - } - else - ifp->if_opackets++; - - ifp->if_flags &= ~IFF_OACTIVE; -/* - * XXX should this be done here ? - */ - /* if data on send queue */ - if (!IFQ_IS_EMPTY(&ifp->if_snd)) - tr_oldstart(ifp); - break; - - case XMIT_XID_CMD: - printf("tr_int: xmit XID return code = 0x%x\n", - retcode); - break; - default: - printf("%s: SSB error, invalid command =%x\n", - sc->sc_dev.dv_xname, command); - } - /* clear this interrupt bit */ - ACA_RSTB(sc, ACA_ISRP_o, ~(SSB_RESP_INT)); - - /* tell adapter that SSB is available */ - ACA_SETB(sc, ACA_ISRA_o, SSB_FREE); - } - rc = 1; /* Claim responsibility for interrupt */ - status = ACA_RDB(sc, ACA_ISRP_o); - } - /* Is this interrupt caused by an adapter error or access violation? */ - if (ACA_RDB(sc, ACA_ISRP_e) & (TCR_INT | ERR_INT | ACCESS_INT)) { - printf("%s: adapter error, ISRP_e = %x\n", - sc->sc_dev.dv_xname, ACA_RDB(sc, ACA_ISRP_e)); - - /* Clear these interrupt bits */ - ACA_RSTB(sc, ACA_ISRP_e, ~(TCR_INT | ERR_INT | ACCESS_INT)); - rc = 1; /* Claim responsibility for interrupt */ - - } - - /* Clear IRQ latch in order to reenable interrupts. */ - bus_space_write_1(sc->sc_piot, sc->sc_pioh, TR_CLEARINT, 0); - return (rc); -} - -#ifdef notyet -int asb_reply_rcv() -{ -} - -int asb_reply_xmit() -{ -} - -int asb_response(bus_size_t asb, size_t len) -{ - if (empty_queue) { - answer with RESP_IN_ASB | ASB_FREE - } - else { - put asb in queue - } -} -#endif - - -/* - * U-B receive interrupt. - * - * in the original version, this routine had three tasks: - * - * 1. move the data into the receive buffer and set up various pointers - * in the tr_softc struct - * 2. switch on the type field for ip and arp, dropping all else - * 3. resetting the adaptor status block info (asb) and updating the - * tr_softc struct - * determine lan message type, pull packet off interface and - * pass to an appropriate higher-level routine - * - */ -void -tr_rint(sc) -struct tr_softc *sc; -{ - bus_size_t arb = sc->sc_arb; - bus_size_t asb = sc->sc_asb; - struct rbcb *rbc = &sc->rbc; - struct mbuf *m; - struct ifnet *ifp = &sc->sc_arpcom.ac_if; - -#ifdef TROPICDEBUG - printf("tr_rint: arb.command = %x, arb.station_id= %x\n", - ARB_INB(sc, arb, ARB_CMD), ARB_INW(sc, arb, ARB_STATIONID)); - printf("arb.buf_addr = %x, arb.lan_hdr_len = %x\n", - ARB_INW(sc, arb, ARB_RXD_BUFADDR), - ARB_INB(sc, arb, ARB_RXD_LANHDRLEN)); - printf("arb.dlc_hdr_len = %d, arb.frame_len = %d\n", - ARB_INB(sc, arb, ARB_RXD_DLCHDRLEN), - ARB_INW(sc, arb, ARB_RXD_FRAMELEN)); - printf("arb.msg_type = %x\n", ARB_INB(sc, arb, ARB_RXD_MSGTYPE)); -#endif /* TROPICDEBUG */ - /* - * copy the offset in RAM of the first receive buffer from the - * receive-data block of the adapter request block associated - * with the unit's softc struct into the receive control block. - */ - rbc->rbufp = ARB_INW(sc, arb, ARB_RXD_BUFADDR); - - /* - * copy the pointer to data in first receive buffer - */ - rbc->rbuf_datap = rbc->rbufp + RB_DATA; - /* - * the token-ring header is viewed as two header structs: the physical - * header (aka TR header) with access, frame, dest, src, and routing - * information, and the logical link control header (aka LLC header) - * with dsap, ssap, llc, proto and type fields. - * - * rfc1042 requires support for unnumbered information (UI) commands, - * but does not specify a required semantic, so we'll discard them. - * - */ - - /* - * if there is a second receive buffer, set up the next pointer - */ - if (RB_INW(sc, rbc->rbufp, RB_NEXTBUF)) - rbc->rbufp_next = RB_INW(sc, rbc->rbufp, RB_NEXTBUF) - - RB_NEXTBUF; - else - rbc->rbufp_next = 0; /* we're finished */ - - rbc->data_len = RB_INW(sc, rbc->rbufp, RB_BUFLEN); - /* - * At this point we move the packet from the adapter to a chain - * of mbufs - */ - m = tr_get(sc, ARB_INW(sc, arb, ARB_RXD_FRAMELEN), ifp); -/* - * XXX Clear ARB interrupt here? - */ -/* - * XXX create a queue where the responses are buffered - * XXX but is it really needed ? - */ - - if (ASB_INB(sc, asb, RECV_RETCODE) != 0xff) - printf("tr_rint: ASB IS NOT FREE!!!\n"); - /* - * Load receive response into ASB. - */ - ASB_OUTB(sc, asb, RECV_CMD, REC_DATA); - ASB_OUTW(sc, asb, RECV_STATIONID, ARB_INW(sc, arb, ARB_STATIONID)); - ASB_OUTW(sc, asb, RECV_RESP_RECBUFADDR, - ARB_INW(sc, arb, ARB_RXD_BUFADDR)); - - if (m == 0) { - /* - * Tell adapter data lost, no mbufs. - */ - ASB_OUTB(sc, asb, RECV_RETCODE, 0x20); - ACA_SETB(sc, ACA_ISRA_o, RESP_IN_ASB); - ++ifp->if_ierrors; -#ifdef TROPICDEBUG - printf("tr_rint: packet dropped\n"); -#endif /* TROPICDEBUG */ - } - else { - /* - * Indicate successful receive. - */ - ASB_OUTB(sc, asb, RECV_RETCODE, 0); - ACA_SETB(sc, ACA_ISRA_o, RESP_IN_ASB); - ++ifp->if_ipackets; - -#if NBPFILTER > 0 - if (ifp->if_bpf) - bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_IN); -#endif - token_input(ifp, m); - } -} - -/* - * Interrupt handler for old style "adapter requires data to transmit". - */ -void -tr_oldxint(sc) -struct tr_softc *sc; -{ - bus_size_t arb = sc->sc_arb; /* pointer to ARB */ - bus_size_t asb = sc->sc_asb; /* pointer to ASB */ - bus_size_t dhb; /* pointer to DHB */ - struct mbuf *m0; /* pointer to top of mbuf chain */ - u_short size = 0; - char command; - struct ifnet *ifp = &sc->sc_arpcom.ac_if; - struct token_header *trh; - int i; - u_int8_t hlen; - -/* - * XXX xmit_asb_response() - */ - if (ASB_INB(sc, asb, XMIT_RETCODE) != 0xff) - printf("tr_oldxint: ASB IS NOT FREE!!!\n"); - - /* load parameters into ASB */ - ASB_OUTB(sc, asb, XMIT_CMDCORR, ARB_INB(sc, arb, ARB_XMT_CMDCORR)); - ASB_OUTW(sc, asb, XMIT_STATIONID, ARB_INW(sc, arb, ARB_STATIONID)); - ASB_OUTB(sc, asb, XMIT_RETCODE, 0); -/* - * XXX LLC_{X25,ISO}_LSAP - */ - ASB_OUTB(sc, asb, XMIT_REMSAP, LLC_SNAP_LSAP); - - /* XXX if num_dhb == 2 this should alternate between the two buffers */ - dhb = ARB_INW(sc, arb, ARB_XMT_DHBADDR); - - command = SRB_INB(sc, sc->sc_srb, SRB_CMD); - - if (command == XMIT_XID_CMD || command == XMIT_TEST_CMD) { - ASB_OUTB(sc, asb, XMIT_CMD, command); - ASB_OUTW(sc, asb, XMIT_FRAMELEN, 0x11); -/* - * XXX 0xe == sizeof(struct token_header) - */ - ASB_OUTB(sc, asb, XMIT_HDRLEN, 0x0e); - - SR_OUTB(sc, (dhb + 0), TOKEN_AC); - SR_OUTB(sc, (dhb + 1), TOKEN_FC); - /* Load destination and source addresses. */ - for (i=0; i < ISO88025_ADDR_LEN; i++) { - SR_OUTB(sc, (dhb + 2 + i), 0xff); - SR_OUTB(sc, (dhb + 8 + i), 0x00); - } - } - else { -/* - * XXX what's command here ? command = 0x0d (always ?) - */ - /* if data in queue, copy mbuf chain to DHB */ - IFQ_DEQUEUE(&ifp->if_snd, m0); - if (m0 != 0) { -#if NBPFILTER > 0 - if (ifp->if_bpf) - bpf_mtap(ifp->if_bpf, m0, BPF_DIRECTION_OUT); -#endif - /* Pull packet off interface send queue, fill DHB. */ - trh = mtod(m0, struct token_header *); - hlen = sizeof(struct token_header); - if (trh->token_shost[0] & TOKEN_RI_PRESENT) { -/* - * XXX assumes route info is in the same mbuf as the token-ring header - */ - struct token_rif *rif; - - rif = TOKEN_RIF(trh); - hlen += ((ntohs(rif->tr_rcf) & TOKEN_RCF_LEN_MASK) >> 8); - } - size = tr_mbcopy(sc, dhb, m0); - m_freem(m0); - - ASB_OUTB(sc, asb, XMIT_CMD, XMIT_UI_FRM); - ASB_OUTB(sc, asb, XMIT_HDRLEN, hlen); - - /* Set size of transmission frame in ASB. */ - ASB_OUTW(sc, asb, XMIT_FRAMELEN, size); - } - else { - printf("%s: unexpected empty mbuf send queue\n", - sc->sc_dev.dv_xname); - - /* Set size of transmission frame in ASB to zero. */ - ASB_OUTW(sc, asb, XMIT_FRAMELEN, 0); - } - } -/* - * XXX asb_response(void *asb, len) - */ - /* tell adapter that there is a response in the ASB */ - ACA_SETB(sc, ACA_ISRA_o, RESP_IN_ASB); -} - -/* - * Interrupt handler for fast path transmit complete - */ -void -tr_xint(sc) -struct tr_softc *sc; -{ - u_short tail; - struct ifnet *ifp = &sc->sc_arpcom.ac_if; - bus_size_t txbuf; - - /* - * To prevent race conditions on 8-bit cards when reading or writing - * 16-bit values. See page 4-12 of the IBM manual. - * XXX use volatile ? - */ - do { - tail = TXCA_INW(sc, TXCA_COMPLETION_QUEUE_TAIL); - } while (tail != TXCA_INW(sc, TXCA_COMPLETION_QUEUE_TAIL)); - while (tail != TXCA_INW(sc, TXCA_FREE_QUEUE_TAIL)) { - txbuf = TXCA_INW(sc, TXCA_FREE_QUEUE_TAIL) - XMIT_NEXTBUF; - txbuf = TXB_INW(sc, txbuf, XMIT_NEXTBUF) - XMIT_NEXTBUF; - if (TXB_INB(sc, txbuf, XMIT_RETCODE) != 0) { - ifp->if_oerrors++; - printf("tx: retcode = %x\n", - TXB_INB(sc, txbuf, XMIT_RETCODE)); - } - sc->sc_xmit_buffers += - (TXB_INW(sc, txbuf, XMIT_FRAMELEN) + 514 - 1) / 514; - tail = TXB_INW(sc, txbuf, XMIT_LASTBUF); - TXCA_OUTW(sc, TXCA_FREE_QUEUE_TAIL, tail); - tail = TXCA_INW(sc, TXCA_COMPLETION_QUEUE_TAIL); - do { - tail = TXCA_INW(sc, TXCA_COMPLETION_QUEUE_TAIL); - } while (tail != TXCA_INW(sc, TXCA_COMPLETION_QUEUE_TAIL)); - } - if (sc->sc_xmit_buffers == sc->sc_nbuf) - ifp->if_flags &= ~IFF_OACTIVE; - tr_start(ifp); -} - - -/* - * copy out the packet byte-by-byte in reasonably optimal fashion - */ -int -tr_mbcopy(sc, dhb, m0) -struct tr_softc *sc; -bus_size_t dhb; -struct mbuf *m0; -{ - bus_size_t addr = dhb; - int len, size = 0; - char *ptr; - struct mbuf *m; - - for (m = m0; m; m = m->m_next) { - len = m->m_len; - ptr = mtod(m, char *); - - bus_space_write_region_1(sc->sc_memt, sc->sc_sramh, - addr, ptr, len); - size += len; - addr += len; - } - return (size); -} - -/* - * Pull read data off an interface. - * Len is length of data, with local net header stripped. - * Off is non-zero if a trailer protocol was used, and - * gives the offset of the trailer information. - * XXX trailer information, really ???? - * We copy the trailer information and then all the normal - * data into mbufs. - * - * called from tr_rint - receive interrupt routine - */ -struct mbuf * -tr_get(sc, totlen, ifp) -struct tr_softc *sc; -int totlen; -struct ifnet *ifp; -{ - int len; - struct mbuf *m, *m0, *newm; - - MGETHDR(m0, M_DONTWAIT, MT_DATA); - if (m0 == 0) - return (0); - - m0->m_pkthdr.rcvif = ifp; - m0->m_pkthdr.len = totlen; - len = MHLEN; - - m = m0; - while (totlen > 0) { - if (totlen >= MINCLSIZE) { - MCLGET(m, M_DONTWAIT); - if ((m->m_flags & M_EXT) == 0) { - m_free(m0); - return 0; - } - len = MCLBYTES; - } - - /* - * Make sure data after the MAC header is aligned. - */ - if (m == m0) { - caddr_t newdata = (caddr_t) - ALIGN(m->m_data + sizeof(struct token_header)) - - sizeof(struct token_header); - len -= newdata - m->m_data; - m->m_data = newdata; - } - m->m_len = len = min(totlen, len); - tr_bcopy(sc, mtod(m, char *), len); - totlen -= len; - if (totlen > 0) { - MGET(newm, M_DONTWAIT, MT_DATA); - if (newm == 0){ - m_freem(m0); - return (0); - } - m->m_next = newm; - m = newm; - len = MLEN; - } - /* - * ignore trailers case again - */ - } - return (m0); -} - -/* - * tr_ioctl - process an ioctl request - */ -int -tr_ioctl(ifp, cmd, data) -struct ifnet *ifp; -u_long cmd; -caddr_t data; -{ - struct tr_softc *sc = ifp->if_softc; - struct ifreq *ifr = (struct ifreq *) data; - struct ifaddr *ifa = (struct ifaddr *) data; - int s; - int error = 0; - - s = splnet(); - - switch (cmd) { - case SIOCSIFADDR: - - switch (ifa->ifa_addr->sa_family) { -#ifdef INET - case AF_INET: - /* XXX if not running */ - if ((ifp->if_flags & IFF_RUNNING) == 0) { - tr_init(sc); /* before arp_ifinit */ - tr_sleep(sc); - } - arp_ifinit(&sc->sc_arpcom, ifa); - break; -#endif /* INET */ - default: - /* XXX if not running */ - if ((ifp->if_flags & IFF_RUNNING) == 0) { - tr_init(sc); /* before arpwhohas */ - tr_sleep(sc); - } - break; - } - break; - case SIOCSIFFLAGS: - /* - * 1- If the adapter is DOWN , turn the device off - * ie. adapter down but still running - * 2- If the adapter is UP, turn the device on - * ie. adapter up but not running yet - */ - if ((ifp->if_flags & (IFF_RUNNING | IFF_UP)) == IFF_RUNNING) { - tr_stop(sc); - ifp->if_flags &= ~IFF_RUNNING; - } - else if ((ifp->if_flags & (IFF_RUNNING | IFF_UP)) == IFF_UP) { - tr_init(sc); - tr_sleep(sc); - } - else { -/* - * XXX handle other flag changes - */ - } - break; - case SIOCGIFMEDIA: - case SIOCSIFMEDIA: - error = ifmedia_ioctl(ifp, ifr, &sc->sc_media, cmd); - break; -#ifdef SIOCSIFMTU - case SIOCSIFMTU: - if (ifr->ifr_mtu > sc->sc_maxmtu) - error = EINVAL; - else - ifp->if_mtu = ifr->ifr_mtu; - break; -#endif - default: - error = EINVAL; - } - splx(s); - return (error); -} - - -/* - * tr_bcopy - like bcopy except that it knows about the structure of - * adapter receive buffers. - */ -void -tr_bcopy(sc, dest, len) -struct tr_softc *sc; /* pointer to softc struct for this adapter */ -u_char *dest; /* destination address */ -int len; /* number of bytes to copy */ -{ - struct rbcb *rbc = &sc->rbc; /* pointer to rec buf ctl blk */ - - /* While amount of data needed >= amount in current receive buffer. */ - while (len >= rbc->data_len) { - /* Copy all data from receive buffer to destination. */ - - bus_space_read_region_1(sc->sc_memt, sc->sc_sramh, - rbc->rbuf_datap, dest, (bus_size_t)rbc->data_len); - len -= rbc->data_len; /* update length left to transfer */ - dest += rbc->data_len; /* update destination address */ - - /* Make next receive buffer current receive buffer. */ - rbc->rbufp = rbc->rbufp_next; - if (rbc->rbufp != 0) { /* More receive buffers? */ - - /* Calculate pointer to next receive buffer. */ - rbc->rbufp_next = RB_INW(sc, rbc->rbufp, RB_NEXTBUF); - if (rbc->rbufp_next != 0) - rbc->rbufp_next -= RB_NEXTBUF; - - /* Get pointer to data in current receive buffer. */ - rbc->rbuf_datap = rbc->rbufp + RB_DATA; - - /* Get length of data in current receive buffer. */ - rbc->data_len = RB_INW(sc, rbc->rbufp, RB_BUFLEN); - } - else { - if (len != 0) /* len should equal zero. */ - printf("tr_bcopy: residual data not copied\n"); - return; - } - } - - /* Amount of data needed is < amount in current receive buffer. */ - - bus_space_read_region_1(sc->sc_memt, sc->sc_sramh, - rbc->rbuf_datap, dest, (bus_size_t)len); - rbc->data_len -= len; /* Update count of data in receive buffer. */ - rbc->rbuf_datap += len; /* Update pointer to receive buffer data. */ -} - -/* - * tr_opensap - open the token ring SAP interface - */ -void -tr_opensap(sc, type) -struct tr_softc *sc; -u_char type; -{ - bus_size_t srb = sc->sc_srb; - -/************************************************************************ - ** To use the SAP level interface, we will have to execute a ** - ** DLC.OPEN.SAP (pg.6-61 of the Token Ring Tech. Ref.) after we have ** - ** received a good return code from the DIR.OPEN.ADAPTER command. ** - ** We will open the IP SAP x'aa'. ** - ** ** - ** STEPS: ** - ** 1) Reset SRB response interrupt bit ** - ** 2) Use the open_sap srb. ** - ** 3) Fill the following fields: ** - ** command - x'15' ** - ** sap_value - x'aa' ** - ** sap_options- x'24' ** - ** ** - ***********************************************************************/ - - ACA_RSTB(sc, ACA_ISRP_o, ~(SRB_RESP_INT)); - - SRB_OUTB(sc, srb, SRB_CMD, DLC_OPEN_SAP); - SRB_OUTB(sc, srb, SRB_RETCODE, 0x00); - SRB_OUTW(sc, srb, SRB_OPNSAP_STATIONID, 0x0000); - SRB_OUTB(sc, srb, SRB_OPNSAP_TIMERT1, 0x00); - SRB_OUTB(sc, srb, SRB_OPNSAP_TIMERT2, 0x00); - SRB_OUTB(sc, srb, SRB_OPNSAP_TIMERTI, 0x00); - SRB_OUTB(sc, srb, SRB_OPNSAP_MAXOUT, 0x00); - SRB_OUTB(sc, srb, SRB_OPNSAP_MAXIN, 0x00); - SRB_OUTB(sc, srb, SRB_OPNSAP_MAXOUTINCR, 0x00); - SRB_OUTB(sc, srb, SRB_OPNSAP_MAXRETRY, 0x00); - SRB_OUTB(sc, srb, SRB_OPNSAP_GSAPMAXMEMB, 0x00); - SRB_OUTW(sc, srb, SRB_OPNSAP_MAXIFIELD, 0x0088); - SRB_OUTB(sc, srb, SRB_OPNSAP_SAPVALUE, type); - SRB_OUTB(sc, srb, SRB_OPNSAP_SAPOPTIONS, 0x24); - SRB_OUTB(sc, srb, SRB_OPNSAP_STATIONCNT, 0x01); - SRB_OUTB(sc, srb, SRB_OPNSAP_SAPGSAPMEMB, 0x00); - - ACA_SETB(sc, ACA_ISRP_e, INT_ENABLE); - ACA_SETB(sc, ACA_ISRA_o, CMD_IN_SRB); -} - -/* - * tr_sleep - sleep to wait for adapter to open - */ -void -tr_sleep(sc) -struct tr_softc *sc; -{ - int error; - - error = tsleep(&sc->tr_sleepevent, 1, "trsleep", hz * 30); - if (error == EWOULDBLOCK) - printf("%s: sleep event timeout\n", sc->sc_dev.dv_xname); -} - -void -tr_watchdog(ifp) -struct ifnet *ifp; -{ - struct tr_softc *sc = ifp->if_softc; - - log(LOG_ERR,"%s: device timeout\n", sc->sc_dev.dv_xname); - ++ifp->if_oerrors; - - tr_reset(sc); -} |