📄 ltpc.c
字号:
} memset(dev->priv, 0, sizeof(struct ltpc_private)); dev->get_stats = ltpc_get_stats; /* add the ltpc-specific things */ dev->do_ioctl = <pc_ioctl; dev->set_multicast_list = &set_multicast_list; dev->mc_list = NULL; return 0;}static int ltpc_poll_counter;static void ltpc_poll(unsigned long l){ struct net_device *dev = (struct net_device *) l; del_timer(<pc_timer); if(debug&DEBUG_VERBOSE) { if (!ltpc_poll_counter) { ltpc_poll_counter = 50; printk("ltpc poll is alive\n"); } ltpc_poll_counter--; } if (!dev) return; /* we've been downed */ idle(dev); ltpc_timer.expires = jiffies+5; add_timer(<pc_timer);}/* DDP to LLAP translation */static int ltpc_xmit(struct sk_buff *skb, struct net_device *dev){ /* in kernel 1.3.xx, on entry skb->data points to ddp header, * and skb->len is the length of the ddp data + ddp header */ struct net_device_stats *stats = &((struct ltpc_private *)dev->priv)->stats; int i; struct lt_sendlap cbuf; cbuf.command = LT_SENDLAP; cbuf.dnode = skb->data[0]; cbuf.laptype = skb->data[2]; skb_pull(skb,3); /* skip past LLAP header */ cbuf.length = skb->len; /* this is host order */ skb->h.raw=skb->data; if(debug&DEBUG_UPPER) { printk("command "); for(i=0;i<6;i++) printk("%02x ",((unsigned char *)&cbuf)[i]); printk("\n"); } do_write(dev,&cbuf,sizeof(cbuf),skb->h.raw,skb->len); if(debug&DEBUG_UPPER) { printk("sent %d ddp bytes\n",skb->len); for(i=0;i<skb->len;i++) printk("%02x ",skb->h.raw[i]); printk("\n"); } stats->tx_packets++; stats->tx_bytes+=skb->len; dev_kfree_skb(skb); return 0;}static struct net_device_stats *ltpc_get_stats(struct net_device *dev){ struct net_device_stats *stats = &((struct ltpc_private *) dev->priv)->stats; return stats;}/* initialization stuff */ static int __init ltpc_probe_dma(int base){ int dma = 0; int timeout; unsigned long f; if (!request_dma(1,"ltpc")) { f=claim_dma_lock(); disable_dma(1); clear_dma_ff(1); set_dma_mode(1,DMA_MODE_WRITE); set_dma_addr(1,virt_to_bus(ltdmabuf)); set_dma_count(1,sizeof(struct lt_mem)); enable_dma(1); release_dma_lock(f); dma|=1; } if (!request_dma(3,"ltpc")) { f=claim_dma_lock(); disable_dma(3); clear_dma_ff(3); set_dma_mode(3,DMA_MODE_WRITE); set_dma_addr(3,virt_to_bus(ltdmabuf)); set_dma_count(3,sizeof(struct lt_mem)); enable_dma(3); release_dma_lock(f); dma|=2; } /* set up request */ /* FIXME -- do timings better! */ ltdmabuf[0] = LT_READMEM; ltdmabuf[1] = 1; /* mailbox */ ltdmabuf[2] = 0; ltdmabuf[3] = 0; /* address */ ltdmabuf[4] = 0; ltdmabuf[5] = 1; /* read 0x0100 bytes */ ltdmabuf[6] = 0; /* dunno if this is necessary */ inb_p(io+1); inb_p(io+0); timeout = jiffies+100*HZ/100; while(time_before(jiffies, timeout)) { if ( 0xfa == inb_p(io+6) ) break; } inb_p(io+3); inb_p(io+2); while(time_before(jiffies, timeout)) { if ( 0xfb == inb_p(io+6) ) break; } /* release the other dma channel (if we opened both of them) */ if ( (dma&0x2) && (get_dma_residue(3)==sizeof(struct lt_mem)) ){ dma&=1; free_dma(3); } if ( (dma&0x1) && (get_dma_residue(1)==sizeof(struct lt_mem)) ){ dma&=0x2; free_dma(1); } /* fix up dma number */ dma|=1; return dma;}int __init ltpc_probe(struct net_device *dev){ int err; int x=0,y=0; int timeout; int autoirq; unsigned long flags; unsigned long f; SET_MODULE_OWNER(dev); save_flags(flags); /* probe for the I/O port address */ if (io != 0x240 && !check_region(0x220,8)) { x = inb_p(0x220+6); if ( (x!=0xff) && (x>=0xf0) ) io = 0x220; } if (io != 0x220 && !check_region(0x240,8)) { y = inb_p(0x240+6); if ( (y!=0xff) && (y>=0xf0) ) io = 0x240; } if(io) { /* found it, now grab it */ request_region(io,8,"ltpc"); } else { /* give up in despair */ printk ("LocalTalk card not found; 220 = %02x, 240 = %02x.\n", x,y); restore_flags(flags); return -1; } /* probe for the IRQ line */ if (irq < 2) { autoirq_setup(2); /* reset the interrupt line */ inb_p(io+7); inb_p(io+7); /* trigger an interrupt (I hope) */ inb_p(io+6); autoirq = autoirq_report(1); if (autoirq == 0) { printk("ltpc: probe at %#x failed to detect IRQ line.\n", io); } else { irq = autoirq; } } /* allocate a DMA buffer */ ltdmabuf = (unsigned char *) dma_mem_alloc(1000); if (ltdmabuf) ltdmacbuf = <dmabuf[800]; if (!ltdmabuf) { printk("ltpc: mem alloc failed\n"); restore_flags(flags); return(-1); } if(debug&DEBUG_VERBOSE) { printk("ltdmabuf pointer %08lx\n",(unsigned long) ltdmabuf); } /* reset the card */ inb_p(io+1); inb_p(io+3); timeout = jiffies+2*HZ/100; while(time_before(jiffies, timeout)) ; /* hold it in reset for a coupla jiffies */ inb_p(io+0); inb_p(io+2); inb_p(io+7); /* clear reset */ inb_p(io+4); inb_p(io+5); inb_p(io+5); /* enable dma */ inb_p(io+6); /* tri-state interrupt line */ timeout = jiffies+100*HZ/100; while(time_before(jiffies, timeout)) { /* wait for the card to complete initialization */ } /* now, figure out which dma channel we're using, unless it's already been specified */ /* well, 0 is a legal DMA channel, but the LTPC card doesn't use it... */ if (dma == 0) { dma = ltpc_probe_dma(io); if (!dma) { /* no dma channel */ printk("No DMA channel found on ltpc card.\n"); restore_flags(flags); return -1; } } /* print out friendly message */ if(irq) printk("Apple/Farallon LocalTalk-PC card at %03x, IR%d, DMA%d.\n",io,irq,dma); else printk("Apple/Farallon LocalTalk-PC card at %03x, DMA%d. Using polled mode.\n",io,dma); /* seems more logical to do this *after* probing the card... */ err = ltpc_init(dev); if (err) return err; dev->base_addr = io; dev->irq = irq; dev->dma = dma; /* the card will want to send a result at this point */ /* (I think... leaving out this part makes the kernel crash, so I put it back in...) */ f=claim_dma_lock(); disable_dma(dma); clear_dma_ff(dma); set_dma_mode(dma,DMA_MODE_READ); set_dma_addr(dma,virt_to_bus(ltdmabuf)); set_dma_count(dma,0x100); enable_dma(dma); release_dma_lock(f); (void) inb_p(io+3); (void) inb_p(io+2); timeout = jiffies+100*HZ/100; while(time_before(jiffies, timeout)) { if( 0xf9 == inb_p(io+6)) break; } if(debug&DEBUG_VERBOSE) { printk("setting up timer and irq\n"); } if (irq) { /* grab it and don't let go :-) */ (void) request_irq( irq, <pc_interrupt, 0, "ltpc", dev); (void) inb_p(io+7); /* enable interrupts from board */ (void) inb_p(io+7); /* and reset irq line */ } else { /* polled mode -- 20 times per second */ /* this is really, really slow... should it poll more often? */ init_timer(<pc_timer); ltpc_timer.function=ltpc_poll; ltpc_timer.data = (unsigned long) dev; ltpc_timer.expires = jiffies + 5; add_timer(<pc_timer); restore_flags(flags); } return 0;}#ifndef MODULE/* handles "ltpc=io,irq,dma" kernel command lines */static int __init ltpc_setup(char *str){ int ints[5]; str = get_options(str, ARRAY_SIZE(ints), ints); if (ints[0] == 0) { if (str && !strncmp(str, "auto", 4)) { /* do nothing :-) */ } else { /* usage message */ printk (KERN_ERR "ltpc: usage: ltpc=auto|iobase[,irq[,dma]]\n"); return 0; } } else { io = ints[1]; if (ints[0] > 1) { irq = ints[2]; } if (ints[0] > 2) { dma = ints[3]; } /* ignore any other paramters */ } return 1;}__setup("ltpc=", ltpc_setup);#endif /* MODULE */static struct net_device dev_ltpc;#ifdef MODULEMODULE_LICENSE("GPL");MODULE_PARM(debug, "i");MODULE_PARM(io, "i");MODULE_PARM(irq, "i");MODULE_PARM(dma, "i");int __init init_module(void){ int err, result; if(io == 0) printk(KERN_NOTICE "ltpc: Autoprobing is not recommended for modules\n"); /* Find a name for this unit */ dev_ltpc.init = ltpc_probe; err=dev_alloc_name(&dev_ltpc,"lt%d"); if(err<0) return err; if ((result = register_netdev(&dev_ltpc)) != 0) { printk(KERN_DEBUG "could not register Localtalk-PC device\n"); return result; } else { if(debug&DEBUG_VERBOSE) printk("0 from register_netdev\n"); return 0; }}#endifstatic void __exit ltpc_cleanup(void){ long timeout; ltpc_timer.data = 0; /* signal the poll routine that we're done */ if(debug&DEBUG_VERBOSE) printk("freeing irq\n"); if(dev_ltpc.irq) { free_irq(dev_ltpc.irq,&dev_ltpc); dev_ltpc.irq = 0; } if(del_timer(<pc_timer)) { /* either the poll was never started, or a poll is in process */ if(debug&DEBUG_VERBOSE) printk("waiting\n"); /* if it's in process, wait a bit for it to finish */ timeout = jiffies+HZ; add_timer(<pc_timer); while(del_timer(<pc_timer) && time_after(timeout, jiffies)) { add_timer(<pc_timer); schedule(); } } if(debug&DEBUG_VERBOSE) printk("freeing dma\n"); if(dev_ltpc.dma) { free_dma(dev_ltpc.dma); dev_ltpc.dma = 0; } if(debug&DEBUG_VERBOSE) printk("freeing ioaddr\n"); if(dev_ltpc.base_addr) { release_region(dev_ltpc.base_addr,8); dev_ltpc.base_addr = 0; } if(debug&DEBUG_VERBOSE) printk("free_pages\n"); free_pages( (unsigned long) ltdmabuf, get_order(1000)); ltdmabuf=NULL; ltdmacbuf=NULL; if(debug&DEBUG_VERBOSE) printk("unregister_netdev\n"); unregister_netdev(&dev_ltpc); if(debug&DEBUG_VERBOSE) printk("returning from cleanup_module\n");}module_exit(ltpc_cleanup);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -