#include #include #include #include #include #include #include "lancemem.h" #include "lancedrv.h" #include "pktqueue.h" #include "pktdrv.h" #include "cookie.h" #include "inetcust.h" #define noDEBUG #define noDEBUGINTR #define DEBUGPKT #define noDEBUGFREECNT int retval; int term = 0; #define TIMEOUTCNT 10000 /* count down for lance to come up */ short new_stack[ISTACKSIZE/2]; /* interrupt stack */ char *old_stack; /* must be immediately behind new_stack */ void ( *ihandler )(void) = NULL; /* pointer to interrupt handler */ long old_pterm; long lnc_vector = LANCEIVEC * sizeof(char *); int lnc_reset(void); /* reset lance, init datastructures */ void lnc_intr(void); /* interrupt handler */ void memcopy(register char *,register char *,register int); /* own memcopy routine */ void (* old_berr)(); /* old bus error handler */ extern void berr_catch(void); /* bus error handler for ST/STE */ extern void berr_tt_catch(void); /* bus error handler for TT */ int memok; volatile TMD *tmd_sent; /* last sent packet */ PKTBUF *pkt_ring[RECVBUFFS]; /* pointers to packets waiting for recv */ int pkt_recv; /* index of buufer receiving next packet */ PKTPOOL *p_free; /* queue of free packets */ u_short freecnt; /* number of free packets */ volatile int pkt_sent = 0; /* flag if pkt is successfully sent */ HADDR my_haddr; /* my hardware address */ procref ext_tab[8] = /* subfunction table */ { net_reset, net_open, net_release, net_send, net_getadr, net_info, (procref)net_pktalloc, net_pktfree }; PROTOCOL protos[MAXPROTOCOLS]; /* protocols to serve */ int protocols = 0; /* number of active protocols */ et_stat stat; /* statistics block */ long net_resets(void); int read_inf(void) { COOKIE *cookie; cookie = get_cookie(INETCUSTCOOKIE); if(!cookie || !cookie->val) return(0); memcopy(my_haddr,((INETCUST *)(cookie->val))->haddr,(int)sizeof(HADDR)); return(1); } int net_info(int len, char *buf) { if(!buf) return(0); if(buf == (char *)1L) { lnc_reset(); return(0); } stat.st_free = freecnt; memcopy(buf,(char *)&stat,(size_t)len= MAXPROTOCOLS) return(EPROTAVAIL); new = -1; #ifdef RESET_ON_OPEN if(!protocols) { net_resets(); if(ihandler == NULL) return(EINIT); } #endif for(i=0; i (char *)PPOOL)) return(EPARAM); rdp = RCP_RDP; pkt_sent = 0; if(len < 60) len = 60; if(len > (int)sizeof(PACKET)) return(EPKTLEN); *(rdp+1) = CSR0; if(!(*rdp & CSR0_TXON)) return(EINIT); tmd = (TMD *)tmd_sent; if((tmd->tmd1 & OWN) == OWN_CHIP) return(EINIT); tmd->ladr = (u_short)(buf); /* point to packet to send */ tmd->tmd2 = -len; tmd->tmd3 = 0; tmd->tmd1 = (STP | ENP | OWN_CHIP); /* start/end of packet */ timeout = clock() + 3*TIMEOUT; while(!pkt_sent && !tmd->tmd3 && clock() < timeout); /* wait till packet sent */ if(clock() > timeout) return(ETIMEOUT); if(tmd->tmd3 || pkt_sent < 0) return(ECOLLISION); return(len); } int net_getadr(int len, char *buf) { register LNCMEM *mem; if(len>=(int)sizeof(HADDR)) { mem = (LNCMEM *)RCP_MEMBOT; buf[0] = mem->init.haddr[1]; buf[1] = mem->init.haddr[0]; buf[2] = mem->init.haddr[3]; buf[3] = mem->init.haddr[2]; buf[4] = mem->init.haddr[5]; buf[5] = mem->init.haddr[4]; return((int)sizeof(HADDR)); } return(0); } long net_resets(void) { int i; for(i=0;i (PKTBUF *)PPOOL)) { #ifdef DEBUGPKT Cconws("Packet out of band\r\n"); #endif return(FALSE); } if(((long)p_pkt - (long)PPKT) % sizeof(PKTBUF)) { #ifdef DEBUGPKT Cconws("Packet misaligned\r\n"); #endif return(FALSE); } if(ap_putpkt(p_free,p_pkt)) { freecnt++; return(TRUE); } return(FALSE); } /*******************************************************************/ /*******************************************************************/ #ifdef DEBUG char str[40]; #endif void lnc_intr(void) { register int csr0; register int type; register int i; register int *rdp; register et_stat *et_stat; register TMD *md; register PKTBUF *pkt; rdp = RCP_RDP; /* register data port */ *(rdp+1) = CSR0; csr0 = *rdp; if(!(csr0 & CSR0_INTR)) return; et_stat = &stat; #ifdef DEBUGINTR if(protocols>0) { strcpy(str,"pkt intr: "); itoa(csr0,str+strlen(str),16); strcat(str,"\r\n"); Cconws(str); } #endif et_stat->st_err = csr0; et_stat->st_intr++; if(csr0 & CSR0_IDON) *(rdp) = CSR0_IDON; else if(csr0 & CSR0_RINT) { do { (RMD *)md = &PRMD[pkt_recv]; *rdp = CSR0_RINT; if(!(((RMD *)md)->rmd1 & ERR)) /* packet ok */ { /* pkt = pkt_ring[pkt_recv]; */ pkt = (PKTBUF *)((long)RCP_MEMBOT+(((RMD *)md)->ladr)); type = pkt->et_type; et_stat->st_received++; if(protocols > 0) { #ifdef DEBUG itoa(type,str,16); Cconws(str); Cconws(" from "); ltoa((long)pkt,str,16); Cconws(str); Cconws("\r\n"); #endif for(i=0;i 0) { /* must have one packet free */ if(protos[i].handler && protos[i].handler(((RMD *)md)->mcnt,(char *)pkt)) { /* retrieve one packet for receive */ pkt_ring[pkt_recv] = ap_getpkt(ET_FREE,p_free); freecnt--; /* set new receive packet */ ((RMD *)md)->ladr = (u_short)(pkt_ring[pkt_recv]); et_stat->st_got++; protos[i].recvd++; } break; } } } } else { if(((RMD *)md)->rmd1 & CRC) et_stat->st_crc++; lnc_reset(); return; } ((RMD *)md)->mcnt = 0; /* free packet */ ((RMD *)md)->rmd1 = OWN_CHIP; /* give packet back to lance */ pkt_recv++; if(pkt_recv >= RECVBUFFS) pkt_recv = 0; } while((PRMD[pkt_recv].rmd1 & OWN) == OWN_HOST); } else if(csr0 & CSR0_TINT) { md = (TMD *)tmd_sent; if((md->tmd1 & OWN) == OWN_HOST) /* packet given back to host */ { if((md->tmd1) & ERR) { pkt_sent = -1; et_stat->st_xmiterr++; } else { pkt_sent = 1; et_stat->st_sent++; if(md->tmd1 & (MORE | ONE | DEF)) et_stat->st_collision++; } } else et_stat->st_xmiterr++; *rdp = CSR0_TINT; /* clear interrupt bit */ } else if(csr0 & CSR0_ERR) { et_stat->st_missed++; *(rdp+1) = 0; *rdp = CSR0_CERR | CSR0_MERR | CSR0_BABL | CSR0_MISS; } *(rdp+1) = CSR0; *rdp = CSR0_INEA; } int lnc_reset(void) { register LNCMEM *mem; register TMD *md; register u_long i; register int *rdp; rdp = RCP_RDP; *(rdp+1) = CSR0; *rdp = CSR0_STOP; /* init data structures */ mem = (LNCMEM *)RCP_MEMBOT; mem->init.mode = 0; /* mode word */ mem->init.haddr[5] = my_haddr[4]; mem->init.haddr[4] = my_haddr[5]; mem->init.haddr[3] = my_haddr[2]; mem->init.haddr[2] = my_haddr[3]; mem->init.haddr[1] = my_haddr[0]; mem->init.haddr[0] = my_haddr[1]; mem->init.laf[0] = 0; /* logical adress filter */ mem->init.laf[1] = 0; /* logical adress filter */ mem->init.rdrp.drp_lo = (u_short)offsetof(LNCMEM,rmd[0]); /* ((u_long)&(PRMD[0])); */ /* receive ring descr. pointer */ mem->init.rdrp.drp_hi = 0; mem->init.rdrp.len = RECVRLEN; mem->init.tdrp.drp_lo = (u_short)offsetof(LNCMEM,tmd); /* ((u_long)&PTMD); */ /* transmit ring descr. pointer */ mem->init.tdrp.drp_hi = 0; mem->init.tdrp.len = XMITRLEN; md = &mem->tmd; md->ladr = 0; /* dont know adress of packet to send */ md->tmd1 = OWN_HOST; md->tmd2 = 0; /* zero pkt size */ md->tmd3 = 0; for(i=0; i< RECVBUFFS; i++) { (RMD *)md = mem->rmd+i; ((RMD *)md)->ladr = (u_short)((char *)pkt_ring[i]); ((RMD *)md)->rmd1 = OWN_CHIP; ((RMD *)md)->rmd2 = -MAXPKTLEN; /* 2's complement (maximum size) */ ((RMD *)md)->mcnt = 0; } tmd_sent = &mem->tmd; pkt_recv = 0; *(rdp+1) = CSR3; *rdp = CSR3_BSWP; *(rdp+1) = CSR2; *rdp = 0; *(rdp+1) = CSR1; *rdp = 0; *(rdp+1) = CSR0; *rdp = CSR0_STRT | CSR0_INIT; i = TIMEOUTCNT * 100; do { if(*rdp & CSR0_IDON) break; }while(--i > 0); if(i<=0 || (*rdp & CSR0_ERR)) { *rdp = CSR0_STOP; ihandler = NULL; return(EINIT); } ihandler = lnc_intr; *rdp = CSR0_IDON; /* clear idon-bit */ *rdp = CSR0_INEA; /* enable interrupts */ return(0); } main() { COOKIE *cookie; void (*call)(void); Cconws("\r\nPacket driver V1.1 for RieblCard Plus "); cookie = get_cookie(PKTCOOKIE); if(cookie) { (long)call = ((long *)cookie->val)[NETRESET]; call(); /* reset network */ Cconws("\r\nexisting driver reset\r\n"); return(0); } memok = 0; old_berr = Setexc(2,(void (*)())(-1)); cookie = get_cookie(MACHINECOOKIE); if(!cookie || ((cookie->val >> 16) != 2)) Setexc(2,berr_catch); else Setexc(2,berr_tt_catch); *RCP_MEMBOT=0xaa; Setexc(2,old_berr); if(memok) { Cconws("\r\nEthernet Card NOT found\r\n\a"); return(0); } if(!read_inf()) { Cconws("INETCUST not installed !!\r\n"); } else { #ifdef DEBUGFREECNT Cconws("freecnt at 0x"); Cconws(ltoa((long)&freecnt,(char *)new_stack,16)); Cconws("\r\n\a\a"); #endif ihandler = NULL; Supexec(lnc_install); if(net_reset() < 0) { Setexc(LANCEIVEC, (void (*)())old_intr); Cconws("Cannot init Ethernet Card\r\n\a"); return(0); } add_cookie(PKTCOOKIE,(long)ext_tab); Cconws("installed\r\n(c) hw,pm fortec 1991,1992\r\n"); Ptermres(_PgmSize,0); } return(0); }