📄 if_gn.c
字号:
#ifndef lintstatic char sccsid[] = "@(#)if_gn.c 1.1 92/07/30 SMI";#endif/* * Copyright (c) 1988 by Sun Microsystems, Inc. *//* * if_gn.c * * Sun Generic Network Controller Interface * * This generic network standalone driver adheres to the * llcp specification, and includes the additional llcp * files: * hllcputils.c * hportllcp.c */#ifdef PROMCODE #include <strings.h>#include <signal.h> #include "../h/types.h"#include "../h/sunromvec.h"#include "../h/cpu.map.h"#include "../h/eeprom.h"#include "../dev/llcp.h"#include "../dev/saio.h"#include "../dev/param.h"#include "../h/socket.h"#include <net/if.h>#include <netinet/in.h>#include <netinet/if_ether.h>#include "../h/globram.h" #else#include <strings.h>#include <sys/signal.h> #include <sys/types.h>#include <mon/sunromvec.h>#include <sunif/llcp.h>#include <stand/saio.h>#include <stand/param.h>#include <sys/socket.h>#include <net/if.h>#include <netinet/in.h>#include <netinet/if_ether.h>#include <mon/cpu.map.h>#include <mon/eeprom.h>#endif PROMCODE#ifndef PROMCODEstruct ether_addr net_mac_addr; /* our net address */struct ether_addr *gn_mac_addr = &net_mac_addr;#endifstruct gn_softc { char es_scrat[PROTOSCRATCH]; /* work space for nd */ llcp_info_t es_llcp; /* LLCP information structure */ llcp_cntrlr_info_t cinfo; /* controller info on host */ llcp_host_info_t hinfo; /* host info on controller */ char *dataaddr; /* addr of I/O or dma space */}; /* device information */ /* * Note that these addresses are hard-coded here * to facilitate bringup in the case the the * eeprom was incorrectly set-up or was not * initialized at all. These addresses are * unique to the first generation fddi controller * and esthetically do not belong here. * (ie. It hurt, but it makes everyone's life * easier.) * Note: these variables are externs in the file gn_inf.c */u_long gnaddrs[] = { 0x16c0020, 0x18c0020, 0x1ac0020, 0x1cc0020 };#ifndef PROMCODEu_char gnmemtype[] = { ID_VME, ID_VME, ID_VME, ID_VME };#define NGNADDR (sizeof(gnaddrs) / sizeof(gnaddrs[0]))int gnctlrnum;struct devinfo gninfo = { sizeof (llcp_reg_t), /* size of io space */ 0, /* size of dma space */ sizeof(struct gn_softc), /* size of local bytes */ NGNADDR, /* # of standard addresses */ gnaddrs, /* vector of standard addrs */ MAP_VME32A32D, /* map space 32 bit VME bus I/O */ 0, /* transfer size handled by ND */};#endif PROMCODE /* external interfaces */int gnopen(), gnclose();extern int xxprobe();extern char *resalloc();#ifdef PROMCODEint nullsys();extern int tftpboot();#else PROMCODEextern int xxboot(), etherstrategy(), gnstats();#endifstruct boottab gndriver = {#ifdef PROMCODE "gn", xxprobe, tftpboot, gnopen, gnclose, nullsys, #else PROMCODE "gn", xxprobe, xxboot, gnopen, gnclose, etherstrategy, #endif "gn: Sun Generic Network", &gninfo,}; /* ethernet routines */int gnxmit(), gnpoll(), gnreset(), my_mac_addr();struct saif gnif = { gnxmit, gnpoll, gnreset, my_mac_addr#ifndef PROMCODE , gnstats#endif PROMCODE};/* * Description: Open Generic Network nd connection * Synopsis: status = gnopen(sip) * status :(int) = pass value from etheropen * -1 = error * sip :(char *) point to saio structure * * Routines: gninit, etheropen, gnclose */intgnopen(sip)struct saioreq *sip;{ int result; sip->si_sif = &gnif; /* set interface pointers */ if ( gninit(sip) || (result = etheropen(sip)) < 0 ) { printf("gn: open failed\n"); gnclose(sip); /* must close interface */ return (-1); } return (result);} /* gnopen *//* * Description: This routine sets up dma or I/O space and goes through * llcp init sequence. * * Synopsis: status = gninit(sip) * status :(int) 0 = complete * 1 = error * sip :(char *) point to saio structure * Routines: gnreset */intgninit(sip)struct saioreq *sip;{ register struct gn_softc *es; llcp_cntrlr_info_t *cinfoptr; register int retry = 5; /* up to 5 retries */#ifdef PROMCODE int gnctlrnum = gp->g_ctlr_number;#else PROMCODE /* for broken code that sets si_ctlr from controller * number to an address behind the scenes */ for (gnctlrnum=0; gnctlrnum < NGNADDR; gnctlrnum++) if (gnaddrs[gnctlrnum] == sip->si_ctlr) break;#endif PROMCODE es = (struct gn_softc *)sip->si_devdata; /* pt to local space */#ifdef DEBUG printf("Entering gninit sip = 0x%x es = 0x%x\n",sip,es);#endif /* * stuff es_softc structure */ es->es_llcp.cinfop = cinfoptr = &es->cinfo; /* this setup needed for */ es->es_llcp.hinfop = &es->hinfo; /* generic llcp routines */ /* base address of llcp registers */ es->es_llcp.regp = (llcp_reg_t *)sip->si_devaddr; if ( gnmemtype[gnctlrnum] == ID_VME ) cinfoptr->memtyp = SHARED_MEM; else cinfoptr->memtyp = DMA_MEM; if ( cinfoptr->memtyp == DMA_MEM ) /* if dma, alloc space */ cinfoptr->buf = (u_char *)resalloc(RES_DMAMEM, LLCP_BUF_SIZ); else /* clr addr of llcp buf */ cinfoptr->buf = (u_char *)0; cinfoptr->timeout = LLCP_T_RESET; /* initial cmd timeout val*/ if( init_host(sip) == LLCP_FAIL ) /* initialize hinfo struct*/ return(0); /* * retries for simply initiating communication * with the network controller */ while( --retry ) { if ( gnreset(es) == 0 ) /* llcp reset and init */ return(0); /* return success */ if ( (cinfoptr->memtyp == SHARED_MEM) ) { /* * Need to release memory here berfore we try * again but since we are the only ones running, * there is no routine available to release alloc'd * space. If there are a ton of resets, we might * run out of space. */ cinfoptr->buf = (u_char *)0; /* rezero buf */ es->es_llcp.hinfop->buf = (u_char *)0; } } return(1); /* return failure */} /* gninit *//* * Description: Basic Generic Network llcp initialization * Goes through the llcp initialization sequence. * * Synopsis: status = gnreset(es) * status :(int) 0 = complete * 1 = error * es :(char *) pointer to ethernet structure */intgnreset(es) register struct gn_softc *es;{ char *physaddr; llcp_cntrlr_info_t *cinfoptr = es->es_llcp.cinfop; llcp_host_info_t *hinfoptr = es->es_llcp.hinfop;#ifdef PROMCODE int gnctlrnum = gp->g_ctlr_number;#endif PROMCODE char *devalloc();#ifdef DEBUG printf("Entering gnreset es = 0x%x\n",es);#endif if ( llcp_reset(&es->es_llcp) == LLCP_FAIL ) return(1); /* return error */ if ( strt_init(&es->es_llcp) == LLCP_FAIL ) return(1); /* return error */ /* * If we have a shared memory interface, then use the physical address * returned by the controller to map a virtual address to. */ if ( (cinfoptr->memtyp == SHARED_MEM) ) { /* * to get the actual physical address of the buffer area, * need to or in the base address of the llcp registers * without any offset into the page. */ physaddr = (char *)(gnaddrs[gnctlrnum] + cinfoptr->phys_addr); cinfoptr->buf = (u_char *)devalloc(MAP_VME32A32D, physaddr, LLCP_BUF_SIZ); hinfoptr->buf = cinfoptr->buf; }#ifdef DEBUG printf("after strt_init: phys_addr=0x%x mapped addr = 0x%x\n", cinfoptr->phys_addr,cinfoptr->buf);#endif if ( get_info(&es->es_llcp) == LLCP_FAIL ) return(1); /* return error */ /* check if user specified address to be provided by controller */ if (hinfoptr->partition & 0x20) { /* save the MAC address from the controller */ bcopy((char *)cinfoptr->net_laddr,(char *)gn_mac_addr, sizeof(struct ether_addr)); bcopy((char *)cinfoptr->net_laddr, (char *)hinfoptr->net_laddr, sizeof(struct ether_addr)); } else { /* else use host MAC address */ myetheraddr((struct ether_addr *)gn_mac_addr); bcopy((char *)gn_mac_addr, (char *)cinfoptr->net_laddr, sizeof(struct ether_addr)); bcopy((char *)gn_mac_addr, (char *)es->es_llcp.hinfop->net_laddr, sizeof(struct ether_addr)); } if ( send_info(&es->es_llcp) == LLCP_FAIL ) return(1); /* return error */ if ( ena_net(&es->es_llcp) == LLCP_FAIL ) return(1); /* return error */#ifdef DEBUG printf("GNRESET SUCCEEDED !! \n");#endif return(0); /* reset succeeded */} /* gnreset *//* * Description: * Transmits a packet of data. Waits for a maximum time as * specified in the controller info structure. Returns 1 for * error and 0 otherwise. If an error occurs, prints a msg * to the console. * * Synopsis: status = gnxmit(es, buf, count) * es :(char *) pointer to ethernet structure * buf :(char *) pointer to buffer * count :(int) character count * Routines: iesimple, bzero, bcopy */gnxmit(es, buf, count)register struct gn_softc *es;char *buf;int count;{ if ( llcp_send_pkt(&es->es_llcp, buf, count) == LLCP_FAIL ) { printf("gn: xmit failed\n"); return(1); /* return error */ } return(0); /* command completed successfully */} /* gnxmit *//* * Description: * polls for a packet of data for a maximum time as specified * in the controller info structure. Returns 0 for no packet * or an error, otherwise returns the length of the packet * Upon command completion if an error occurs, prints a message * to the console. * * Synopsis: status = lepoll(es, buf) * status :(int) 0 = no packet yet * >0 = length of received packet * es :(char *) pointer to ethernet structure * buf :(char *) pointer of receiving buffer * Routines: */intgnpoll(es, buf)register struct gn_softc *es;char *buf;{ return( llcp_get_pkt(&es->es_llcp, buf) );} /* gnpoll *//* * Description: Close down Lance ethernet device * Synopsis: status = gnclose(sip) * status :(void) * sip :(char *) pointer to saioreq structure */gnclose(sip)struct saioreq *sip;{ if ( llcp_reset(&((struct gn_softc *)(sip->si_devdata))->es_llcp) == LLCP_FAIL ){ printf("gn: close failed\n"); return(1); /* return error */ } return(0); /* return successful */} /* gnclose *//* * init_host - XXX - sets up hinfo structures. This routine will * probably be a focal point for future revisions to llcp. */init_host(sip)struct saioreq *sip;{#ifdef PROMCODE int gnctlrnum = gp->g_ctlr_number;#endif PROMCODE register struct gn_softc *es = (struct gn_softc *)sip->si_devdata; llcp_host_info_t *hinfoptr = es->es_llcp.hinfop; hinfoptr->len = sizeof(llcp_host_info_t); /* len of structure */ hinfoptr->llcp_ver = LLCP_VERSION; /* version of llcp */ hinfoptr->addrtyp = LONG_ADDR; /* type of net addr */ /* MAC address initialized during getinfo handshake */ hinfoptr->memtyp = es->es_llcp.cinfop->memtyp; /* type of memory */ hinfoptr->buf = es->es_llcp.cinfop->buf; /* hinfoptr->prom_rev = *romp->op_mon_id; /* host prom revision */ hinfoptr->prom_rev = 1; /* host prom revision */ hinfoptr->ctlr = gnctlrnum; /* cntrlr num */ hinfoptr->unit = sip->si_unit; /* Unit num in cntrlr */ hinfoptr->partition = (long) sip->si_boff; /* Partition num */ return(LLCP_SUCC);} /* init_host *//* * my_mac_addr - stuffs the current MAC address into the network address * pointer passed. */my_mac_addr(ea)struct ether_addr *ea;{ bcopy((char *)gn_mac_addr, (char *)ea, sizeof(struct ether_addr)); } /* my_mac_addr */#ifndef PROMCODEgnstats(){ /* XXX implement sometime */}#endif PROMCODE
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -