📄 if_ln.c
字号:
#ifndef lintstatic char *sccsid = "@(#)if_ln.c 4.14 (ULTRIX) 4/11/91";#endif lint/************************************************************************ * * * Copyright (c) 1984-1989 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. * * * * This software is derived from software received from the * * University of California, Berkeley, and from Bell * * Laboratories. Use, duplication, or disclosure is subject to * * restrictions under license agreements with University of * * California and with AT&T. * * * * 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: * * 04/11/91 Randall Brown * Before stopping the lance on 3min, disable DMA on I/O ASIC * * 02/24/91 jsd * Allow loopback packets if COPYALL mode is set * * 01/21/91 Randall Brown * Moved code for cpyin4x4 and cpyout4x4 into if_ln_copy.s for * performance improvement. * * 01/01/91 Chran-Ham Chang * Change the code to allow the driver promisc mode to be disabled * after enabling it. * * 12/06/90 Randall Brown * Fixed a bug in the 4x4() routines dealing with small mbufs not on 8 * boundarys. The routines would return an incorrect lrbptr. * * 10/15/90 Randall Brown * Fixed a bug in probe routine for 3min's with large memory configs. * Changed a svtolance32 to svtophy. * * 8/31/90 Lea Gottfredsen * Turned on cacheing for 3min, added clean_dcache calls, and added * DMA memory read error interrupt check in lnintr * * 08/19/90 Fred L. Templin * Fixed setting of "IFF_UP" and "IFF_RUNNING" bits. * * 7/11/90 Lea Gottfredsen * Added 3min support: 3max-like version and DMA version with funky * 4 word read/writes with skips in between. * * 03/26/90 Paul Grist * Added support to lnprobe for mipsmate -- DS_5100. * * 12/19/89 Chran-Ham Chang * Added code to fixed the panic problem when the incoming packet does * not turn on the start packet bit. * * 11/16/89 Chran-Ham Chang * Added code to print out the station address at the system boot time. * * 11/15/89 Chran-Ham Chang * Fixed the unaligned access problem for the 802.2 LLC transmit * frame. * * 11/14/89 Chran-Ham Chang * Fixed 3MAX probing problem. * * 10/27/89 Uttam Shikarpur * Added: * 1) Ability to report back the type of network interface. * 2) Counters to keep track of the multicast pack., bytes sent. * * 9/22/89 Chran-Ham Chang * Fixed collisions counters problem. Merged 3MAX version to the * pool. * * 9/11/89 afd * Bug fixes from testing on KMAX. Set up to really run on 3MAX. * * 31/8/89 Chran-Ham Chang * Added code to check the mbuf return from lnget(). In addition, * Added code to restart the LANCE, if the STP bit not found for * the first incoming packet. * * 8/7/89 Lea Gottfredsen * Added 3max support. * An interim version with 3max disguised * as a PMAX in order to test a specially configured PMAX that * has a 3max IO module. * Also, changed multi unit handling in lnprobe, removed next. * * 7/17/89 Chran-Ham Chang * Merged se DMA receiver architecture into ln driver. * Changed ifnet name from se to ln. * * 6/29/89 Lea Gottfredsen * Merged packet filter and SMP back into this new * lance driver. Merge of pu and isis pools. Multi-unit support. * * 5/2/89 Lea Gottfredsen * Added lnsw structure to provide ease of multi architecture * implementation and readablity. * Mipsfair support. * * The following comments are a subset of the ones found in the two * old versions of if_ln.c and if_se.c * * 6/2/89 Uttam Shikarpur * Add support for Ethernet packet filter * * 9/21/88 U. Sinkewicz * Added locks for SMP. * * 6/8/88 lp * PMAX * * 04-01-88 Fred L. Templin * Several changes from initial version. Now up and running with * Mayfair II. * * 01-04-88 templin (Fred L. Templin) * Created the if_ln.c module. This module is based on * a modified version of if_se.c * * 6-May-88 - 10-Feb-8 Fred Templin * Several enhancements, performance improvements and bug fixes * * 15-Feb-88 fred (Fred Canter) * Changes for VAX420 (CVAXstar/PVAX) support. * * 18-Jun-86 jsd (John Dustin) * Created this VAXstar network controller driver. * For Ethernet Lance chip implementation. * Derived from if_qe.c. * * --------------------------------------------------------------------- */#include "ln.h"#if NLN > 0 || defined(BINARY)/* * Digital LANCE Network Interface */#include "packetfilter.h" /* NPACKETFILTER */#include "../data/if_ln_data.c"extern struct protosw *iftype_to_proto(), *iffamily_to_proto();extern struct timeval time;extern int net_output();#ifdef vaxextern struct nexus nexus[];#elsevolatile unsigned long *rdpptr;char *nexus;#endifextern int cpu;extern struct lnsw mayfairsw[], ffoxsw[], vaxstarsw[];typedef volatile unsigned char * pvoluchar;int lndebug = 0; /* debug flag, range 0->4 */int lnprobe(), lnattach(), lnintr();int lninit(), lnstart(), lnioctl(), lnwatch();struct mbuf *lnget(), *lnget_dma();u_short lnstd[] = { 0 };struct uba_driver lndriver = { lnprobe, 0, lnattach, 0, lnstd, "ln", lninfo };u_char ln_sunused_multi[6] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };unsigned long ln_crc_table[16]; /* crc initialization table */unsigned int ln_poly = 0xedb88320; /* polynomial initialization */#define LRBADDR(start,off) (((int)(start))&0x01 ? \ (caddr_t)((int)(start)+(off*2)+ \ (off%2)): \ ((caddr_t)((int)(start)+(off*2)- \ (off%2))))/* * Probe the Lance to see if it's there */lnprobe(reg,ui) caddr_t reg; struct uba_device *ui; /* Only for MIPS machine */{ static int unit=0; /* Walk thru softc's only for VAX */ register struct ln_softc *sc; register struct lnsw *lnsw; /* ptr to switch struct */ register struct ln_initb *initb; /* LRB initb ptr */ int prp; /* physical addr ring pointer */ int pi; /* physical addr init block */ int i, j, oldcvec,index; unsigned int tmp, x; unsigned short flag; char buf[TC_ROMNAMLEN + 1]; KM_ALLOC(sc,struct ln_softc *, sizeof(struct ln_softc),KM_DEVBUF, KM_CLEAR); if (!sc) return(0); /* * CPU identifiers are found in cpuconf.h */ switch (cpu) { case VAX_3400: /* mayfair II */ ln_softc[unit] = sc; sc->lnsw = lnsw = mayfairsw; sc->rdpaddr = (struct lnreg *)(&((struct ni_regs *)reg)->ni_rdp); sc->rapaddr = (struct lnreg *)(&((struct ni_regs *)reg)->ni_rap); sc->ln_narom = (u_long *)(((struct ni_regs *)reg)->ni_sar); sc->ln_lrb = (u_char *)(((struct ni_regs *)reg)->ni_nilrb); sc->is_if.if_sysid_type = 60; flag = (LN_IDON | LN_INIT); break; case DS_5400: /* mipsfair */ unit = ui->ui_unit; ln_softc[unit] = sc; sc->lnsw = lnsw = ds5400sw; sc->rdpaddr = (struct lnreg *)PHYS_TO_K1(lnsw->ln_phys_rdp); sc->rapaddr = (struct lnreg *)PHYS_TO_K1(lnsw->ln_phys_rap); sc->ln_narom = (u_long *)PHYS_TO_K1(lnsw->ln_phys_narom); sc->ln_lrb = (pvoluchar)PHYS_TO_K1(lnsw->ln_phys_lrb); sc->is_if.if_sysid_type = 94; flag = (LN_IDON | LN_INIT); break; case DS_5000: /* 3max */ case DS_5000_100: /* 3min */ unit = ui->ui_unit; ln_softc[unit] = sc; sc->is_if.if_sysid_type = (cpu == DS_5000_100 ? 118 : 94); tc_addr_to_name(reg, buf); if (!strcmp(buf,"PMAD-AA ")) { /* 3max like */ sc->lnsw = lnsw = ds5000sw; sc->rdpaddr = (struct lnreg *)((u_long)reg + lnsw->ln_phys_rdp); sc->rapaddr = (struct lnreg *)((u_long)reg + lnsw->ln_phys_rap); sc->ln_narom = (u_long *)((u_long)reg + lnsw->ln_phys_narom); sc->ln_lrb = (pvoluchar)((u_long)reg + lnsw->ln_phys_lrb); flag = (LN_IDON | LN_INIT); } else { /* PMAD_BA, DMA version */ sc->lnsw = lnsw = ds3minsw; sc->rdpaddr = (struct lnreg *)PHYS_TO_K1(lnsw->ln_phys_rdp); sc->rapaddr = (struct lnreg *)PHYS_TO_K1(lnsw->ln_phys_rap); sc->ln_narom = (u_long *)PHYS_TO_K1(lnsw->ln_phys_narom); sc->ssraddr = (u_long *)PHYS_TO_K1(lnsw->ln_phys_ssr); sc->siraddr = (u_long *)PHYS_TO_K1(lnsw->ln_phys_sir); sc->ldpaddr = (u_long *)PHYS_TO_K1(lnsw->ln_phys_ldp); KM_ALLOC(sc->ln_lrb,pvoluchar,LN_LRB_SIZE, KM_DEVBUF, KM_CLEAR); if (!sc->ln_lrb) return(0); while (svtophy(sc->ln_lrb) & 0xffff) sc->ln_lrb++; /* 64K align */ /* enable IOASIC to do lance DMA */ *(u_int *)(sc->ssraddr) |= BIT16SET; /* next is really svtoioasic */ *(sc->ldpaddr) = (((svtophy(sc->ln_lrb)) & LDPBITS) << 3 ); flag = (LN_IDON | LN_INIT); } break; case DS_3100: /* pmax */ case DS_5100: /* mipsmate */ unit = ui->ui_unit; ln_softc[unit] = sc; sc->lnsw = lnsw = pmaxsw; sc->rdpaddr = (struct lnreg *)PHYS_TO_K1(lnsw->ln_phys_rdp); sc->rapaddr = (struct lnreg *)PHYS_TO_K1(lnsw->ln_phys_rap); sc->ln_narom = (u_long *)PHYS_TO_K1(lnsw->ln_phys_narom); sc->ln_lrb = (pvoluchar)PHYS_TO_K1(lnsw->ln_phys_lrb); flag = (LN_IDON | LN_INIT); sc->is_if.if_sysid_type = (cpu == DS_3100 ? 67 : 94); break; case VAX_60: /* firefox */ ln_softc[unit] = sc; sc->lnsw = lnsw = ffoxsw; sc->rdpaddr = (struct lnreg *)(&((struct ni_regs *)reg)->ni_rdp); sc->rapaddr = (struct lnreg *)(&((struct ni_regs *)reg)->ni_rap); sc->ln_narom = (u_long *)(((struct ni_regs *)reg)->ni_sar); sc->ln_lrb = (u_char *)(((struct ni_regs *)reg)->ni_nilrb); flag = (LN_IDON | LN_INIT); sc->is_if.if_sysid_type = 39; break;#ifdef vax case VAXSTAR: /* vs2000 */ case C_VAXSTAR: /* pvax */ ln_softc[unit] = sc; sc->lnsw = lnsw = vaxstarsw; sc->rdpaddr = (struct lnreg *)(&(((struct nb1_regs *)qmem)->nb_ni_rdp)); sc->rapaddr = (struct lnreg *)(&(((struct nb1_regs *)qmem)->nb_ni_rap)); sc->ln_narom = (u_long *)(((struct nb_regs *)nexus)->nb_narom); sc->ln_lrb = (u_char *)( &ln_lrb[unit][0] ); flag = (LN_IDON | LN_INIT | LN_INEA); sc->is_if.if_sysid_type = 39; /* system network interrupt */ ((struct nb_regs *)nexus)->nb_int_msk |= LN_INT_NP ; break;#endif vax default: printf("lnprobe : cpu type %d unknown\n", cpu ); return(0); } unit++; /* for VAX architecture multiple units */ sc->ln_rap = LN_CSR0; sc->ln_rdp = LN_STOP; /* * start lrb_offset to point to first byte of the local RAM * buffer. lnalloc bumps pointer as chunks of the buffer are * allocated. */ sc->lrb_offset = 0; /* * Initialize some per unit counters */ sc->callno = 0; lnshowmulti = 0; lnbablcnt=0; lnmisscnt=0; lnmerrcnt=0; lnrestarts=0; /* * Allocate contiguous, quadword aligned (required) * space for both descriptor rings. "lnalloc" takes into account * the "alignment factor" for LRB sizing. */ for (i=0; i<nLNNRCV; i++) { sc->rring[i] = lnsw->ln_alloc(sc,sizeof(struct ln_ring), (i==0?LN_QUAD_ALIGN : 0)); if (sc->rring[i] == NULL) { printf("ln%d: lnalloc: cannot alloc memory for recv descriptor rings\n", unit-1); return(0); } } for (i=0; i<nLNNXMT; i++) { sc->tring[i] = lnsw->ln_alloc(sc,sizeof(struct ln_ring), (i==0 ? LN_QUAD_ALIGN : 0)); if (sc->tring[i] == NULL) { printf("ln%d: lnalloc: cannot alloc memory for xmit descriptor rings\n", unit-1); return(0); } } /* * Allocate local RAM buffer memory for the init block */ sc->initbaddr = lnsw->ln_alloc(sc, sizeof(struct ln_initb), LN_WORD_ALIGN); if (sc->initbaddr == NULL) { printf("ln%d: lnalloc: cannot alloc memory for init block\n", unit-1); return(0); } /* * Initialize multicast address array. Number of active entries * is driven by number of "ADDMULTI" operations. (1, initailly). */ for (i=0; i<nLNMULTI; i++) { sc->muse[i] = 0; bcopy(ln_sunused_multi,&sc->multi[i],MULTISIZE); } sc->nmulti = 0; /* * Initialize Lance chip with init block, ln_initb * ln_mode; mode word ln_sta_addr; station address ln_multi_mask; multicast address mask ln_rcvlist_lo, ln_rcvlist_hi; rcv descriptor addr ln_rcvlen; rcv length ln_xmtlist_lo, ln_xmtlist_hi; xmt descriptor addr ln_xmtlen; xmt length */ initb = &sc->ln_initb; initb->ln_mode = 0; /* normal operation (mode==0) */ /* * fill out station address from the narom */ for (i = j = 0; i < 3; i++, j += 2) { initb->ln_sta_addr[i] = (short)((sc->ln_narom[j]>>lnsw->ln_na_align)&0xff); initb->ln_sta_addr[i] |= (short)(((sc->ln_narom[j+1]>>lnsw->ln_na_align)&0xff)<<8); } /* * fill out multicast address mask */ for (i = 0; i < 4; i++) { initb->ln_multi_mask[i] = 0x0000; } /* * initialize the multicast address CRC table, * using initb as a dummy variable. */ for (index=0; !(unit-1) && index<16; index++) { tmp = index; for (j=0; j<4; j++) { x = (tmp & 0x01); tmp = (tmp >> 1); /* logical shift right 1 bit */ if (x == 1) tmp = (tmp ^ ln_poly); /* XOR */ } ln_crc_table[index] = tmp; } /* * Convert VAX Virtual to LANCE relative */ prp = lnsw->ln_svtolance(sc->rring[0]); initb->ln_rcvlist_lo = (short)prp & 0xffff; initb->ln_rcvlist_hi = (char)(((int)prp >> 16) & 0xff); initb->ln_rcvlen = RLEN; /* Also clears rcvresv */ prp = lnsw->ln_svtolance(sc->tring[0]); initb->ln_xmtlist_lo = (short)prp & 0xffff; initb->ln_xmtlist_hi = (char)(((int)prp >> 16) & 0xff); initb->ln_xmtlen = TLEN; /* Also clears xmtresv */ lnsw->ln_cpyout(initb,sc->initbaddr,sizeof(struct ln_initb),0); /* * get physical address of init block for Lance */ /* set-up CSR 1 */ sc->ln_rap = LN_CSR1; pi = lnsw->ln_svtolance(sc->initbaddr); sc->ln_rdp = (short)(pi & 0xffff); /* set-up CSR 2 */ sc->ln_rap = LN_CSR2; sc->ln_rdp = (short)(((int)pi>>16) & 0xff); /* hi 8 bits */ sc->ln_rap = LN_CSR0; /* * clear IDON by writing 1, and start INIT sequence */ sc->ln_rdp = flag ; /* wait for init done */ j=0; while (j++ < 100) { if ((sc->ln_rdp & LN_IDON) != 0) break; DELAY(10000); } /* make sure got out okay */ if ((sc->ln_rdp & LN_IDON) == 0) { if (sc->ln_rdp & LN_ERR) { printf("ln%d: initialization error, csr = %04x\n",unit-1,(sc->ln_rdp & 0xffff)); } else { printf("ln%d: cannot initialize Lance\n",unit-1); } return(0); /* didn't interrupt */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -