/* File new.c : packet driver interface */ /* Copyright (C) 1992 Indian Institute of Technology, Bombay Written by V. Srinivas and Vishwas Joglekar, Dept of Computer Science and Engineering. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 1, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "yapcbr.h" #include "ipxwatch.h" /* extern int access_type(int pkt_drv_int,unsigned if_class, unsigned if_type, unsigned if_number, char far *type, unsigned *typelen, char (far *receiver)()); */ int release_type (int intno,int handle); int get_address (int intno,int handle,unsigned char *buf,int len); int send_pkt (int intno,unsigned char *buf,int len); int set_rcv_mode (int intno,int handle,int mode); char *receiver(int phandle, int rflag, WORD plen, char *pbuffer); int driver_info(int pkt_drv_int,int *version, unsigned *class, unsigned *type, unsigned char *number, char *name, char *functionality); static char Pkt_sig[] = "PKT DRVR"; /* Packet driver signature */ extern int rx_head,rx_tail,tmp_tail, overflow_flag,rx_count; extern struct rxstruct rx[]; extern unsigned int rcv_count,lost_count; extern struct ipxpktdv Ipxpktdv; /* Packet driver receiver routine. Called from an assembly program (sup1.asm) that pushes the caller's parameters the stack so we can access and modify them. */ char *receiver(int phandle, int rflag, WORD plen, char *pbuffer) { switch(rflag){ case 0: /* buffer request call */ if(rx_count == (MAX_QSIZ-1)) { /* no buffer space, return NULL */ lost_count++; return((char *)NULL); } Ipxpktdv.tmp_tail = rx_tail; rx_tail++; if(rx_tail == MAX_QSIZ) rx_tail=0; rx_count++; return((char *)&rx[Ipxpktdv.tmp_tail].rcv_buffer); case 1: rx[Ipxpktdv.tmp_tail].rcv_flag = SET; rx[Ipxpktdv.tmp_tail].len = plen; rcv_count++; /* number of packets received */ /* return(&rx[Ipxpktdv.tmp_tail].rcv_buffer); */ break; default: break; } } /* Initialise the packet driver * softvec: software interrupt vector, e.g., 0x60 * net_name: interface label, e.g., "seg#0" * Ether type, ETHERNET_II or IEEE802_3 */ int pkt_init(unsigned char *soft_vec,unsigned char *net_name,int ether_type) { unsigned char class,number,functionality; unsigned int version,typ; int intno; unsigned int pkt_len; char catch_all[] = {0x0}; char far *nm; char novell_type[] ={0x81,0x37}; /* pkt type is Novell's IPX */ char far *pkt_type; unsigned char my_net[] = {0x00,0x00,0x00,0x00}; int i,handle; long drvvec; char sig[8]; /* Copy of driver signature "PKT DRVR" */ unsigned char tmp[25]; /* Check whether there is a packet driver at the specified interrupt vector */ intno = hex_toascii(soft_vec); drvvec = (long)getvect(intno); movblock(FP_OFF(drvvec)+3, FP_SEG(drvvec), FP_OFF(sig),FP_SEG(sig),strlen(Pkt_sig)); if(strncmp(sig,Pkt_sig,strlen(Pkt_sig)) != 0){ printf("No packet driver found at int 0x%x\n",intno); return -1; } Ipxpktdv.intno = intno; Ipxpktdv.dev = 0; if(driver_info(intno,&version, &class, &typ, &number, &nm,&functionality) == -1){ fprintf(stderr,"Error initialising pkt driver\n"); exit(-1); } if(class != 1){ fprintf(stderr,"Only class 1 drivers supported\n"); exit(-1); } Ipxpktdv.ether_type = ether_type; pkt_len = 2; /* catch only pkts of type 8137h */ pkt_type = novell_type; /* cprintf("Packet driver tionality=%d, nm=%Fs \n",version,class,typ,number,functionality,nm);*/ if((handle=access_type(intno,class,typ,number,pkt_type,pkt_len,receiver))== -1){ fprintf(stderr,"Error initialising packet driver \n"); exit(-1); } Ipxpktdv.handle = handle; set_rcv_mode(intno,handle,0); /* turn off receiver */ get_address(intno,handle,Ipxpktdv.eaddr,EADDR_LEN); if(Ipxpktdv.eaddr[0] & 1){ fprintf(stderr,"Warning! Multicast address bit set : %s",Ipxpktdv.eaddr); exit(-1); } tmp[0] = '\0'; prnt_hex(Ipxpktdv.eaddr,tmp,6); cprintf("\r\n My Ethernet Address is %s \r\n",tmp); Ipxpktdv.class = class; /* set my network address to 00000000 */ memcpy(Ipxpktdv.net_id,my_net,4); return 0; } int send_pkt(int intno,unsigned char *buf,int len) { union REGS regs; struct SREGS sregs; segread(&sregs); sregs.ds = FP_SEG(buf); regs.x.si = FP_OFF(buf); regs.x.cx = len; regs.h.ah = SEND_PKT; int86x(intno,®s,®s,&sregs); if(regs.x.cflag) return -1; else return 0; } /* get the physical address of the interface */ int get_address(int intno,int handle,unsigned char *addr,int len) { union REGS regs; struct SREGS sregs; segread(&sregs); sregs.es = FP_SEG(addr); regs.x.di = FP_OFF(addr); regs.x.cx = len; regs.x.bx = handle; regs.h.ah = GET_ADDRESS; int86x(intno,®s,®s,&sregs); if(regs.x.cflag) return -1; else return 0; } int set_rcv_mode(int intno,int handle,int mode) { union REGS regs; regs.h.ah = SET_RCV_MODE; regs.x.bx = handle; regs.x.cx = mode; regs.x.dx = 00; int86(intno,®s,®s); if(regs.x.cflag) return -1; else return 0; } int release_type(int intno,int handle) { union REGS regs; regs.x.bx = handle; regs.h.ah = RELEASE_TYPE; int86(intno,®s,®s); if(regs.x.cflag) return -1; else return 0; }