📄 if_fza.c
字号:
#ifndef lintstatic char *sccsid = "@(#)if_fza.c 4.14 (ULTRIX) 4/30/91";#endif lint/************************************************************************ * * * Copyright (c) 1988 by * * Digital Equipment Corporation, Maynard, MA * * All rights reserved. * * * * This software is furnished under a license and may be used and * * copied only in accordance with the terms of such license and * * with the inclusion of the above copyright notice. This * * software or any other copies thereof may not be provided or * * otherwise made available to any other person. No title to and * * ownership of the software is hereby transferred. * * * * The information in this software is subject to change without * * notice and should not be construed as a commitment by Digital * * Equipment Corporation. * * * * Digital assumes no responsibility for the use or reliability * * of its software on equipment which is not supplied by Digital. * * * ************************************************************************//*----------------------------------------------------------------------- * Modification History: * * 02-APR-91 jsd * Allow packets to be looped back if COPYALL mode is set * * 27-FEB-91 chc * Added code to make the interface state consitently before and * after the EEPROM update. * * 19-DEC-90 chc * Fixed the counter initialization problem. Also allow to * read counter while the adapter is in the MAINTENANCE * state. * * 31-Oct-90 chc * Added code to fix the SMT chained and SMT 6.2 duplicated * address detected problems. Also added code to support the * read status. * * 5-Oct-90 chc * Added code to sync the firmware and fixed the counter. * * 7-Sep-90 chc * Added code to support FDDI MIB * * 9-Aug-90 chc (Chran-Ham Chang) * Bugs Fixed and support the EEPROM update * * 27-Apr-90 chc (Chran-Ham Chang) * Created the if_fza.c module * Derived from if_xna.c. * *---------------------------------------------------------------------- */#include "fza.h"#if NFZA > 0 || defined(BINARY)#include "packetfilter.h" /* NPACKETFILTER */#include "../data/if_fza_data.c"#include "../h/types.h"#include "../h/errlog.h"extern struct protosw *iftype_to_proto(), *iffamily_to_proto();extern struct timeval time;int fzaattach(), fzaintr(), fzaprobe(),fzastart();int fzainit(),fzaioctl(),fzareset(),fzawatch();u_short fzastd[] = { 0 };struct uba_driver fzadriver = { fzaprobe, 0 ,fzaattach, 0 , fzastd, "fza", fzainfo };extern int net_output();struct mbuf *fzamkparam();FZACMDRING *fzamkcmd();u_char fza_dbeacon[] = {0x01, 0x80, 0xc2, 0x00, 0x01, 0x00};u_char fza_rpurge[] = {0x09, 0x00, 0x2b, 0x02, 0x01, 0x05};u_char fza_notset[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};int fzadebug = 0 ;int dludebug = 0 ;#define XMTSEGSIZE 512#define FZAMCLGET(m) { \ register struct mbuf *p; \ MGET((m), M_DONTWAIT, MT_DATA); \ if ((m)) { \ MCLGET((m), p); \ if (p == 0) { \ m_freem((m)); \ (m) = (struct mbuf *)NULL; \ } \ } \}#define FZATIMEOUT(cp,timeout ) { \ register int s = splnet(); \ register long sec0 = time.tv_sec; \ while ( !(cp->own) && ((time.tv_sec - sec0) < 15 )); \ if ( !(cp->own) ) \ timeout = 1; \ splx(s); \}/* * Probe the FZA to see if there * */fzaprobe(reg,ui) caddr_t reg; struct uba_device *ui;{ register struct fza_softc *sc = &fza_softc[ui->ui_unit]; register int delay; union fzacmd_buf *cmdpt; FZARCVRING *rp; FZAXMTRING *tp; struct rmbuf *bp; struct mbuf *m,*m1; int unit = ui->ui_unit; caddr_t mp; int i; sc->basereg = PHYS_TO_K1((u_long)reg); /* fill out the register address and others */ sc->resetaddr = (struct fzareg *)(sc->basereg + FZA_RESET); sc->ctlaaddr = (struct fzareg *)(sc->basereg + FZA_CTL_A); sc->ctlbaddr = (struct fzareg *)(sc->basereg + FZA_CTL_B); sc->intraddr = (struct fzareg *)(sc->basereg + FZA_INT_EVENT); sc->maskaddr = (struct fzareg *)(sc->basereg + FZA_INT_MASK); sc->statusaddr = (struct fzareg *)(sc->basereg + FZA_STATUS ); /* fill out the cmd and unsolicited ring address */ sc->cmdring = (FZACMDRING *)(sc->basereg + FZACMD_PHY_ADDR); sc->unsring = (FZACMDRING *)(sc->basereg + FZAUNS_PHY_ADDR); /* turn on the driver active mode */ sc->reg_ctlb = FZA_ACTIVE ; /* Clear the interrupt event register */ sc->reg_mask = FZA_INTR_MASK; sc->reg_intr = sc->reg_intr; wbflush(); /* * perform the adapter self test */ if(!fzaselftest(sc,unit)) { printf("fza%d: fzaprobe selftest fail \n",unit); return(0); } /* set the interrup mask */ sc->reg_mask = FZA_INTR_MASK; /* * Allocate space for the ctrblk, initblk and statusblk */ KM_ALLOC(mp, caddr_t, 512 * 3 , KM_DEVBUF, KM_NOW_CL_CO_CA); if (mp == 0) { printf("fza%d: Couldn't allocate memory for internal structure\n", unit); return(0); } sc->ctrblk = (struct _fzactrs *)mp; sc->initblk = (struct fzainit *)(mp + 512); sc->statusblk = (struct fzastatus *)(mp + 512 * 2); /* * initialize all the indexes * * sc->tindex == index of next transmit desc. to activate * sc->ltindex == index of last transmit processed * sc->nxmit == # of transmit pending * sc->rindex == index of next recv. descriptor to activate * sc->tsmtindex == index of next SMT tansmit to CNS * sc->rsmtindex == index of next SMT receive from CNS * sc->cmdindex == index of next command desc. to activate * sc->lcmdindex == index of last comman processed * sc->unsindex == index of next unsolicited desc. to activate */ sc->tindex = sc->nxmit = sc->rindex = 0; sc->tsmtindex = sc->rsmtindex = 0; sc->cmdindex = sc->unsindex = 0; sc->ltindex = sc->lcmdindex = -1; sc->smtrmcindex = sc->lsmtrmcindex = 0; sc->initflag = 1; /* * We are now guaranteed that the port has succesfully completed * self test and is in the "UNINITIALIZED" state. At this point, * we can prepare a command buffer to issue the INIT command * */ if(!fzacmdinit(sc,unit)) { printf("fzaprobe init command fail \n",unit); KM_FREE(mp,KM_DEVBUF); return(0); } sc->reg_intr = sc->reg_intr; /* * get the initial value from the INIT command * fill out the init value */ fzafillinit(sc,sc->initblk); sc->reg_mask = FZA_INTR_MASK; /* * put two multicast addresses : * * Ring Purger : 09-00-2b-02-01-05 * Directed Beacon : 01-80-c2-00-01-00 */ bcopy(fza_rpurge,&sc->is_multi[0][0],6); bcopy(fza_dbeacon,&sc->is_multi[1][0],6); sc->is_muse[0] = sc->is_muse[1] = 1; /* * allocate mbufs for receive ring */ for (i = 0, rp = &sc->rring[0], bp = &sc->rmbuf[0]; (i < NFZARCV ); i++, rp++, bp++) { FZAMCLGET(m) if(m) { FZAMCLGET(m1) if (m1) { fzainitdesc(rp, bp, m, m1); } else { goto fail; break; } } else { goto fail; break; } } /* * clear the transmit ring mbuf entry */ for ( i=0, tp = &sc->tring[0]; i < sc->nrmcxmt ; i++, tp++) tp->xmt_mbuf = (struct mbuf *)0; return (sizeof(struct fza_softc));fail: KM_FREE(mp,KM_DEVBUF); for (i = 0, bp = &sc->rmbuf[0]; (i < NFZARCV ); i++, bp++) { if(bp->mbufa != NULL) m_freem(bp->mbufa); if(bp->mbufb != NULL) m_freem(bp->mbufb); } printf("fza%d: fzaprobe fail - can not allocate enough receive buffer",unit); return(0); }/* * Interface exists: make available by filling in network interface * record. System will initialize the interface when it is ready * to accept packets. */fzaattach(ui) struct uba_device *ui;{ register struct fza_softc *sc = &fza_softc[ui->ui_unit]; register struct ifnet *ifp = &sc->is_if; struct sockaddr_in *sin; register int i; /* initialize the lock */ lockinit(&sc->lk_fza_softc, &lock_device15_d); ifp->if_unit = ui->ui_unit; ifp->if_name = "fza"; ifp->if_mtu = FDDIMTU; ifp->if_flags |= IFF_BROADCAST|IFF_DYNPROTO|IFF_802HDR| IFF_NOTRAILERS; ifp->if_type = IFT_FDDI; ifp->lk_softc = &sc->lk_fza_softc; ((struct arpcom *)ifp)->ac_ipaddr.s_addr = 0; ifp->if_sysid_type = 119; /* * Initialize multicast address table */ for (i = 2; i < NMULTI; i++) { bcopy((caddr_t)etherbroadcastaddr, sc->is_multi[i], 6); sc->is_muse[i] = 0; } /* * Set maxlen for the SMT receive queue; attach interface */ sc->is_smt.ifq_maxlen = IFQ_MAXLEN; sin = (struct sockaddr_in *)&ifp->if_addr; sin->sin_family = AF_INET; ifp->if_output = net_output; ifp->if_start = fzastart; ifp->if_init = fzainit; ifp->if_ioctl = fzaioctl; ifp->if_reset = fzareset; ifp->if_watchdog = fzawatch; ifp->if_timer = 1; ifp->d_affinity = ALLCPU; /* * Hook up the device interrupt vector to begin allowing interrupts. * We know that the device has been successfully initialized at this * point. Initialize if_version string. */ bcopy("DEC DEFZA FDDI Interface", ifp->if_version, 25); ifp->if_version[25] = '\0'; printf("fza%d: %s, hardware address %s ROM rev %c%c%c%c Firmware rev %c%c%c%c \n", ifp->if_unit, ifp->if_version, ether_sprintf(sc->is_dpaddr), sc->phy_rev[0],sc->phy_rev[1],sc->phy_rev[2],sc->phy_rev[3], sc->fw_rev[0],sc->fw_rev[1],sc->fw_rev[2],sc->fw_rev[3]);#if NPACKETFILTER > 0 attachpfilter(&(sc->is_ed));#endif NPACKETFILTER if_attach(ifp);}/* * Initialize interface. May be called by a user process or a software * interrupt scheduled by fzareset(). */fzainit(unit) int unit;{ register struct fza_softc *sc = &fza_softc[unit]; register union fzacmd_buf *xcmd; register struct mbuf *m; register int delay; FZACMDRING *cp; struct ifnet *ifp = &sc->is_if; int i, s, t,timeout=0; /* not yet, if address still unknown */ if (ifp->if_addrlist == (struct ifaddr *)0) return; if (ifp->if_flags & IFF_RUNNING) return; /* * Lock the softc to ensure coherency of softc data needed to fill * out the command buffers by "fzamkcmd". */ t = splnet(); s = splimp(); smp_lock(&sc->lk_fza_softc, LK_RETRY); /* clear the interrupt event register */ sc->reg_intr = sc->reg_intr; wbflush(); /* * Issue the MODCAM command to set up the CAM addresses */ if(cp=fzamkcmd(sc,CMD_MODCAM,unit)) { smp_unlock(&sc->lk_fza_softc); splx(s); FZATIMEOUT(cp,timeout) s = splimp(); smp_lock(&sc->lk_fza_softc,LK_RETRY); if(timeout) { printf ("fza%d: port modify CAM command timeout \n", unit); goto done; } else if ( cp->status_id != CMD_SUCCESS ) { printf("fza%d: port init failed\n", unit); goto done; } } else { printf("fza%d: port init failed\n", unit); goto done; } /* * Issue a "PARAM" command to fill in the initial * system parameters. Wait for completion, * which will be signaled by the interrupt handler. */ if(cp=fzamkcmd(sc, CMD_PARAM, unit)) { smp_unlock(&sc->lk_fza_softc); splx(s); FZATIMEOUT(cp,timeout) s = splimp(); smp_lock(&sc->lk_fza_softc, LK_RETRY); if(timeout) { printf ("fza%d: port PARAM command timeout \n", unit); goto done; } else if ( cp->status_id != CMD_SUCCESS ) { printf("fza%d: port init failed\n", unit); goto done; } } else { printf("fza%d: port init failed\n", unit); goto done; } if (ifp->if_flags & IFF_PROMISC) { if (cp =fzamkcmd(sc, CMD_MODPROM,ifp->if_unit)) { smp_unlock(&sc->lk_fza_softc); splx(s); FZATIMEOUT(cp,timeout) if(timeout) { printf ("fza%d: port MODPROM command timeout \n",unit); goto done; } else if (cp->status_id != CMD_SUCCESS) { printf("fza%d: port init failed\n", unit); goto done; } } else { printf("fza%d: port init failed\n", unit); goto done; } } /* * Mark interface up and running; start output * on device. */ sc->is_if.if_flags |= (IFF_UP|IFF_RUNNING); sc->is_if.if_flags &= ~IFF_OACTIVE; if(sc->initflag) { sc->ztime = time.tv_sec; sc->initflag = 0; } if (sc->is_if.if_snd.ifq_head) fzastart(unit); /* queue output packets */done: /* * Relinqusih softc lock, drop IPL. */ smp_unlock(&sc->lk_fza_softc); splx(s); splx(t); if(fzadebug > 0 ) PRT_REG(sc) return;}/* * FZA start routine. Strings output packets and SMT output packets * onto the transmit ring. */fzastart(unit) int unit;{ register FZAXMTRING *tp; register struct mbuf *m; register int index; struct fza_softc *sc = &fza_softc[unit]; struct ifnet *ifp = &sc->is_if; FZAXMTRING *tpstart; struct mbuf *m0; int last,totlen; u_long tmp; /* * Process the transmit queues. */ for (index = sc->tindex, tp = &sc->tring[index] ; index !=sc->ltindex && !(tp->own & FZA_RMC_OWN) ; index = ++index % sc->nrmcxmt , tp = &sc->tring[index]) {next_m: if (sc->is_if.if_snd.ifq_head ) { IF_DEQUEUE(&sc->is_if.if_snd, m0); } else { sc->tindex = index; return; } /* * get the total packet size and check the owner ship * bit for the required number of RMC descriptors */ m = m0; totlen = 0; while (m) { totlen += m->m_len ; m = m->m_next; } /* * two bytes Preamble and one byte starting delimiter */ if ( totlen > FDDIMAX ) { /* * drop this packet for size too long * */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -