📄 daynaport.c
字号:
return -ENOMEM; } /* OK, we are certain this is going to work. Setup the device. */ ei_status.name = model_name; ei_status.word16 = word16; ei_status.tx_start_page = WD_START_PG; ei_status.rx_start_page = WD_START_PG + TX_PAGES; dev->rmem_start = dev->mem_start + TX_PAGES*256; ei_status.stop_page = (dev->mem_end - dev->mem_start)/256; dev->rmem_end = dev->mem_end; if(promoff==-1) /* Use nubus resources ? */ { if(nubus_ethernet_addr(dev->irq /* slot */, dev->dev_addr)) { printk("mac_ns8390: MAC address not in resources!\n"); return -ENODEV; } } else /* Pull it off the card */ { int i=0; int x=1; /* These should go in the end I hope */ if(type==NS8390_DAYNA) x=2; if(type==NS8390_INTERLAN) x=4; while(i<6) { dev->dev_addr[i]=*prom; prom+=x; if(i) printk(":"); printk("%02X",dev->dev_addr[i++]); } } printk(" %s, IRQ %d, shared memory at %#lx-%#lx.\n", model_name, dev->irq, dev->mem_start, dev->mem_end-1); switch(type) { case NS8390_DAYNA: /* Dayna card */ /* 16 bit, 4 word offsets */ ei_status.reset_8390 = &ns8390_no_reset; ei_status.block_input = &dayna_block_input; ei_status.block_output = &dayna_block_output; ei_status.get_8390_hdr = &dayna_get_8390_hdr; ei_status.reg_offset = fwrd4_offsets; break; case NS8390_FARALLON: case NS8390_APPLE: /* Apple/Asante/Farallon */ /* 16 bit card, register map is reversed */ ei_status.reset_8390 = &ns8390_no_reset; ei_status.block_input = &slow_sane_block_input; ei_status.block_output = &slow_sane_block_output; ei_status.get_8390_hdr = &slow_sane_get_8390_hdr; ei_status.reg_offset = back4_offsets; break; case NS8390_ASANTE: /* 16 bit card, register map is reversed */ ei_status.reset_8390 = &ns8390_no_reset; ei_status.block_input = &sane_block_input; ei_status.block_output = &sane_block_output; ei_status.get_8390_hdr = &sane_get_8390_hdr; ei_status.reg_offset = back4_offsets; break; case NS8390_INTERLAN: /* Interlan */ /* 16 bit card, map is forward */ ei_status.reset_8390 = &interlan_reset; ei_status.block_input = &sane_block_input; ei_status.block_output = &sane_block_output; ei_status.get_8390_hdr = &sane_get_8390_hdr; ei_status.reg_offset = back4_offsets; break; case NS8390_KINETICS: /* Kinetics */ /* 8bit card, map is forward */ ei_status.reset_8390 = &ns8390_no_reset; ei_status.block_input = &sane_block_input; ei_status.block_output = &sane_block_output; ei_status.get_8390_hdr = &sane_get_8390_hdr; ei_status.reg_offset = back4_offsets; break; default: panic("Detected a card I can't drive - whoops\n"); } dev->open = &ns8390_open; dev->stop = &ns8390_close_card; NS8390_init(dev, 0); return 0;}static int ns8390_open(struct device *dev){ ei_open(dev); MOD_INC_USE_COUNT; return 0;}static void ns8390_no_reset(struct device *dev){ if (ei_debug > 1) printk("Need to reset the NS8390 t=%lu...", jiffies); ei_status.txing = 0; if (ei_debug > 1) printk("reset not supported\n"); return;}static int ns8390_close_card(struct device *dev){ if (ei_debug > 1) printk("%s: Shutting down ethercard.\n", dev->name); ei_close(dev); MOD_DEC_USE_COUNT; return 0;}struct nubus_device_specifier nubus_8390={ ns8390_probe, NULL};/* * Interlan Specific Code Starts Here */static void interlan_reset(struct device *dev){ unsigned char *target=nubus_slot_addr(dev->irq); if (ei_debug > 1) printk("Need to reset the NS8390 t=%lu...", jiffies); ei_status.txing = 0; /* This write resets the card */ target[0xC0000]=0; if (ei_debug > 1) printk("reset complete\n"); return;}/* * Daynaport code (some is used by other drivers) *//* Grab the 8390 specific header. Similar to the block_input routine, but we don't need to be concerned with ring wrap as the header will be at the start of a page, so we optimize accordingly. *//* Block input and output are easy on shared memory ethercards, and trivial on the Daynaport card where there is no choice of how to do it. The only complications are that the ring buffer wraps.*/static void dayna_cpu_memcpy(struct device *dev, void *to, int from, int count){ volatile unsigned short *ptr; unsigned short *target=to; from<<=1; /* word, skip overhead */ ptr=(unsigned short *)(dev->mem_start+from); while(count>=2) { *target++=*ptr++; /* Copy and */ ptr++; /* Cruft and */ count-=2; } /* * Trailing byte ? */ if(count) { /* Big endian */ unsigned short v=*ptr; *((char *)target)=v>>8; }}static void cpu_dayna_memcpy(struct device *dev, int to, const void *from, int count){ volatile unsigned short *ptr; const unsigned short *src=from; to<<=1; /* word, skip overhead */ ptr=(unsigned short *)(dev->mem_start+to); while(count>=2) { *ptr++=*src++; /* Copy and */ ptr++; /* Cruft and */ count-=2; } /* * Trailing byte ? */ if(count) { /* Big endian */ unsigned short v=*src; *((char *)ptr)=v>>8; }}static void dayna_get_8390_hdr(struct device *dev, struct e8390_pkt_hdr *hdr, int ring_page){ unsigned long hdr_start = (ring_page - WD_START_PG)<<8; dayna_cpu_memcpy(dev, (void *)hdr, hdr_start, 4); /* Register endianism - fix here rather than 8390.c */ hdr->count=(hdr->count&0xFF)<<8|(hdr->count>>8);}static void dayna_block_input(struct device *dev, int count, struct sk_buff *skb, int ring_offset){ unsigned long xfer_base = ring_offset - (WD_START_PG<<8); unsigned long xfer_start = xfer_base+dev->mem_start; /* * Note the offset maths is done in card memory space which * is word per long onto our space. */ if (xfer_start + count > dev->rmem_end) { /* We must wrap the input move. */ int semi_count = dev->rmem_end - xfer_start; dayna_cpu_memcpy(dev, skb->data, xfer_base, semi_count); count -= semi_count; dayna_cpu_memcpy(dev, skb->data + semi_count, dev->rmem_start - dev->mem_start, count); } else { dayna_cpu_memcpy(dev, skb->data, xfer_base, count); }}static void dayna_block_output(struct device *dev, int count, const unsigned char *buf, int start_page){ long shmem = (start_page - WD_START_PG)<<8; cpu_dayna_memcpy(dev, shmem, buf, count);}/* * Cards with full width memory */static void sane_get_8390_hdr(struct device *dev, struct e8390_pkt_hdr *hdr, int ring_page){ unsigned long hdr_start = (ring_page - WD_START_PG)<<8; memcpy((void *)hdr, (char *)dev->mem_start+hdr_start, 4); /* Register endianism - fix here rather than 8390.c */ hdr->count=(hdr->count&0xFF)<<8|(hdr->count>>8);}static void sane_block_input(struct device *dev, int count, struct sk_buff *skb, int ring_offset){ unsigned long xfer_base = ring_offset - (WD_START_PG<<8); unsigned long xfer_start = xfer_base+dev->mem_start; if (xfer_start + count > dev->rmem_end) { /* We must wrap the input move. */ int semi_count = dev->rmem_end - xfer_start; memcpy(skb->data, (char *)dev->mem_start+xfer_base, semi_count); count -= semi_count; memcpy(skb->data + semi_count, (char *)dev->rmem_start, count); } else { memcpy(skb->data, (char *)dev->mem_start+xfer_base, count); }}static void sane_block_output(struct device *dev, int count, const unsigned char *buf, int start_page){ long shmem = (start_page - WD_START_PG)<<8; memcpy((char *)dev->mem_start+shmem, buf, count);}static void word_memcpy_tocard(void *tp, const void *fp, int count){ volatile unsigned short *to = tp; const unsigned short *from = fp; count++; count/=2; while(count--) *to++=*from++;}static void word_memcpy_fromcard(void *tp, const void *fp, int count){ unsigned short *to = tp; const volatile unsigned short *from = fp; count++; count/=2; while(count--) *to++=*from++;}static void slow_sane_get_8390_hdr(struct device *dev, struct e8390_pkt_hdr *hdr, int ring_page){ unsigned long hdr_start = (ring_page - WD_START_PG)<<8; word_memcpy_fromcard((void *)hdr, (char *)dev->mem_start+hdr_start, 4); /* Register endianism - fix here rather than 8390.c */ hdr->count=(hdr->count&0xFF)<<8|(hdr->count>>8);}static void slow_sane_block_input(struct device *dev, int count, struct sk_buff *skb, int ring_offset){ unsigned long xfer_base = ring_offset - (WD_START_PG<<8); unsigned long xfer_start = xfer_base+dev->mem_start; if (xfer_start + count > dev->rmem_end) { /* We must wrap the input move. */ int semi_count = dev->rmem_end - xfer_start; word_memcpy_fromcard(skb->data, (char *)dev->mem_start+xfer_base, semi_count); count -= semi_count; word_memcpy_fromcard(skb->data + semi_count, (char *)dev->rmem_start, count); } else { word_memcpy_fromcard(skb->data, (char *)dev->mem_start+xfer_base, count); }}static void slow_sane_block_output(struct device *dev, int count, const unsigned char *buf, int start_page){ long shmem = (start_page - WD_START_PG)<<8; word_memcpy_tocard((char *)dev->mem_start+shmem, buf, count);#if 0 long shmem = (start_page - WD_START_PG)<<8; volatile unsigned short *to=(unsigned short *)(dev->mem_start+shmem); volatile int p; unsigned short *bp=(unsigned short *)buf; count=(count+1)/2; while(count--) { *to++=*bp++; for(p=0;p<10;p++) p++; }#endif }/* * Local variables: * compile-command: "gcc -D__KERNEL__ -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O6 -m486 -c daynaport.c" * version-control: t * tab-width: 4 * kept-new-versions: 5 * End: */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -