/* v35.c * Copyright (C) 1999-2000 by Benedykt Kroplewski * e-mail: mlody@popnet.pl ,tel. 0-501-853172 */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define MTU 1500 #define DOFF 0x10 /* Data offset */ #define ROFF 0x8 /* Registers offset 0x8 */ static long base = 0x00000; #include "bin.h" #include "db.c" int v35_init(struct device *dev); static void v35_interrupt(int irq, void *dev_id, struct pt_regs * regs); static int v35_open(struct device *dev); static int v35_stop(struct device *dev); static int v35_send(struct sk_buff *skb, struct device *dev); static struct net_device_stats *v35_stat(struct device *dev); static const char *version = "v35.c:v1.0 1999 Benedykt Kroplewski (mlody@sic.popnet.pl)\n"; static const char* irqname = "v35card"; static char v35name[10] = {"wan0\0"}; static struct device v35dev = { v35name,0,0,0,0,0,0,0,0,0,NULL,v35_init }; static struct net_device_stats stats; static int irq = 0; MODULE_PARM(irq,"i"); MODULE_PARM(base,"i"); int v35_init(struct device *dev) { int irqval,i; printk("v35_init(%s);\n",dev->name); printk(KERN_DEBUG "%s", version); irqval = request_irq(dev->irq, &v35_interrupt, 0, irqname, dev); if (irqval) { printk("%s: unable to get IRQ %d (irqval=%d).\n",dev->name, dev->irq, irqval); return -EAGAIN; } initcard(dev->base_addr); for(i=0;i<20000;i++) readb(dev->base_addr+DOFF); printk("read 20 000 bytes\n"); dev->open = v35_open; dev->stop = v35_stop; dev->hard_start_xmit = v35_send; dev->get_stats = v35_stat; dev->mtu = 1500; dev->hard_header_len = 0; dev->addr_len = 0; dev->type = ARPHRD_SLIP; dev->tx_queue_len = 10; dev_init_buffers(dev); dev->flags = IFF_NOARP|IFF_POINTOPOINT; return 0; } static void v35_got(struct device *dev,int wielkosc) { struct sk_buff *skb; int i; stats.rx_bytes+=wielkosc-3; skb = dev_alloc_skb(wielkosc-1); skb_put(skb,wielkosc-1); skb->dev = dev; for(i=0;i<=wielkosc-3;i++) *(skb->data+i) = readb(dev->base_addr+DOFF); skb->pkt_type = PACKET_HOST; skb->mac.raw=skb->data; skb->protocol=htons(ETH_P_IP); netif_rx(skb); stats.rx_packets++; } /* numer = numer & BIN00111111; ---> zerowanie pierwszych 2 bitow */ /* numer = numer ^ BIN11000000; ---> zapalanie pierwszych 2 bitow */ static void v35_interrupt(int irq, void *dev_id, struct pt_regs * regs) { struct device *dev = dev_id; unsigned char reg1,reg3,reg7,reg6,znak,tmp; int what_irq=0; int wielkosc=0; int error=0; /* long flags; */ dev->interrupt = 1; /* save_flags(flags); cli(); */ reg3 = readregister(3,dev->base_addr); /******************************* IRQ RX ********************************************************/ if((reg3 & 0x20) == 0x20) { what_irq++; readregister(2,dev->base_addr); do { reg7 = readregister(7,dev->base_addr); reg6 = readregister(6,dev->base_addr); reg1 = readregister(1,dev->base_addr); if((reg1 & 0x10) == 0x10) /* bit 4 */ { writeb(0x30,base+ROFF); error = 4; } /* E4 */ if((reg1 & 0x20) == 0x20) /* bit 5 */ { writeb(0x30,base+ROFF); error = 5; } /* E5 */ if((reg1 & 0x40) == 0x40) /* bit 6 */ { writeb(0x30,base+ROFF); error = 6; } /* E6 */ if((reg1 & 0x80) == 0x80) ; /* bit 7 */ tmp = reg7 & BIN00111111; wielkosc = tmp << 8; wielkosc = wielkosc + reg6; v35_got(dev,wielkosc); znak = readb(dev->base_addr+DOFF); znak = readb(dev->base_addr+DOFF); znak = readb(dev->base_addr+DOFF); reg7 = readregister(7,dev->base_addr); reg7 = readregister(7,dev->base_addr); } while( (reg7 & BIN01000000) == BIN01000000 ); if(error != 0) printk("RX error nr. %d\n",error); writeb(0x38,base+ROFF); printk("v35_interrupt(%s,Rx,%s,SIZE=%d,ERROR=%d);\n",dev->name,char2bin(reg3),wielkosc-3,error); } /************************************ IRQ TX *******************************************************/ if((reg3 & 0x8) == 0x8) { what_irq++; stats.tx_packets++; udelay(1000); dev->tbusy = 0; mark_bh(NET_BH); readregister(2,dev->base_addr); printk("v35_interrupt(%s,Tx,%s);\n",dev->name,char2bin(reg3)); writeb(0x10,base+ROFF); writeb(0x10,base+ROFF); writeb(0x38,base+ROFF); } /***************************** IRQ unknown *********************************************************/ if(what_irq == 0) { readregister(2,dev->base_addr); printk("v35_interrupt(%s,UNKNOWN,%s);\n",dev->name,char2bin(reg3)); writeb(0x10,base+ROFF); writeb(0x10,base+ROFF); writeb(0x38,base+ROFF); } /* restore_flags(flags); */ dev->interrupt = 0; return; } static int v35_open(struct device *dev) { printk("v35_open(%s);\n",dev->name); MOD_INC_USE_COUNT; dev->start = 1; dev->tbusy = 0; return 0; } static int v35_stop(struct device *dev) { printk("v35_stop(%s);\n",dev->name); dev->start = 0; dev->tbusy = 1; free_irq(dev->irq, dev); MOD_DEC_USE_COUNT; return 0; } long flags; static int v35_send(struct sk_buff *skb, struct device *dev) { int len,i; unsigned char *data; dev->trans_start = jiffies; len = skb->len; data = skb->data; if(!dev->interrupt) { save_flags(flags); cli(); for(i=0;i<=len;i++) writeb(*(data+i),dev->base_addr+DOFF); dev->tbusy=1; restore_flags(flags); /* printk("%s: transmit %d bytes\n",dev->name,len); */ stats.tx_bytes+=skb->len; dev->trans_start = jiffies; dev_kfree_skb(skb); } return 0; } static struct net_device_stats *v35_stat(struct device *dev) { return &stats; } int init_module(void) { int result; if(irq == 0) { printk("insmod v35.o irq=NUMER base=ADDRESS\n"); return 1; } if(base == 0) { printk("insmod v35.o irq=NUMER base=ADDRESS\n"); return 1; } v35dev.base_addr = base; v35dev.irq = irq; if((result = register_netdev(&v35dev)) != 0) return result; return 0; } void cleanup_module(void) { printk("cleanup_module();\n"); unregister_netdev(&v35dev); } /* end. */