📄 ewrk3.c
字号:
} else if (j) break; } return i;}/* ** Read the EWRK3 EEPROM using this routine */static int Read_EEPROM(u_long iobase, u_char eaddr){ int i; outb((eaddr & 0x3f), EWRK3_PIR1); /* set up 6 bits of address info */ outb(EEPROM_RD, EWRK3_IOPR); /* issue read command */ for (i = 0; i < 5000; i++) inb(EWRK3_CSR); /* wait 1msec */ return inw(EWRK3_EPROM1); /* 16 bits data return */}/* ** Write the EWRK3 EEPROM using this routine */static int Write_EEPROM(short data, u_long iobase, u_char eaddr){ int i; outb(EEPROM_WR_EN, EWRK3_IOPR); /* issue write enable command */ for (i = 0; i < 5000; i++) inb(EWRK3_CSR); /* wait 1msec */ outw(data, EWRK3_EPROM1); /* write data to register */ outb((eaddr & 0x3f), EWRK3_PIR1); /* set up 6 bits of address info */ outb(EEPROM_WR, EWRK3_IOPR); /* issue write command */ for (i = 0; i < 75000; i++) inb(EWRK3_CSR); /* wait 15msec */ outb(EEPROM_WR_DIS, EWRK3_IOPR); /* issue write disable command */ for (i = 0; i < 5000; i++) inb(EWRK3_CSR); /* wait 1msec */ return 0;}/* ** Look for a particular board name in the on-board EEPROM. */static void __init EthwrkSignature(char *name, char *eeprom_image){ u_long i, j, k; char *signatures[] = EWRK3_SIGNATURE; strcpy(name, ""); for (i = 0; *signatures[i] != '\0' && *name == '\0'; i++) { for (j = EEPROM_PNAME7, k = 0; j <= EEPROM_PNAME0 && k < strlen(signatures[i]); j++) { if (signatures[i][k] == eeprom_image[j]) { /* track signature */ k++; } else { /* lost signature; begin search again */ k = 0; } } if (k == strlen(signatures[i])) { for (k = 0; k < EWRK3_STRLEN; k++) { name[k] = eeprom_image[EEPROM_PNAME7 + k]; name[EWRK3_STRLEN] = '\0'; } } } return; /* return the device name string */}/* ** Look for a special sequence in the Ethernet station address PROM that ** is common across all EWRK3 products. ** ** Search the Ethernet address ROM for the signature. Since the ROM address ** counter can start at an arbitrary point, the search must include the entire ** probe sequence length plus the (length_of_the_signature - 1). ** Stop the search IMMEDIATELY after the signature is found so that the ** PROM address counter is correctly positioned at the start of the ** ethernet address for later read out. */static int __init DevicePresent(u_long iobase){ union { struct { u32 a; u32 b; } llsig; char Sig[sizeof(u32) << 1]; } dev; short sigLength; char data; int i, j, status = 0; dev.llsig.a = ETH_PROM_SIG; dev.llsig.b = ETH_PROM_SIG; sigLength = sizeof(u32) << 1; for (i = 0, j = 0; j < sigLength && i < PROBE_LENGTH + sigLength - 1; i++) { data = inb(EWRK3_APROM); if (dev.Sig[j] == data) { /* track signature */ j++; } else { /* lost signature; begin search again */ if (data == dev.Sig[0]) { j = 1; } else { j = 0; } } } if (j != sigLength) { status = -ENODEV; /* search failed */ } return status;}static u_char __init get_hw_addr(struct net_device *dev, u_char * eeprom_image, char chipType){ int i, j, k; u_short chksum; u_char crc, lfsr, sd, status = 0; u_long iobase = dev->base_addr; u16 tmp; if (chipType == LeMAC2) { for (crc = 0x6a, j = 0; j < ETH_ALEN; j++) { sd = dev->dev_addr[j] = eeprom_image[EEPROM_PADDR0 + j]; outb(dev->dev_addr[j], EWRK3_PAR0 + j); for (k = 0; k < 8; k++, sd >>= 1) { lfsr = ((((crc & 0x02) >> 1) ^ (crc & 0x01)) ^ (sd & 0x01)) << 7; crc = (crc >> 1) + lfsr; } } if (crc != eeprom_image[EEPROM_PA_CRC]) status = -1; } else { for (i = 0, k = 0; i < ETH_ALEN;) { k <<= 1; if (k > 0xffff) k -= 0xffff; k += (u_char) (tmp = inb(EWRK3_APROM)); dev->dev_addr[i] = (u_char) tmp; outb(dev->dev_addr[i], EWRK3_PAR0 + i); i++; k += (u_short) ((tmp = inb(EWRK3_APROM)) << 8); dev->dev_addr[i] = (u_char) tmp; outb(dev->dev_addr[i], EWRK3_PAR0 + i); i++; if (k > 0xffff) k -= 0xffff; } if (k == 0xffff) k = 0; chksum = inb(EWRK3_APROM); chksum |= (inb(EWRK3_APROM) << 8); if (k != chksum) status = -1; } return status;}/* ** Look for a particular board name in the EISA configuration space */static int __init EISA_signature(char *name, s32 eisa_id){ u_long i; char *signatures[] = EWRK3_SIGNATURE; char ManCode[EWRK3_STRLEN]; union { s32 ID; char Id[4]; } Eisa; int status = 0; *name = '\0'; for (i = 0; i < 4; i++) { Eisa.Id[i] = inb(eisa_id + i); } ManCode[0] = (((Eisa.Id[0] >> 2) & 0x1f) + 0x40); ManCode[1] = (((Eisa.Id[1] & 0xe0) >> 5) + ((Eisa.Id[0] & 0x03) << 3) + 0x40); ManCode[2] = (((Eisa.Id[2] >> 4) & 0x0f) + 0x30); ManCode[3] = ((Eisa.Id[2] & 0x0f) + 0x30); ManCode[4] = (((Eisa.Id[3] >> 4) & 0x0f) + 0x30); ManCode[5] = '\0'; for (i = 0; (*signatures[i] != '\0') && (*name == '\0'); i++) { if (strstr(ManCode, signatures[i]) != NULL) { strcpy(name, ManCode); status = 1; } } return status; /* return the device name string */}/* ** Perform IOCTL call functions here. Some are privileged operations and the ** effective uid is checked in those cases. */static int ewrk3_ioctl(struct net_device *dev, struct ifreq *rq, int cmd){ struct ewrk3_private *lp = (struct ewrk3_private *) dev->priv; struct ewrk3_ioctl *ioc = (struct ewrk3_ioctl *) &rq->ifr_data; u_long iobase = dev->base_addr; int i, j, status = 0; u_char csr; union ewrk3_addr { u_char addr[HASH_TABLE_LEN * ETH_ALEN]; u_short val[(HASH_TABLE_LEN * ETH_ALEN) >> 1]; }; union ewrk3_addr *tmp; tmp = kmalloc(sizeof(union ewrk3_addr), GFP_KERNEL); if(tmp==NULL) return -ENOMEM; switch (ioc->cmd) { case EWRK3_GET_HWADDR: /* Get the hardware address */ for (i = 0; i < ETH_ALEN; i++) { tmp->addr[i] = dev->dev_addr[i]; } ioc->len = ETH_ALEN; if (copy_to_user(ioc->data, tmp->addr, ioc->len)) status = -EFAULT; break; case EWRK3_SET_HWADDR: /* Set the hardware address */ if (capable(CAP_NET_ADMIN)) { csr = inb(EWRK3_CSR); csr |= (CSR_TXD | CSR_RXD); outb(csr, EWRK3_CSR); /* Disable the TX and RX */ if (copy_from_user(tmp->addr, ioc->data, ETH_ALEN)) { status = -EFAULT; break; } for (i = 0; i < ETH_ALEN; i++) { dev->dev_addr[i] = tmp->addr[i]; outb(tmp->addr[i], EWRK3_PAR0 + i); } csr &= ~(CSR_TXD | CSR_RXD); /* Enable the TX and RX */ outb(csr, EWRK3_CSR); } else { status = -EPERM; } break; case EWRK3_SET_PROM: /* Set Promiscuous Mode */ if (capable(CAP_NET_ADMIN)) { csr = inb(EWRK3_CSR); csr |= CSR_PME; csr &= ~CSR_MCE; outb(csr, EWRK3_CSR); } else { status = -EPERM; } break; case EWRK3_CLR_PROM: /* Clear Promiscuous Mode */ if (capable(CAP_NET_ADMIN)) { csr = inb(EWRK3_CSR); csr &= ~CSR_PME; outb(csr, EWRK3_CSR); } else { status = -EPERM; } break; case EWRK3_GET_MCA: /* Get the multicast address table */ spin_lock_irq(&lp->hw_lock); if (lp->shmem_length == IO_ONLY) { outb(0, EWRK3_IOPR); outw(PAGE0_HTE, EWRK3_PIR1); for (i = 0; i < (HASH_TABLE_LEN >> 3); i++) { tmp->addr[i] = inb(EWRK3_DATA); } } else { outb(0, EWRK3_MPR); isa_memcpy_fromio(tmp->addr, lp->shmem_base + PAGE0_HTE, (HASH_TABLE_LEN >> 3)); } spin_unlock_irq(&lp->hw_lock); ioc->len = (HASH_TABLE_LEN >> 3); if (copy_to_user(ioc->data, tmp->addr, ioc->len)) status = -EFAULT; break; case EWRK3_SET_MCA: /* Set a multicast address */ if (capable(CAP_NET_ADMIN)) { if (copy_from_user(tmp->addr, ioc->data, ETH_ALEN * ioc->len)) { status = -EFAULT; break; } set_multicast_list(dev); } else { status = -EPERM; } break; case EWRK3_CLR_MCA: /* Clear all multicast addresses */ if (capable(CAP_NET_ADMIN)) { set_multicast_list(dev); } else { status = -EPERM; } break; case EWRK3_MCA_EN: /* Enable multicast addressing */ if (capable(CAP_NET_ADMIN)) { csr = inb(EWRK3_CSR); csr |= CSR_MCE; csr &= ~CSR_PME; outb(csr, EWRK3_CSR); } else { status = -EPERM; } break; case EWRK3_GET_STATS: /* Get the driver statistics */ cli(); ioc->len = sizeof(lp->pktStats); if (copy_to_user(ioc->data, &lp->pktStats, ioc->len)) status = -EFAULT; sti(); break; case EWRK3_CLR_STATS: /* Zero out the driver statistics */ if (capable(CAP_NET_ADMIN)) { cli(); memset(&lp->pktStats, 0, sizeof(lp->pktStats)); sti(); } else { status = -EPERM; } break; case EWRK3_GET_CSR: /* Get the CSR Register contents */ tmp->addr[0] = inb(EWRK3_CSR); ioc->len = 1; if (copy_to_user(ioc->data, tmp->addr, ioc->len)) status = -EFAULT; break; case EWRK3_SET_CSR: /* Set the CSR Register contents */ if (capable(CAP_NET_ADMIN)) { if (copy_from_user(tmp->addr, ioc->data, 1)) { status = -EFAULT; break; } outb(tmp->addr[0], EWRK3_CSR); } else { status = -EPERM; } break; case EWRK3_GET_EEPROM: /* Get the EEPROM contents */ if (capable(CAP_NET_ADMIN)) { for (i = 0; i < (EEPROM_MAX >> 1); i++) { tmp->val[i] = (short) Read_EEPROM(iobase, i); } i = EEPROM_MAX; tmp->addr[i++] = inb(EWRK3_CMR); /* Config/Management Reg. */ for (j = 0; j < ETH_ALEN; j++) { tmp->addr[i++] = inb(EWRK3_PAR0 + j); } ioc->len = EEPROM_MAX + 1 + ETH_ALEN; if (copy_to_user(ioc->data, tmp->addr, ioc->len)) status = -EFAULT; } else { status = -EPERM; } break; case EWRK3_SET_EEPROM: /* Set the EEPROM contents */ if (capable(CAP_NET_ADMIN)) { if (copy_from_user(tmp->addr, ioc->data, EEPROM_MAX)) { status = -EFAULT; break; } for (i = 0; i < (EEPROM_MAX >> 1); i++) { Write_EEPROM(tmp->val[i], iobase, i); } } else { status = -EPERM; } break; case EWRK3_GET_CMR: /* Get the CMR Register contents */ tmp->addr[0] = inb(EWRK3_CMR); ioc->len = 1; if (copy_to_user(ioc->data, tmp->addr, ioc->len)) status = -EFAULT; break; case EWRK3_SET_TX_CUT_THRU: /* Set TX cut through mode */ if (capable(CAP_NET_ADMIN)) { lp->txc = 1; } else { status = -EPERM; } break; case EWRK3_CLR_TX_CUT_THRU: /* Clear TX cut through mode */ if (capable(CAP_NET_ADMIN)) { lp->txc = 0; } else { status = -EPERM; } break; default: status = -EOPNOTSUPP; } kfree(tmp); return status;}#ifdef MODULEstatic struct net_device thisEthwrk;static int io = 0x300; /* <--- EDIT THESE LINES FOR YOUR CONFIGURATION */static int irq = 5; /* or use the insmod io= irq= options */MODULE_PARM(io, "i");MODULE_PARM(irq, "i");MODULE_PARM_DESC(io, "EtherWORKS 3 I/O base address");MODULE_PARM_DESC(irq, "EtherWORKS 3 IRQ number");int init_module(void){ thisEthwrk.base_addr = io; thisEthwrk.irq = irq; thisEthwrk.init = ewrk3_probe; if (register_netdev(&thisEthwrk) != 0) return -EIO; return 0;}void cleanup_module(void){ unregister_netdev(&thisEthwrk); if (thisEthwrk.priv) { kfree(thisEthwrk.priv); thisEthwrk.priv = NULL; } thisEthwrk.irq = 0; release_region(thisEthwrk.base_addr, EWRK3_TOTAL_SIZE);}#endif /* MODULE */MODULE_LICENSE("GPL");/* * Local variables: * compile-command: "gcc -D__KERNEL__ -I/linux/include -Wall -Wstrict-prototypes -fomit-frame-pointer -fno-strength-reduce -malign-loops=2 -malign-jumps=2 -malign-functions=2 -O2 -m486 -c ewrk3.c" * * compile-command: "gcc -D__KERNEL__ -DMODULE -I/linux/include -Wall -Wstrict-prototypes -fomit-frame-pointer -fno-strength-reduce -malign-loops=2 -malign-jumps=2 -malign-functions=2 -O2 -m486 -c ewrk3.c" * End: */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -